一、Percona XtraDB Cluster相关概念及原理:

1、Percona XtraDB Cluster简介:

Percona XtraDB Cluster是基于Galera协议的MySQL高可用集群架构。GaleraCodership提供的多主数据同步复制机制,具有高可用性,方便扩展,可以实现多个MySQL节点间的数据同步复制以及读写,并且可保障数据库的服务高可用及数据一致性。基于Galera的高可用方案主要有MariaDB Galera ClusterPercona XtraDB Cluster(简称PXC)。PXC属于一套近乎完美的MySQL高可用集群解决方案,相比那些传统的基于主从复制模型的集群架构MHAMM+KeepalivedGalera Cluster最突出的特点就是解决了诟病已久的数据复制延迟问题,基本上可以达到实时同步,而且节点与节点之间,它们相互的关系是对等的。本身Galera Cluster也是一种多主架构,如下图所示:

要搭建PXC架构至少需要3MySQL实例来组成一个集群,3个实例之间不是主从模式,而是各自为主,所以三者是对等关系,不分从属,这就叫multi-master架构。客户端写入和读取数据时,连接哪个实例都是一样的,读取到的数据也都是相同的,写入任意一个实例之后,集群自身会将新写入的数据同步到其它实例上,这种架构不共享任何数据,是一种高冗余架构。

2、PXC原理:

PXC最常使用如下4个端口号:

(1)3306:数据库对外服务的端口号

(2)4444:请求SST的端口号

(3)4567:组成员之间进行沟通的端口号

(4)4568:用于传输IST的端口号

备注:

Ø  SSTState Snapshot Transfer,全量数据传输

Ø  ISTIncremental State Transfer,增量数据传输

从上图中可以看出PXC的操作流程,首先客户端发起一个事务,该事务先在本地执行,执行完成后发起对事务的提交操作。在提交之前需要将产生的复制写集广播出去,然后获取到一个全局的事务ID号,一并传送到另一节点上。通过验证合并数据之后,发现没有冲突数据,执行apply_cbcommit_cb操作,否则就需要取消(discard)此次事务的操作。而当前server节点通过验证之后,执行提交操作,并返回OK,如果验证没通过,则执行回滚。当然在生产中至少要有三个节点的集群环境,如果其中有一个节点没有验证通过,出现了数据冲突,那么此时采取的方式就是将出现不一致的节点踢出集群环境,而且它自己会执行shutdown命令,自动关机。

3、PXC架构的优缺点:

(1)优点:

a、实现MySQL集群架构的高可用性和数据强一致性

b、实现真正的多节点读写集群方案

c、改善了传统意义上的主从复制延迟问题,基本上达到了实时同步

d、新加入的节点可以自动部署,无需提供手动备份,维护方便

e、多节点写入,数据库故障切换容易

(2)缺点:

a、只支持InnoDB引擎,其它存储引擎的更改不复制,DDL语句在statement级别被复制,并且对mysql.*表的更改会基于此被复制,例如:CREATE USER...语句会被复制,但INSERT INTO mysql.user...语句则不会被复制,可通过wsrep_replicate_myisam参数开启MyISAM存储引擎的复制,但这只是一个实验性的参数

b、新加入节点采用SST时的代价高

c、存在写扩大问题

d、任何更新事务都需要全局验证通过,才会在每个节点库上执行,集群性能/吞吐量受限于性能最差的节点,也就是经常说的短板效应

e、由于需要保证数据的一致性,所以在多节点并发写时,锁冲突及死锁问题比较严重

f、所有表必须含有主键

g、不支持LOCK TABLE等显式表级别的锁定操作

h、不支持XA

4、PXC中涉及到的重要概念和核心参数:

(1)集群中节点的数量:整个集群中节点数量应该控制在最少3个、最多8个的范围内。最少3个节点是为了防止出现脑裂现象,因为只有在2个节点下才会出现此现象。脑裂现象的标志就是输入任何命令,返回的结果都是unknown command。节点在集群中,会因新节点的加入或故障、同步失效等原因发生状态的切换。

(2)节点状态的变化阶段:

a、open:节点启动成功,尝试连接到集群时的状态

b、primary:节点已处于集群中,在新节点加入并选取donor进行数据同步时的状态

c、joiner:节点处于等待接收同步文件时的状态

d、joined:节点完成数据同步工作,尝试保持和集群进度一致时的状态

e、synced:节点正常提供服务时的状态,表示已经同步完成并和集群进度保持一致

f、donor:节点处于为新加入的节点提供全量数据时的状态

备注:donor节点就是数据的贡献者,如果一个新节点加入集群,此时又需要大量数据的SST数据传输,就有可能因此而拖垮整个集群的性能,所以在生产环境中,如果数据量较小,还可以使用SST全量数据传输,但如果数据量很大就不建议使用这种方式,可以考虑先建立主从关系,然后再加入集群。

(3)节点的数据传输方式:一种叫SST全量数据传输,另一种叫IST增量数据传输。SST数据传输有xtrabackupmysqldumprsync三种方式,而增量数据传输就只有一种方式xtrabackup,但生产环境中一般数据量较小时,可以使用SST全量数据传输,但也只使用xtrabackup方法。

(4)GCache模块:在PXC中一个特别重要的模块,它的核心功能就是为每个节点缓存当前最新的写集。如果有新节点加入进来,就可以把新数据的增量传递给新节点,而不需要再使用SST传输方式,这样可以让节点更快地加入集群中,涉及如下参数:

a、gcache.size:缓存写集增量信息的大小,它的默认大小是128MB,通过wsrep_provider_options参数设置,建议调整为2GB~4GB范围,足够的空间便于缓存更多的增量信息。

b、gcache.mem_sizeGCache中内存缓存的大小,适度调大可以提高整个集群的性能

c、gcache.page_size:如果内存不够用(GCache不足),就直接将写集写入磁盘文件中


二、准备工作(如无特殊说明,3个节点都需要执行如下操作)

1、演示环境:

IP

操作系统

主机名

角色

数据库版本

安装方式

192.168.1.143

CentOS   7.6 x86_64

node1

master1

5.7.25-28-57-log   Percona XtraDB Cluster

yum

192.168.1.144

CentOS   7.6 x86_64

node2

master2

5.7.25-28-57-log   Percona XtraDB Cluster

yum

192.168.1.145

CentOS   7.6 x86_64

node3

master3

5.7.25-28-57-log   Percona XtraDB Cluster

yum

2、关闭SELinuxfirewalld

3、配置epel

4、配置服务器时间同步

5、配置主机名

6、配置/etc/hosts文件:

# vim /etc/hosts

192.168.1.143 node1

192.168.1.144 node2

192.168.1.145 node3


三、yum方式安装配置PXC(如无特殊说明,3个节点都需要执行如下操作)

1、安装percona yum源:# yum -y install https://repo.percona.com/yum/percona-release-latest.noarch.rpm

2、测试percona yum源:# yum list | grep -i percona

3、安装PXC# yum -y install Percona-XtraDB-Cluster-57

备注:安装后生成的比较重要的配置文件

Ø  /etc/percona-xtradb-cluster.conf.d/mysqld.cnf

Ø  /etc/percona-xtradb-cluster.conf.d/mysqld_safe.cnf

Ø  /etc/percona-xtradb-cluster.conf.d/wsrep.cnf

4、创建软链接:

# mv /etc/my.cnf /etc/my.cnf.bak

# update-alternatives --install /etc/my.cnf my.cnf "/etc/percona-xtradb-cluster.cnf" 200

5、master1节点修改mysqld.cnf配置文件:

# vim /etc/percona-xtradb-cluster.conf.d/mysqld.cnf

[mysqld]

server-id=1

datadir=/var/lib/mysql

socket=/var/lib/mysql/mysql.sock

log-error=/var/log/mysqld.log

pid-file=/var/run/mysqld/mysqld.pid

log_bin=mysql-bin

log_bin_index=mysql-bin.index

log_slave_updates

expire_logs_days=7

symbolic-links=0

port=3306

lower_case_table_names=1

character_set_server=utf8mb4

collation_server=utf8mb4_general_ci

innodb_file_per_table=1

skip_name_resolve=1

slow_query_log=1

slow_query_log_file=mysql-slow.log

备注:

Ø  master2节点中的server-id=2master3节点中的server-id=3

Ø  尽管Galera Cluster不再需要通过binlog的形式进行同步,但还是建议在配置文件中开启二进制日志功能,原因是后期如果有新节点需要加入,老节点通过SST全量传输的方式向新节点传输数据,很可能会拖垮集群性能,所以让新节点先通过binlog方式完成同步后再加入集群会是一种更好的选择

6、master1节点修改wsrep.cnf配置文件:

# vim /etc/percona-xtradb-cluster.conf.d/wsrep.cnf

[mysqld]

wsrep_provider=/usr/lib64/galera3/libgalera_smm.so

wsrep_provider_options="gcache.size=2G"

wsrep_cluster_address="gcomm://192.168.1.143,192.168.1.144,192.168.1.145"

binlog_format=ROW

default_storage_engine=InnoDB

wsrep_slave_threads=8

wsrep_log_conflicts

innodb_autoinc_lock_mode=2

wsrep_node_address=192.168.1.143

wsrep_cluster_name=pxc-cluster

wsrep_node_name=node1

pxc_strict_mode=ENFORCING

wsrep_sst_method=xtrabackup-v2

wsrep_sst_auth="sstuser:s3cretPass"

常用配置参数说明:

(1)wsrep_providerGalera库的路径和文件名

(2)wsrep_provider_optionsGalera库的额外参数

(3)wsrep_cluster_address:集群中各节点IP

(4)binlog_format:二进制日志的记录格式

(5)default_storage_engine:默认使用的存储引擎

(6)wsrep_slave_threads:使用的从属线程个数

(7)wsrep_node_address:本节点IP

(8)wsrep_cluster_name:集群名称

(9)wsrep_node_name:本节点在集群中的名称

(10)wsrep_sst_methodSST传输数据的方式,有xtrabackupmysqldumprsync三种,前两者在传输时都需要对donor加全局只读锁(FLUSH TABLES WITH READ LOCK),而xtrabackup则不需要(它使用percona自己提供的backup lock),强烈推荐使用xtrabackup-v2方式

(11)wsrep_sst_auth:在SST传输时需要使用的认证凭据,格式为“用户:密码”

备注:

Ø  master2节点中的wsrep_node_address=192.168.1.144wsrep_node_name=node2

Ø  master3节点中的wsrep_node_address=192.168.1.145wsrep_node_name=node3

7、初始化MySQL数据:# mysqld --initialize --user=mysql

备注:确保初始化前/var/lib/mysql目录为空,初始化完成后会在此目录中生成各类文件

8、master1节点启动MySQL服务:

# systemctl start [email protected]

# ss -tunlp | grep mysqld

# systemctl enable [email protected]

# systemctl status [email protected]

# tail -100 /var/log/mysqld.log

9、master1节点配置MySQL安全向导:

# grep "password" /var/log/mysqld.log --> sIw4lWaqXy+X

# mysql_secure_installation

10、master1节点授权root用户远程登录和创建PXC传输用户sstuser

# mysql -uroot -p

mysql> create user 'root'@'192.168.1.%' identified by '123456';

mysql> grant all on *.* to 'root'@'192.168.1.%';

mysql> flush privileges;

mysql> create user 'sstuser'@'localhost' identified by 's3cretPass';

mysql> grant reload, lock tables, process, replication client on *.* to 'sstuser'@'localhost';

mysql> flush privileges;

备注:之后的MySQL版本将不支持grant授权的同时创建用户,而是需要先创建用户,再进行授权

11、master2master3节点分别启动MySQL服务:

# systemctl start mysql.service

# ss -tunlp | grep mysqld

# systemctl enable mysql.service

# systemctl status mysql.service

# tail -100 /var/log/mysqld.log

备注:master2master3节点无需分别配置MySQL安全向导,也无需分别授权root用户远程登录,已从master1节点处同步

12、查看PXC集群状态:

mysql> show global status like 'wsrep%';

常用PXC集群状态监控指标说明:

(1)wsrep_local_state_uuid:与wsrep_cluster_state_uuid的值一致,且所有节点该值都相同

(2)wsrep_cluster_state_uuid:所有节点该值都相同,如果有不同值的节点,说明该节点没有与集群建立连接

(3)wsrep_last_committed:集群已经提交事务的数量,是一个累计值,所有节点该值都相同,如果出现不一致,说明事务有延迟,可以用来计算延

(4)wsrep_replicated:从本节点复制出去的写集数量,wsrep_replicated_bytes为写集的总字节数,可以用于参考节点间的负载均衡是否平衡,该值较大的节点较为繁忙

(5)wsrep_received:与wsrep_replicated对应,本节点接收来自其它节点的写集数量

(6)wsrep_local_state:所有节点该值都应该为4,表示正常,节点状态有如下6个取值

     a、取值1:节点启动并与集群建立连接

     b、取值2:当节点成功执行状态传输请求时,该节点开始缓存写集

          c、取值3:节点接收了SST全量数据传输,该节点现在拥有所有集群数据,并开始应用已缓存的写集

     d、取值4:节点完成与集群数据的同步,它的从属队列现在是空的,并启用流控使其保持为空

     e、取值5:节点接收了状态传输请求,该节点现在对donor不执行流控,该节点已缓存所有的写集但无法应用

     f、取值6:节点完成对joiner节点的状态传输

(7)wsrep_incoming_addresses:集群中所有节点的IP,且每个节点该值都相同

(8)wsrep_cluster_size:集群中的节点数量,所有节点该值都相同

(9)wsrep_cluster_conf_id:所有节点该值都相同,如果值不同,说明该节点被临时“分区”了

(10)wsrep_cluster_status:集群组成的状态,所有节点该值都为“Primary”,如果该值不为“Primary”,说明该节点出现“分区”或“脑裂”现象

(11)wsrep_connected:所有节点该值都为“ON”,表示本节点已经与集群建立连接

(12)wsrep_ready:所有节点该值都为“ON”,表示本节点可以正常提供服务


四、测试PXC

1、master1节点创建测试数据:

mysql> create database db;

mysql> use db;

mysql> create table tb(id int unsigned auto_increment primary key not null,name char(20) not null);

mysql> desc tb;

mysql> insert into tb(name) values('zhangsan'),('lisi');

mysql> select * from tb;

2、master2master3节点分别查看测试数据:

mysql> show databases;

mysql> use db;

mysql> show tables;

mysql> desc tb;

mysql> select * from tb;

3、master2节点创建测试数据:

mysql> insert into tb(name) values('wangwu'),('zhaoliu');

mysql> select * from tb;

4、master1master3节点分别查看测试数据:

mysql> select * from tb;

5、master3节点创建测试数据:

mysql> insert into tb(name) values('jack'),('tom');

mysql> select * from tb;

6、master1master2节点分别查看测试数据:

mysql> select * from tb;


五、模拟新节点加入PXC

将一个新节点加入PXC集群,需要SST全量数据传输,很有可能拖垮集群整体性能,可以考虑让新节点先成为PXC集群中某个节点(此处以master2节点为例)的从节点,然后在线快速通过IST方式加入集群。

1、演示环境:

IP

操作系统

主机名

角色

数据库版本

安装方式

192.168.1.143

CentOS   7.6 x86_64

node1

master1

5.7.25-28-57-log   Percona XtraDB Cluster

yum

192.168.1.144

CentOS   7.6 x86_64

node2

master2

5.7.25-28-57-log   Percona XtraDB Cluster

yum

192.168.1.145

CentOS   7.6 x86_64

node3

master3

5.7.25-28-57-log   Percona XtraDB Cluster

yum

192.168.1.146

CentOS 7.6 x86_64

node4

slave

5.7.25-28-57-log Percona XtraDB Cluster

yum

2、slave节点关闭SELinuxfirewalld、配置epel源、配置服务器时间同步、配置主机名

3、四个节点配置/etc/hosts文件:

# vim /etc/hosts

192.168.1.143 node1

192.168.1.144 node2

192.168.1.145 node3

192.168.1.146 node4

4、slave节点安装percona yum源:# yum -y install https://repo.percona.com/yum/percona-release-latest.noarch.rpm

5、slave节点安装PXC# yum -y install Percona-XtraDB-Cluster-57

6、slave节点创建软链接:

# mv /etc/my.cnf /etc/my.cnf.bak

# update-alternatives --install /etc/my.cnf my.cnf "/etc/percona-xtradb-cluster.cnf" 200

7、slave节点修改mysqld.cnf配置文件:

# vim /etc/percona-xtradb-cluster.conf.d/mysqld.cnf

[mysqld]

server-id=4

datadir=/var/lib/mysql

socket=/var/lib/mysql/mysql.sock

log-error=/var/log/mysqld.log

pid-file=/var/run/mysqld/mysqld.pid

log_bin=mysql-bin

log_bin_index=mysql-bin.index

log_slave_updates

expire_logs_days=7

symbolic-links=0

port=3306

lower_case_table_names=1

character_set_server=utf8mb4

collation_server=utf8mb4_general_ci

innodb_file_per_table=1

skip_name_resolve=1

slow_query_log=1

slow_query_log_file=mysql-slow.log

relay_log=relay-log

relay_log_index=relay-log.index

read_only=1

8、slave节点暂时不启用PXC的相关配置:# cd /etc/percona-xtradb-cluster.conf.d  # mv wsrep.cnf wsrep.cnf.bak

9、slave节点初始化MySQL数据:# mysqld --initialize --user=mysql

10、slave节点启动MySQL服务:

# systemctl start mysql.service

# ss -tunlp | grep mysqld

# systemctl enable mysql.service

# systemctl status mysql.service

# tail -100 /var/log/mysqld.log

11、slave节点配置MySQL安全向导:

# grep "password" /var/log/mysqld.log --> 7gk0ti?jf*(M

# mysql_secure_installation

12、slave节点授权root用户远程登录:

# mysql -uroot -p

mysql> create user 'root'@'192.168.1.%' identified by '123456';

mysql> grant all on *.* to 'root'@'192.168.1.%';

mysql> flush privileges;

13、master2节点创建具有复制权限的用户repluser

mysql> create user 'repluser'@'192.168.1.%' identified by '123456';

mysql> grant replication slave on *.* to 'repluser'@'192.168.1.%';

mysql> flush privileges;

14、master2节点使用mysqldump对所有数据库进行全量热备,并将导出的sql文件复制至slave节点:

# mkdir -pv /backup

# mysqldump -E -F -R -q --single-transaction --master-data=2 -A -uroot -p > /backup/all_`date +%F`.sql

# less /backup/all_2019-06-06.sql,找到已被注释的CHANGE MASTER TO语句:

-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000002', MASTER_LOG_POS=154;

# scp -p /backup/all_2019-06-06.sql node4:/backup/

15、slave节点还原数据:

mysql> show variables like 'sql_log_bin';

mysql> set sql_log_bin=0;

mysql> source /backup/all_2019-06-06.sql

mysql> set sql_log_bin=1;

16、slave节点使用具有复制权限的用户连接至master2

mysql> change master to master_host='192.168.1.144',master_user='repluser',master_password='123456',master_port=3306,master_log_file='mysql-bin.000002',master_log_pos=154;

mysql> start slave;

mysql> show slave status\G

17、slave节点停止MySQL服务:

# systemctl stop mysql.service

# ss -tunlp | grep mysqld

# systemctl status mysql.service

# tail -100 /var/log/mysqld.log

18、slave节点注释/etc/percona-xtradb-cluster.conf.d/mysqld.cnf[mysqld]配置段中read_only=1选项

19、slave节点启用PXC的相关配置:# cd /etc/percona-xtradb-cluster.conf.d  # mv wsrep.cnf.bak wsrep.cnf

20、slave节点修改wsrep.cnf配置文件:

# vim /etc/percona-xtradb-cluster.conf.d/wsrep.cnf

[mysqld]

wsrep_provider=/usr/lib64/galera3/libgalera_smm.so

wsrep_provider_options="gcache.size=2G"

wsrep_cluster_address="gcomm://192.168.1.143,192.168.1.144,192.168.1.145,192.168.1.146"

binlog_format=ROW

default_storage_engine=InnoDB

wsrep_slave_threads=8

wsrep_log_conflicts

innodb_autoinc_lock_mode=2

wsrep_node_address=192.168.1.146

wsrep_cluster_name=pxc-cluster

wsrep_node_name=node4

pxc_strict_mode=ENFORCING

wsrep_sst_method=xtrabackup-v2

wsrep_sst_auth="sstuser:s3cretPass"

21、master2节点确认PXC需要同步的位置:# mysqlbinlog /var/lib/mysql/mysql-bin.000001 | grep Xid

备注:master2节点在使用mysqldump对所有数据库进行全量热备时使用了“-F”选项,备份时会自动滚动二进制日志,所以此处命令中使用的二进制日志为mysql-bin.000001Xid的值为最新的18

22、master2节点查看grastate.dat文件的内容,并将grastate.dat文件复制至slave节点的对应目录下:

# cat /var/lib/mysql/grastate.dat

备注:

Ø  uuid:集群中wsrep_cluster_state_uuid的值

Ø  seqno:集群中swrep_last_committed的值,根据此值可以直接判断下次节点启动时做增量传输的位置,目前master2节点处于正常运行的状态,所以值为-1

# scp -p /var/lib/mysql/grastate.dat node4:/var/lib/mysql/

23、slave节点修改grastate.dat文件的属主属组为mysql用户:# chown mysql.mysql /var/lib/mysql/grastate.dat

24、slave节点设置同步开始位置:# vim /var/lib/mysql/grastate.dat

备注:修改seqno的值,将seqno: -1修改为刚才获取的position 1967对应Xid的值18,这就是PXC同步开始的位置

25、slave节点启动MySQL服务:

# systemctl start mysql.service

# ss -tunlp | grep mysqld

# systemctl status mysql.service

# tail -100 /var/log/mysqld.log

26、slave节点停止主从复制:

mysql> stop slave;

27、查看PXC集群状态:

mysql> show global status like 'wsrep%';

(1)wsrep_local_state_uuid:与wsrep_cluster_state_uuid的值一致,且所有节点该值都相同

(2)wsrep_cluster_state_uuid:所有节点该值都相同

(3)wsrep_last_committed:所有节点该值都相同

(4)wsrep_local_state:所有节点该值都应该为4,表示正常

(5)wsrep_incoming_addresses:集群中所有节点的IP192.168.1.143~146),且每个节点该值都相同

(6)wsrep_cluster_size:集群中的节点数量,所有节点该值都相同

(7)wsrep_cluster_conf_id:所有节点该值都相同

(8)wsrep_cluster_status:集群组成的状态,所有节点该值都为“Primary

(9)wsrep_connected:所有节点该值都为“ON”,表示本节点已经与集群建立连接

(10)wsrep_ready:所有节点该值都为“ON”,表示本节点可以正常提供服务

28、新集群中无论哪个节点写入数据,都会复制给其它三个节点


六、模拟PXC中某个节点故障并恢复:

1、master3节点停止MySQL服务:

# systemctl stop mysql.service

# ss -tunlp | grep mysqld

# systemctl status mysql.service

# tail -100 /var/log/mysqld.log

2、查看PXC集群状态:

mysql> show global status like 'wsrep%';

(1)wsrep_incoming_addresses:目前集群中所有节点的IP143144146),且每个节点该值都相同

(2)wsrep_cluster_size:集群中的节点数量(3),所有节点该值都相同

3、集群剩余节点中无论哪个节点写入数据,都会复制给其它两个节点

4、master3节点修改wsrep.cnf配置文件:

# vim /etc/percona-xtradb-cluster.conf.d/wsrep.cnf

[mysqld]

wsrep_cluster_address="gcomm://192.168.1.143,192.168.1.144,192.168.1.145,192.168.1.146"

5、master3节点启动MySQL服务:

# systemctl start mysql.service

# ss -tunlp | grep mysqld

# systemctl status mysql.service

# tail -100 /var/log/mysqld.log

6、查看PXC集群状态:

mysql> show global status like 'wsrep%';

备注:集群已恢复正常

7、宕机时在其它可用节点中写入的数据,已复制给master3节点