MySQL Group Relication是MySQL 5.7.17发布的一个重要的功能。 Group Replication组复制是MySQL的一个插件,可以让多个MySQL节点中的数据保持一致。 其中一个节点的数据被修改后,剩余节点会自动同步。

组复制与MySQL主从复制的区别

在组复制之前,MySQL还支持异步复制(Asynchronous Replication)、半同步复制(Semisynchronous Replication)两种复制模式:

  • 异步复制:这是MySQL最早支持的复制模式,提供最基本的主从复制,可以支持一个主库和多个从库之间的复制,主库更新执行之后,基于binlog这些操作会在从库上重新执行(支持STATEMENT,ROW,MIXED三种方式)。主库不需要保证从库接收并执行了binlog,因此是异步的,主从之间数据会有一定的延迟。在对外不停止服务的前提下,如果主库宕机,提升从库为新的主库,有可能丢失数据,出现数据不一致。
  • 半同步复制:MySQL5.5开始以插件形式实现了半同步复制方案,需要在Master和Savle上安装semisync_master.so和semisync_slave.so插件。半同步复制在异步复制的基础上增加了一个同步过程:在从库接收到主库的更新操作时,会通知主库,主库需要接收来自从库的ack。基本原理是:主库提交事务的线程会被锁定,直到至少一个从库收到这个事务。半同步复制只是能保证从库收到了binlog,但并不保证从库执行了事务,可以结合MHA(Master High Availability),如果master宕机,salve可以在apply所有的relay log后切换成master。 半同步复制的优点是更大程度的保证了数据的一致性;缺点是在性能有所下降,而且 如果异常发生,会降级为异步复制模式。

异步复制和半同步复制,都是一个master对应一个或多个slave,都存在延迟,而且如果master出现故障,那么有可能会出现数据不一致和数据丢失的问题,这在有些业务场景下是不能接受的。MySQL 5.7.17的组复制模式似乎就是为这个问题而生的。

组复制通过分布式一致性算法Paxos来实现各节点状态的高一致性,一个组内允许部分节点挂掉,因此提供了容错性,只要大多数节点都OK的话,对外服务是OK的。在组复制模式下,节点的新增和移除都是自动的。

当前组复制支持如下两种模式:

  • 单master模式:自动选举master,所有更新操作在master上进行
  • 多mastere模式: 所有server都是master,可以同时处理更新操作

试验Group Replication

在简单理解了一下组复制之后,下面通过实验体验一下MySQL 5.7.17的组复制。

现在每台机器上编译安装mysql。

试验环境

  • 192.168.61.21 db1
  • 192.168.61.22 db2
  • 192.168.61.23 db3

/etc/hosts

1192.168.61.21 db1
2192.168.61.22 db2
3192.168.61.23 db3

编译安装mysql

下载源码:

1wget https://cdn.mysql.com//Downloads/MySQL-5.7/mysql-5.7.17.tar.gz
2tar -zxvf mysql-5.7.17.tar.gz
3
4wget http://sourceforge.net/projects/boost/files/boost/1.59.0/boost_1_59_0.tar.gz
5tar -zxvf boost_1_59_0.tar.gz

创建mysql用户:

1groupadd mysql
2useradd -g mysql -d /var/lib/mysql -s /sbin/nologin mysql

编译安装:

 1yum install -y make cmake ncurses-devel libtool zlib-devel gcc gcc-c++ bison
 2
 3mkdir /usr/local/mysql
 4mkdir /var/log/mysql
 5chown mysql:mysql /var/log/mysql/
 6
 7cd mysql-5.7.17
 8
 9cmake . -DCMAKE_INSTALL_PREFIX=/usr/local/mysql \
10-DMYSQL_DATADIR=/var/lib/mysql \
11-DSYSCONFDIR=/etc \
12-DDOWNLOAD_BOOST=1 \
13-DWITH_BOOST=/root/boost_1_59_0
14
15make
16
17make install

mysql配置文件:

1rm -f /etc/my.cnf
2cd /usr/local/mysql
3cp ./support-files/my-default.cnf /etc/my.cnf

修改/etc/my.cnf:

 1[mysqld]
 2basedir=/usr/local/mysql
 3datadir=/var/lib/mysql
 4
 5server_id = 1 #各节点分别指定1,2,3
 6character-set-server=utf8mb4
 7collation-server=utf8mb4_unicode_ci
 8default-storage-engine=INNODB
 9#Optimize omit
10sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
11log-bin     = binlog
12log_bin_trust_function_creators=1
13binlog_format = ROW
14expire_logs_days = 99
15sync_binlog = 0
16slow-query-log=1
17slow-query-log-file=/var/log/mysql/slow-queries.log
18long_query_time = 3
19log-queries-not-using-indexes

初始化mysql实例:

1/usr/local/mysql/bin/mysqld --initialize \
2--user=mysql \
3--basedir=/usr/local/mysql \
4--datadir=/var/lib/mysql

上面的命令会生成mysql root用户的密码,记录一下。

mysql启动脚本:

1cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
2sed -i 's#^basedir=#basedir='/usr/local/mysql'#' /etc/init.d/mysqld
3sed -i 's#^datadir=#datadir='/var/lib/mysql'#' /etc/init.d/mysqld
4
5chmod 755 /etc/init.d/mysqld
6chkconfig mysqld on
7
8echo "export PATH=\$PATH:/usr/local/mysql/bin" >> /etc/profile
9source /etc/profile

启动mysql:

1service mysqld start

使用之前生成的随机密码登陆,修改mysql root用户密码。

1mysql -uroot -p
2
3SET PASSWORD = PASSWORD('newpassword');

多主组复制配置

各节点上创建repl复制用户:

1GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.%' IDENTIFIED BY 'repl';
2flush privileges;

修改各个节点上的/etc/my.cnf:

 1[mysqld]
 2......
 3log-bin     = binlog
 4log_bin_trust_function_creators=1
 5binlog_format = ROW
 6expire_logs_days = 99
 7
 8relay-log=db1-relay-bin  #针对各个节点指定
 9
10gtid_mode=ON
11enforce_gtid_consistency=ON
12master_info_repository=TABLE
13relay_log_info_repository=TABLE
14relay_log_recovery=ON
15binlog_checksum=NONE
16log_slave_updates=ON
17
18plugin-load=group_replication.so
19transaction_write_set_extraction = XXHASH64
20loose-group_replication_group_name = "c7edeea5-ff2d-11e6-a6c7-0800279704c8" #组id,可select uuid();生成
21
22loose-group_replication_start_on_boot = off
23loose-group_replication_local_address = "db1:13306"  #针对各个节点指定
24loose-group_replication_group_seeds = "db1:13306,db2:13306,db3:13306"
25loose-group_replication_bootstrap_group= off
26loose-group_replication_single_primary_mode=FALSE
27loose-group_replication_enforce_update_everywhere_checks= TRUE
28
29group_replication_allow_local_disjoint_gtids_join
30group-replication-auto-increment-increment=3
31......

其中loose-group_replication_local_address中分别指定当前机器的地址以及GR监听的端口,该端口独立于MySQL默认3306的端口。 group-replication-auto-increment-increment是组复制时自增列的步长,默认值为7,这里三个节点,设置为3。另外需要注意auto_increment_offset的值默认是server_id

各个节点上重启mysqld,使配置生效。

开启复制

在db1上开启复制:

1CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='repl' FOR CHANNEL 'group_replication_recovery';
2SET GLOBAL group_replication_bootstrap_group=ON;
3START GROUP_REPLICATION;
4SET GLOBAL group_replication_bootstrap_group=OFF;

在db2和db3上开启复制:

1CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='repl' FOR CHANNEL 'group_replication_recovery';
2START GROUP_REPLICATION;

查看集群状态:

 1 SELECT * FROM performance_schema.replication_group_members\G
 2*************************** 1. row ***************************
 3CHANNEL_NAME: group_replication_applier
 4   MEMBER_ID: 1b5e2aeb-ff60-11e6-a122-0800279704c8
 5 MEMBER_HOST: db2
 6 MEMBER_PORT: 3306
 7MEMBER_STATE: ONLINE
 8*************************** 2. row ***************************
 9CHANNEL_NAME: group_replication_applier
10   MEMBER_ID: 8b180cc7-ff1d-11e6-a970-0800279704c8
11 MEMBER_HOST: db3
12 MEMBER_PORT: 3306
13MEMBER_STATE: ONLINE
14*************************** 3. row ***************************
15CHANNEL_NAME: group_replication_applier
16   MEMBER_ID: bf19bf76-ff5f-11e6-94ff-0800279704c8
17 MEMBER_HOST: db1
18 MEMBER_PORT: 3306
19MEMBER_STATE: ONLINE
203 rows in set (0.00 sec)

MySQL GR已经部署完成,下面就可以在一个节点上建库建表写入数据,在其他节点上查看复制是否生效。

参考