一、PXC的介绍
PXC的全称是Percona XtraDB Cluster。是一套 MySQL 高可用集群解决方案,与传统的基于主从复制模式的集群架构相比 PXC 最突出特点就是解决了诟病已久的数据复制延迟问题,基本上可以达到实时同步。而且节点与节点之间,他们相互的关系是对等的。PXC 最关注的是数据的一致性,对待事物的行为时,要么在所有节点上执行,要么都不执行,它的实现机制决定了它对待一致性的行为非常严格,这也能非常完美的保证 MySQL 集群的数据一致性。
二、PXC的优缺点
- 优点
PXC最大的优势:强一致性、无同步延迟。
完全兼容 MySQL。
同步复制,事务要么在所有节点提交或不提交。
多主复制,可以在任意节点进行写操作。
在从服务器上并行应用事件,真正意义上的并行复制。
节点自动配置,数据一致性,不再是异步复制。
故障切换:因为支持多点写入,所以在出现数据库故障时可以很容易的进行故障切换。
自动节点克隆:在新增节点或停机维护时,增量数据或基础数据不需要人工手动备份提供,galera cluster会自动拉取在线节点数据,集群最终会变为一致; - 缺点
复制只支持InnoDB 引擎,其他存储引擎的更改不复制
写入效率取决于节点中最慢的一台
三、PXC与Replication的区别
Replication | PXC |
---|---|
数据同步是单向的,master负责写,然后异步复制给slave;如果slave写入数据,不会复制给master。 | 数据同步时双向的,任何一个mysql节点写入数据,都会同步到集群中其它的节点。 |
异步复制,从和主无法保证数据的一致性 | 同步复制,事务在所有集群节点要么同时提交,要么同时不提交 |
四、使用Docker搭建PXC集群
1、安装
搜索percona-xtradb-cluster
镜像,我们使用5.7
版本。
docker pull percona/percona-xtradb-cluster:5.7
示例:
[root@localhost ~]# docker pull percona/percona-xtradb-cluster:5.7
Trying to pull repository docker.io/percona/percona-xtradb-cluster ...
5.7: Pulling from docker.io/percona/percona-xtradb-cluster
524b0c1e57f8: Already exists
27b947d6be19: Pull complete
26efa431217c: Pull complete
7d4afafca533: Pull complete
05e05cf6b007: Pull complete
868bb5b06c86: Pull complete
f0794e3eeb9c: Pull complete
3a988f4f1cd9: Pull complete
46f38e1635eb: Pull complete
75805c1fcaed: Pull complete
575a6d0fc78f: Pull complete
c8bb3fa6ebc4: Pull complete
Digest: sha256:b03a060e9261b37288a2153c78f86dcfc53367c36e1bcdcae046dd2d0b0721af
Status: Downloaded newer image for docker.io/percona/percona-xtradb-cluster:5.7
root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/percona/percona-xtradb-cluster 5.7 ad45cffb713a 6 weeks ago 491 MB
docker.io/centos latest 831691599b88 7 weeks ago 215 MB
2、创建集群网络
docker network create pxc-network
创建一个用于docker各个集群应用的相互通信的网络。
实例:
[root@localhost ~]# docker network create pxc-network
f743566e4ca1e40b4f7cec29b96c83d400afba3effb3dfa61bf7bb27cbd6e5cd
3、创建数据卷
这里,我们搭建一个3节点的集群,所以需要创建三个数据卷。
# 第一个数据卷
docker volume create --name v1
# 第二个数据卷
docker volume create --name v2
# 第三个数据卷
docker volume create --name v3
创建三个数据卷,并命名v1
,v2
,v3
。这三个数据卷,分别挂载这3个节点容器。
实例:
[root@localhost ~]# docker volume create --name v1
v1
[root@localhost ~]# docker volume create --name v2
v2
[root@localhost ~]# docker volume create --name v3
v3
如果使用了数据卷的镜像创建失败,数据卷也需要删除,重新创建。
docker volume rm v1
4、创建节点容器
创建第一个节点。
docker run -di --name=pn1 --net=pxc-network -p 9000:3306 -v v1:/var/lib/mysql --privileged -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=cluster1 -e XTRABACKUP_PASSWORD=123456 ad45cffb713a
示例:
[root@localhost ~]# docker run -di --name=pn1 --net=pxc-network -p 9000:3306 -v v1:/var/lib/mysql --privileged -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=cluster1 -e XTRABACKUP_PASSWORD=123456 ad45cffb713a
e6f309f355466e7187b5e23a8a0d4d18e0d164addbdff3533e08ba99f7f57935
-di
以交互模式运行容器后台运行。
--name=pn1
当前的容器命名为pn1
--net=pxc-network
加入集群网络,用于各个节点通信
-p 9000:3306
映射当前服务器的9000端口到容器的3306端口
-v v1:/var/lib/mysql
映射v1
数据卷到容器的/var/lib/mysql
目录
--privileged
给予root权限(特殊权限)
MYSQL_ROOT_PASSWORD=123456
设置数据库的访问密码
-e
环境变量设置
使用镜像id为ad45cffb713a
PXC镜像,来创建容器。
然后,依次创建第二节点。
docker run -di --name=pn2 --net=pxc-network -p 9001:3306 -v v2:/var/lib/mysql --privileged -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=cluster1 -e XTRABACKUP_PASSWORD=123456 -e CLUSTER_JOIN=pn1 ad45cffb713a
服务器9001端口映射到容器的3306
v2
数据卷映射到容器/var/lib/mysql
的目录
-e CLUSTER_JOIN=pn1
表示该节点与--name=pn1
的节点同步。
第三个节点
docker run -di --name=pn3 --net=pxc-network -p 9002:3306 -v v3:/var/lib/mysql --privileged -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=cluster1 -e XTRABACKUP_PASSWORD=123456 -e CLUSTER_JOIN=pn2 ad45cffb713a
服务器9002端口映射到容器的3306
v3
数据卷映射到容器/var/lib/mysql
的目录
CLUSTER_JOIN=pn2
表示与第二个节点同步。
后面节点的创建相比第一节点增加了CLUSTER_JOIN
环境变量,表示同步节点。
示例:
[root@localhost ~]# docker run -di --name=pn2 --net=pxc-network -p 9001:3306 -v v2:/var/lib/mysql --privileged -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=cluster1 -e XTRABACKUP_PASSWORD=123456 -e CLUSTER_JOIN=pn1 ad45cffb713a
4f0bae62f8544708580dfc014e3daf6f86c442983dfce0132eac3888a2ab913d
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4f0bae62f854 ad45cffb713a "/entrypoint.sh my..." 3 seconds ago Up 3 seconds 4567-4568/tcp, 0.0.0.0:9001->3306/tcp pn2
e6f309f35546 ad45cffb713a "/entrypoint.sh my..." 39 seconds ago Up 39 seconds 4567-4568/tcp, 0.0.0.0:9000->3306/tcp pn1
[root@localhost ~]# docker run -di --name=pn3 --net=pxc-network -p 9002:3306 -v v3:/var/lib/mysql --privileged -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=cluster1 -e XTRABACKUP_PASSWORD=123456 -e CLUSTER_JOIN=pn2 ad45cffb713a
ea638d2cde30a0100061c95055606052818261381366db56fabf78a5d0b4253a
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ea638d2cde30 ad45cffb713a "/entrypoint.sh my..." 3 seconds ago Up 2 seconds 4567-4568/tcp, 0.0.0.0:9002->3306/tcp pn3
4f0bae62f854 ad45cffb713a "/entrypoint.sh my..." 15 seconds ago Up 14 seconds 4567-4568/tcp, 0.0.0.0:9001->3306/tcp pn2
e6f309f35546 ad45cffb713a "/entrypoint.sh my..." 51 seconds ago Up 51 seconds 4567-4568/tcp, 0.0.0.0:9000->3306/tcp pn1
5、状态查看
进入pn1
节点
# 1.进入节点
docker exec -it pn1 /usr/bin/mysql -uroot -p123456
# 2.查看状态
mysql> show status like 'wsrep%';
实例:
mysql> show status like 'wsrep%';
+----------------------------------+-------------------------------------------------------+
| Variable_name | Value |
+----------------------------------+-------------------------------------------------------+
| wsrep_local_state_uuid | 944d2133-d956-11ea-982d-e7a1f0fcefe6 |
| wsrep_protocol_version | 9 |
| wsrep_last_applied | 18 |
| wsrep_last_committed | 18 |
| wsrep_replicated | 0 |
| wsrep_replicated_bytes | 0 |
| wsrep_repl_keys | 0 |
| wsrep_repl_keys_bytes | 0 |
| wsrep_repl_data_bytes | 0 |
| wsrep_repl_other_bytes | 0 |
| wsrep_received | 10 |
| wsrep_received_bytes | 812 |
| wsrep_local_commits | 0 |
| wsrep_local_cert_failures | 0 |
| wsrep_local_replays | 0 |
| wsrep_local_send_queue | 0 |
| wsrep_local_send_queue_max | 1 |
| wsrep_local_send_queue_min | 0 |
| wsrep_local_send_queue_avg | 0.000000 |
| wsrep_local_recv_queue | 0 |
| wsrep_local_recv_queue_max | 2 |
| wsrep_local_recv_queue_min | 0 |
| wsrep_local_recv_queue_avg | 0.100000 |
| wsrep_local_cached_downto | 0 |
| wsrep_flow_control_paused_ns | 0 |
| wsrep_flow_control_paused | 0.000000 |
| wsrep_flow_control_sent | 0 |
| wsrep_flow_control_recv | 0 |
| wsrep_flow_control_interval | [ 173, 173 ] |
| wsrep_flow_control_interval_low | 173 |
| wsrep_flow_control_interval_high | 173 |
| wsrep_flow_control_status | OFF |
| wsrep_cert_deps_distance | 0.000000 |
| wsrep_apply_oooe | 0.000000 |
| wsrep_apply_oool | 0.000000 |
| wsrep_apply_window | 0.000000 |
| wsrep_commit_oooe | 0.000000 |
| wsrep_commit_oool | 0.000000 |
| wsrep_commit_window | 0.000000 |
| wsrep_local_state | 4 |
| wsrep_local_state_comment | Synced |
| wsrep_cert_index_size | 0 |
| wsrep_cert_bucket_count | 22 |
| wsrep_gcache_pool_size | 1728 |
| wsrep_causal_reads | 0 |
| wsrep_cert_interval | 0.000000 |
| wsrep_open_transactions | 0 |
| wsrep_open_connections | 0 |
| wsrep_ist_receive_status | |
| wsrep_ist_receive_seqno_start | 0 |
| wsrep_ist_receive_seqno_current | 0 |
| wsrep_ist_receive_seqno_end | 0 |
| wsrep_incoming_addresses | e6f309f35546:3306,4f0bae62f854:3306,ea638d2cde30:3306 |
| wsrep_cluster_weight | 3 |
| wsrep_desync_count | 0 |
| wsrep_evs_delayed | |
| wsrep_evs_evict_list | |
| wsrep_evs_repl_latency | 0/0/0/0/0 |
| wsrep_evs_state | OPERATIONAL |
| wsrep_gcomm_uuid | 9d4853de-d956-11ea-b64e-6b6d80ffcf54 |
| wsrep_cluster_conf_id | 3 |
| wsrep_cluster_size | 3 |
| wsrep_cluster_state_uuid | 944d2133-d956-11ea-982d-e7a1f0fcefe6 |
| wsrep_cluster_status | Primary |
| wsrep_connected | ON |
| wsrep_local_bf_aborts | 0 |
| wsrep_local_index | 0 |
| wsrep_provider_name | Galera |
| wsrep_provider_vendor | Codership Oy <info@codership.com> |
| wsrep_provider_version | 3.43(ra60e019) |
| wsrep_ready | ON |
+----------------------------------+-------------------------------------------------------+
71 rows in set (0.05 sec)
这里的wsrep_incoming_addresses
的地址是三个对应容器的ID:端口
的形式。证明三个节点已经链接成功。
6、节点检查
集群完整性检查:
属性 | 含义 |
---|---|
wsrep_cluster_state_uuid | 在集群所有节点的值应该是相同的,有不同值的节点,说明其没有连接入集群. |
wsrep_cluster_conf_id | 正常情况下所有节点上该值是一样的.如果值不同,说明该节点被临时”分区”了.当节点之间网络连接恢复的时候应该会恢复一样的值. |
wsrep_cluster_size | 如果这个值跟预期的节点数一致,则所有的集群节点已经连接. |
wsrep_cluster_status | 集群组成的状态.如果不为”Primary”,说明出现”分区”或是”split-brain”脑裂状况. |
节点状态检查:
属性 | 含义 |
---|---|
wsrep_ready | 该值为 ON,则说明可以接受 SQL 负载.如果为 Off,则需要检查 wsrep_connected |
wsrep_connected | 如果该值为 Off,且 wsrep_ready 的值也为 Off,则说明该节点没有连接到集群.(可能是 wsrep_cluster_address 或 wsrep_cluster_name 等配置错造成的.具体错误需要查看错误日志) |
wsrep_local_state_comment | 如果 wsrep_connected 为 On,但 wsrep_ready 为 OFF,则可以从该项查看原因 |
复制健康检查:
属性 | 含义 |
---|---|
wsrep_flow_control_paused | 表示复制停止了多长时间.即表明集群因为 Slave 延迟而慢的程度.值为 0~1,越靠近 0 越好,值为 1 表示 复制完全停止.可优化 wsrep_slave_threads 的值来改善 |
wsrep_cert_deps_distance | 有多少事务可以并行应用处理.wsrep_slave_threads 设置的值不应该高出该值太多 |
wsrep_flow_control_sent | 表示该节点已经停止复制了多少次 |
*wsrep_local_recv_queue_avg | 表示 slave 事务队列的平均长度.slave 瓶颈的预兆. 最慢的节点的 wsrep_flow_control_sent 和 wsrep_local_recv_queue_avg 这两个值最高.这两个值较低的话,相对更好 |
检测慢网络问题:
属性 | 含义 |
---|---|
wsrep_local_send_queue_avg | 网络瓶颈的预兆.如果这个值比较高的话,可能存在网络瓶颈 |
冲突或死锁的数目:
属性 | 含义 |
---|---|
wsrep_last_committed | 最后提交的事务数目 |
wsrep_local_cert_failures 和 wsrep_local_bf_aborts | 回滚,检测到的冲突数目 |
7、集群同步验证
我们进入其中的一个节点,比如第二个。创建的时候端口映射是9001:3306
,所以外部登录的话,使用以下命令完成。
mysql -h192.168.56.101 -uroot -p123456
创建一个数据库,一个表,看看其他数据库是否同步了
# 1.创建数据库
create database test;
# 2.创建表
示例:
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)
mysql> create database test;
Query OK, 1 row affected (0.03 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| test |
+--------------------+
5 rows in set (0.00 sec)
mysql> use test;
Database changed
mysql> create table users(id int ,name varchar(30));
Query OK, 0 rows affected (0.01 sec)
mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| users |
+----------------+
1 row in set (0.00 sec)
切换账号查询
mysql -h192.168.56.101 -uroot -p123456 -P9000
示例:
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| test |
+--------------------+
5 rows in set (0.00 sec)
mysql> use test;
Database changed
mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| users |
+----------------+
1 row in set (0.00 sec)
可以看到数据正常同步。
部分内容来自互联网:
鸣谢:MySQL之PXC集群搭建