一、Percona XtraDB Cluster相关概念及原理:
1、Percona XtraDB Cluster简介:
Percona XtraDB Cluster是基于Galera协议的MySQL高可用集群架构。Galera是Codership提供的多主数据同步复制机制,具有高可用性,方便扩展,可以实现多个MySQL节点间的数据同步复制以及读写,并且可保障数据库的服务高可用及数据一致性。基于Galera的高可用方案主要有MariaDB Galera Cluster和Percona XtraDB Cluster(简称PXC)。PXC属于一套近乎完美的MySQL高可用集群解决方案,相比那些传统的基于主从复制模型的集群架构MHA和MM+Keepalived,Galera Cluster最突出的特点就是解决了诟病已久的数据复制延迟问题,基本上可以达到实时同步,而且节点与节点之间,它们相互的关系是对等的。本身Galera Cluster也是一种多主架构,如下图所示:
要搭建PXC架构至少需要3个MySQL实例来组成一个集群,3个实例之间不是主从模式,而是各自为主,所以三者是对等关系,不分从属,这就叫multi-master架构。客户端写入和读取数据时,连接哪个实例都是一样的,读取到的数据也都是相同的,写入任意一个实例之后,集群自身会将新写入的数据同步到其它实例上,这种架构不共享任何数据,是一种高冗余架构。
2、PXC原理:
PXC最常使用如下4个端口号:
(1)3306:数据库对外服务的端口号
(2)4444:请求SST的端口号
(3)4567:组成员之间进行沟通的端口号
(4)4568:用于传输IST的端口号
备注:
Ø SST:State Snapshot Transfer,全量数据传输
Ø IST:Incremental State Transfer,增量数据传输
从上图中可以看出PXC的操作流程,首先客户端发起一个事务,该事务先在本地执行,执行完成后发起对事务的提交操作。在提交之前需要将产生的复制写集广播出去,然后获取到一个全局的事务ID号,一并传送到另一节点上。通过验证合并数据之后,发现没有冲突数据,执行apply_cb和commit_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数据传输有xtrabackup、mysqldump和rsync三种方式,而增量数据传输就只有一种方式xtrabackup,但生产环境中一般数据量较小时,可以使用SST全量数据传输,但也只使用xtrabackup方法。
(4)GCache模块:在PXC中一个特别重要的模块,它的核心功能就是为每个节点缓存当前最新的写集。如果有新节点加入进来,就可以把新数据的增量传递给新节点,而不需要再使用SST传输方式,这样可以让节点更快地加入集群中,涉及如下参数:
a、gcache.size:缓存写集增量信息的大小,它的默认大小是128MB,通过wsrep_provider_options参数设置,建议调整为2GB~4GB范围,足够的空间便于缓存更多的增量信息。
b、gcache.mem_size:GCache中内存缓存的大小,适度调大可以提高整个集群的性能
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、关闭SELinux和firewalld
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=2,master3节点中的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_provider:Galera库的路径和文件名
(2)wsrep_provider_options:Galera库的额外参数
(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_method:SST传输数据的方式,有xtrabackup、mysqldump和rsync三种,前两者在传输时都需要对donor加全局只读锁(FLUSH TABLES WITH READ LOCK),而xtrabackup则不需要(它使用percona自己提供的backup lock),强烈推荐使用xtrabackup-v2方式
(11)wsrep_sst_auth:在SST传输时需要使用的认证凭据,格式为“用户:密码”
备注:
Ø master2节点中的wsrep_node_address=192.168.1.144,wsrep_node_name=node2
Ø master3节点中的wsrep_node_address=192.168.1.145,wsrep_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、master2和master3节点分别启动MySQL服务:
# systemctl start mysql.service
# ss -tunlp | grep mysqld
# systemctl enable mysql.service
# systemctl status mysql.service
# tail -100 /var/log/mysqld.log
备注:master2和master3节点无需分别配置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、master2和master3节点分别查看测试数据:
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、master1和master3节点分别查看测试数据:
mysql> select * from tb;
5、master3节点创建测试数据:
mysql> insert into tb(name) values('jack'),('tom');
mysql> select * from tb;
6、master1和master2节点分别查看测试数据:
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节点关闭SELinux和firewalld、配置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.000001,Xid的值为最新的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:集群中所有节点的IP(192.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:目前集群中所有节点的IP(143、144、146),且每个节点该值都相同
(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节点