MySQL Group Replication(MGR)是自MySQL 5.7.17版本引入的一个服务器插件,可用于创建高可用、可扩展、容错的复制拓扑结构。
组复制可以在单主模式下操作,其中只有一个服务器接受更新,这个单主是系统自动选举出来的。对于高级用户,也可以部署为多主模式,其中所有服务器都可以接受更新。
MGR对属于同一组的服务器自动进行协调,对于要提交的事务,组成员必须就全局事务序列中给定事务的顺序达成一致。提交或回滚事务由每个服务器单独完成,但所有服务器都必须做出相同的决定。如果存在网络分区,导致成员无法达成事先定义的分割策略,则在解决此问题之前系统不会继续进行,这是一种内置的自动裂脑保护机制。
MGR由组通信系统(Group Communication System,GCS)协议支持,该系统提供故障检测机制、组成员服务以及安全且有序的消息传递。所有这些属性都是创建系统的关键,可确保在服务器组中一致地复制数据。该技术的核心是Paxos算法的实现,它充当组通信引擎。
使用场景
- 弹性复制。服务器的数量能够动态增加或减少,并且尽可能减小副作用,例如云数据库服务。
- 高可用分片。分片是实现写扩展的流行方法,MGR实现高可用分片,其中每个分片映射到复制组。
- 主从复制的替代方案。某些情况下,使用单个主服务器会使其成为热点,写入整组更具可扩展性。
基本条件
- 必须使用InnoDB存储引擎。
- 每个数据表都必须有主键。
系统环境
本人测试环境的操作系统采用CentOS7.9,mysql版本为8.0.23,对应的mysql-shell和mysql-router均为8.0.23。
主机名 | 主机IP | 应用集 |
mysql-cluster-router-1 | 10.10.200.201 | mysql, mysql-router, mysql-shell |
mysql-cluster-router-2 | 10.10.200.202 | mysql, mysql-router |
mysql-cluster-router-3 | 10.10.200.203 | mysql, mysql-router |
建议mysql-server和mysql-router部署在一起,mysql-shell可以创建新服务器单独部署。
设置防火墙
# 设置selinux setenforce 0 sed -i '/^SELINUX/s/enforcing/disabled/g' /etc/selinux/config # 如果不能禁用selinux,须安装semanage # yum install -y policycoreutils-python-utils # 放行组复制通信端口33061 # semanage port -a -t mysqld_port_t -p tcp 33061 # 设置seboolean # setsebool -P mysql_connect_any=ON # 设置firewalld # 禁用firewalld,或者放行mysql端口,一般选择放行端口 firewall-cmd --permanent --zone=public --add-port=3306/tcp firewall-cmd --permanent --zone=public --add-port=3316/tcp firewall-cmd --permanent --zone=public --add-port=3326/tcp firewall-cmd --permanent --zone=public --add-port=33061/tcp firewall-cmd --reload
安装MySQL8
配置yum源(Redhat7/CentOS7),修改/etc/yum.repos.d/mysql-community.repo:
[mysql80-community] name=MySQL 8.0 Community Server baseurl=http://repo.mysql.com/yum/mysql-8.0-community/el/7/$basearch/ enabled=1 gpgcheck=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql
安装MySQL8
yum clean all yum makecache yum install mysql-community-server
离线安装方法可参照MySQL5.7升级至MySQL8.0详细步骤中的相关内容。
配置MySQL8
# 先通过以下命令生成组ID,备用 uuidgen # 生成的uuid:2e5cc2a4-13f8-441f-a25d-cb6f53e14da9
修改配置文件/etc/my.cnf:
[mysqld] datadir = /var/lib/mysql socket = /var/lib/mysql/mysql.sock log-error = /var/log/mysqld.log pid-file = /var/run/mysqld/mysqld.pid # 本配置文件中的部分参数并非唯一,请根据实际需求调整 # 设置时区和字符集 default-time_zone = '+8:00' character-set-server = utf8mb4 collation-server = utf8mb4_general_ci skip-character-set-client-handshake # 设置默认的密码认证方式 default-authentication-plugin = mysql_native_password # 设置数据库引擎 disabled_storage_engines = "MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY" sql_mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION # 集群相关设置 # 另外两台mysql的server_id分别是202和203 server_id = 201 gtid_mode = ON enforce_gtid_consistency = 1 master_info_repository = TABLE relay_log_info_repository = TABLE binlog_checksum = NONE log_slave_updates = ON # 开启binlog日志 log-bin = mysql-bin binlog_format = ROW max_binlog_size = 1G binlog_cache_size = 8M max_binlog_cache_size = 256M # 需要创建目录/var/lib/mysql/bin-log relay-log = /var/lib/mysql/bin-log/relay-log relay-log-index = /var/lib/mysql/bin-log/relay-log-index binlog_transaction_dependency_tracking = WRITESET slave_parallel_type = LOGICAL_CLOCK slave_preserve_commit_order = ON slow_query_log = ON slow_query_log_file = /var/log/mysql/mysqld-slow.log long_query_time = 5 log_queries_not_using_indexes = OFF # 禁用域名访问 skip-name-resolve report-host = '10.10.200.201' # 组复制基本配置 transaction_write_set_extraction = XXHASH64 loose-group_replication_group_name = "2e5cc2a4-13f8-441f-a25d-cb6f53e14da9" # 集群启动后立即复制 loose-group_replication_start_on_boot = ON # 另外两台mysql的loose-group_replication_local_address分别改为各自的IP loose-group_replication_local_address = "10.10.200.201:33061" loose-group_replication_group_seeds = "10.10.200.201:33061,10.10.200.202:33061,10.10.200.203:33061" loose-group_replication_bootstrap_group = OFF loose-group_replication_ip_whitelist = "10.10.200.0/24" # 启用单一主节点模式,多主易脑裂 loose-group_replication_single_primary_mode = ON loose-group_replication_enforce_update_everywhere_checks = OFF
初始化mysql:
# 创建bin-log日志目录: mkdir -p /var/lib/mysql/bin-log # 启动mysql systemctl start mysqld # 获取初始密码 grep "temporary password" /var/log/mysqld.log # 登录mysql mysql -uroot -p
配置MySQL复制账号:
set sql_log_bin=0; ALTER USER 'root'@'localhost' IDENTIFIED BY 'PASSword_123'; CREATE USER 'mycluster'@'%' identified by 'MyCluster_123'; grant all privileges on *.* to 'mycluster'@'%' with grant option; flush privileges; quit
安装MySQL-Shell
访问MySQL-Shell下载页面获取对应版本的mysql-shell,以8.0.23版本为例:
wget https://dev.mysql.com/get/Downloads/MySQL-Shell/mysql-shell-8.0.23-1.el7.x86_64.rpm yum -y localinstall mysql-shell-8.0.23-1.el7.x86_64.rpm
配置集群
在任意一台安装了mysql-shell的主机上执行集群配置操作即可。
mysqlsh --log-level=DEBUG3 # 检查节点配置状态 dba.checkInstanceConfiguration('mycluster@10.10.200.201:3306'); dba.checkInstanceConfiguration('mycluster@10.10.200.202:3306'); dba.checkInstanceConfiguration('mycluster@10.10.200.203:3306'); # 配置节点 dba.configureLocalInstance('mycluster@10.10.200.201'); dba.configureLocalInstance('mycluster@10.10.200.202'); dba.configureLocalInstance('mycluster@10.10.200.203'); # 创建集群 shell.connect('mycluster@10.10.200.201:3306'); var cluster = dba.createCluster('myCluster'); # 将节点加入集群 cluster.addInstance('mycluster@10.10.200.202:3306'); cluster.addInstance('mycluster@10.10.200.203:3306'); # 检查集群状态 cluster.status() cluster.describe(); # 检查节点运行状态 cluster.checkInstanceState('mycluster@10.10.200.201:3306'); cluster.checkInstanceState('mycluster@10.10.200.202:3306'); cluster.checkInstanceState('mycluster@10.10.200.203:3306'); # 退出mysqlsh \q
执行以下SQL语句验证集群:
SELECT * from performance_schema.replication_group_members; SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME = 'group_replication_primary_member';
集群管理常用命令
mysqlsh --log-level=DEBUG3 # 重启集群方法,慎用!!! # 一般在整个集群停宕以后使用,且启动过程很慢 dba.rebootClusterFromCompleteOutage('myCluster'); # 将节点重新加入集群 cluster.rejoinInstance('mycluster@10.10.200.203')
销毁集群
执行以下MySQL-shell命令解散集群:
shell.connect('mycluster@10.10.200.201:3306') var cluster = dba.getCluster('myCluster') cluster.removeInstance('mycluster@10.10.200.202:3306',{force:true}) cluster.removeInstance('mycluster@10.10.200.203:3306',{force:true}) cluster.dissolve({force:true}) dba.dropMetadataSchema();
执行以下SQL语句清理数据:
stop group_replication; reset master; reset slave;
安装MySQL-Router
访问MySQL-Router下载页面获取对应版本的mysql-router,以8.0.23版本为例:
wget https://dev.mysql.com/get/Downloads/MySQL-Router/mysql-router-community-8.0.23-1.el7.x86_64.rpm yum -y localinstall mysql-router-community-8.0.23-1.el7.x86_64.rpm
安装完成后,可以通过以下命令初始化mysql-router:
mysqlrouter --bootstrap cluster@10.10.200.201:3306 --directory /opt/mysqlrouter --conf-use-sockets --force --user=root
不过,我个人还是更习惯手动修改配置文件,修改配置/etc/mysqlrouter/mysqlrouter.conf:
[DEFAULT] logging_folder = /var/log/mysqlrouter runtime_folder = /var/run/mysqlrouter config_folder = /etc/mysqlrouter [logger] level = INFO [keepalive] interval = 60 [routing:myCluster_rw] bind_address = 0.0.0.0 bind_port = 3316 destinations = 10.10.200.201:3306,10.10.200.202:3306,10.10.200.203:3306 routing_strategy = first-available protocol = classic max_connections = 65535 [routing:myCluster_ro] bind_address = 0.0.0.0 bind_port = 3326 destinations = 10.10.200.202:3306,10.10.200.203:3306 routing_strategy = round-robin protocol = classic max_connections = 65535
建议取消以mysqlrouter为启动用户,修改配置/usr/lib/systemd/system/mysqlrouter.service:
[Unit] Description=MySQL Router After=syslog.target After=network.target [Service] Type=simple # 注释以下两行 # User=mysqlrouter # Group=mysqlrouter PIDFile=/var/run/mysqlrouter/mysqlrouter.pid ExecStart=/usr/bin/mysqlrouter -c /etc/mysqlrouter/mysqlrouter.conf PrivateTmp=true [Install] WantedBy=multi-user.target
注意配置防火墙(见本文开篇),完成所有动作后启动服务:
systemctl daemon-reload systemctl enable mysqlrouter systemctl start mysqlrouter
原创文章禁止转载:技术学堂 » MySQL Group Replication组复制单主模式部署方法