本文对mysql的传统主从复制,半同步复制和组复制进行介绍。
Master 数据库只要发生变化,立马记录到Binlog 日志文件中,Slave数据库启动一个I/0 thread连接Master数据库,请求Master变化的二进制日志。Save I/0获取到的二进制日志,保存到自己的Relay log 日志文件中。Slave 有一个 SQL thread定时检查Realy log是否变化,变化那么就更新数据;
主从复制在正常情况下是可以保证数据一致性的,即从节点的数据和主节点的数据是完全一致的。主从复制的机制是主节点将写入的数据记录成二进制日志(binlog),然后从节点通过读取和解析主节点的binlog来进行数据复制。
主从数据不一致可能在以下情况下出现:
虽然主从复制可以保证数据一致性,但在某些极端情况下,如主节点和从节点同时出现故障,则可能无法避免数据不一致。因此,对于一些对数据一致性要求非常高的场景,可以考虑使用更可靠的复制方案,如半同步复制或组复制。
主从复制只是做了数据的容灾备份,但是没有做到高可用,怎么实现在一个节点挂掉后,不影响整体的业务:
组复制是MySQL InnoDB Cluster中使用的一种多主复制技术,它基于Paxos协议实现了分布式和多主写入的能力。下面是组复制的基本原理:
组成员(Group Members):组复制由多个MySQL实例组成,这些实例彼此协作并形成一个复制组(replication group)。每个实例都是组成员,可以是主节点或从节点。
角色与状态:在组复制中,每个成员可以有三种角色:原始(Primary)、次要(Secondary)和离线(Offline)。原始成员负责处理写操作,其他次要成员则复制原始成员的数据。离线成员指的是暂时不参与复制的成员。
消息通信:组成员之间通过组复制通信层进行消息传递和协调。它提供了成员加入、状态变更、数据同步等功能。在组通信期间,成员之间通过消息传递来达成一致性。
选举与协商:组成员使用Paxos协议来选举原始成员和进行决策。选举过程中会协商并选择一个成员作为原始成员,该成员负责处理写操作并将更改广播到其他成员。
数据一致性:每个成员都维护着自己的事务日志,并通过组复制通信层将已提交的事务广播给其他成员。在事务提交后,组通信确保所有成员的数据是一致的。
自动故障转移:如果原始成员出现故障,组复制会自动选举新的原始成员来接替。选举过程中会基于Paxos协议确保一致的数据状态,从而实现自动的故障转移。
通过上述机制,组复制允许多个节点同时进行写操作,并保证数据的一致性和可靠性。它提供了高可用性、自动故障转移以及简化的管理和扩展能力,适用于分布式环境和多主写入场景。
基于组复制搭建一个高可用的mysql 集群
环境准备:3 台虚拟机:
192.168.75.128
192.168.75.129
192.168.75.130
docker 在每个虚拟机上安装一个mysql实例:
docker run -itd --name mysql -e MYSQL_ROOT_PASSWORD=123456 mysql
# 创建mysql 目录
mkdir /root/mysql
# 创建mysql data 目录
mkdir /root/mysql/data
docker cp mysql:/etc/my.conf /root/mysql
docker run -itd --name mysql-3806 \
--net=host \
--privileged=true \
-e MYSQL_ROOT_PASSWORD=123456 \
-v /root/mysql3806/data:/var/lib/mysql/ \
-v /root/mysql3806/my.cnf:/etc/my.cnf mysql
--net=host 设置mysql 的docker 容器和虚拟机共享网络
# 服务实例id,注意每个实例需要保持唯一 ,注意修改
# 192.168.75.129 的server_id=2222
# 192.168.75.130 的server_id=3333
server_id=1111
# 开启事务的强一致性
gtid_mode=ON
enforce_gtid_consistency=ON
# 存储方式为table
master_info_repository=TABLE
# 使用旧版密码的通讯方式
default_authentication_plugin=mysql_native_password
# 同步配置
# binlog的日志格式
binlog_format=ROW
# 不使用binlog校验和
binlog_checksum=NONE
# 开启binlog 并且以binlog 前置文件命名
log_bin=binlog
# 作为从库同步事务后,记录至数据表
relay_log_info_repository=TABLE
# 从服务记录事件其他从服务器可以继续复制从服务器的二进制日志
log-slave-updates=on
# 组复制配置
# 加载组复制插件
plugin_load_add="group_replication.so"
# UUID,分组的节点需配置一致
loose-group_replication_group_name="89c88c78-c46e-11ec-a8aa-0800271ee0d3"
# 启动MySQL时不自动开启组复制
loose-group_replication_start_on_boot=OFF
# 关闭此MySQL实例的组引导
loose-group_replication_bootstrap_group=OFF
# 关闭单主模式,即使用多主模式
# loose-group_replication_single_primary_mode=OFF
# 在多主模式下,建议开启此选项,严格检查一致性
# loose-group_replication_enforce_update_everywhere_checks=ON
# 组复制节点通信禁用SSL
loose-group_replication_ssl_mode=DISABLED
# 当前MySQL实例的组复制通信地址: 33061 为mysql 默认的组内通信端口
# 每个虚拟机的配置自己的mysql 实例ip 地址
loose-group_replication_local_address="192.168.75.128:33061"
# 组复制的节点通信地址
loose-group_replication_group_seeds="192.168.75.128:33061,192.168.75.129:33061,192.168.75.130:33061"
# 通信白名单配置此处配置192.168.75 段的ip 可以进行通信
loose-group_replication_ip_whitelist="192.168.75.0/24,127.0.0.1"
# 绑定本机ip 地址: 注意每个mysql 实例配置自己的ip
bind-address=192.168.75.128
# 向组内通信 报备的 通信ip 地址 注意每个mysql 实例配置自己的ip
report_host=192.168.75.128
# mysql 的服务端口
port=3806
配置完成记得重启mysql 实例
# 需要开放的端口
firewall-cmd --permanent --zone=public --add-port={3806,33061}/tcp
# 防火墙重新加载
firewall-cmd --reload
# 查看开放的端口
firewall-cmd --zone=public --list-ports
set sql_log_bin=0;
create user repl@'%' identified by '666666';
grant replication slave on *.* to repl@'%';
set sql_log_bin=1;
flush privileges;
change master to master_user='repl', master_password='666666' for channel 'group_replication_recovery';
在 192.168.75.128 mysql 实例中引导组复制
set global group_replication_bootstrap_group=on;
start group_replication;
set global group_replication_bootstrap_group=off;
在 192.168.75.129 和 192.168.75.130 mysql 实例中开启组复制
start group_replication;
如果启动失败,先重置一次,再启动
reset master;
start group_replication;
select * from performance_schema.replication_group_members;
-- 获取主机主节点的id
SHOW STATUS LIKE 'group_replication_primary_member';
-- 对比查看每个mysql 实例的uid
sELECT @@server_uuid;
show variables like '%read_only%';
当主节点挂掉之后使用Paxos协议 从slave 节点得到新的 master,当修复好后可以重新加入组复制,启动mysql 实例后:
change master to master_user='repl', master_password='666666' for channel 'group_replication_recovery';
start group_replication;
loose-group_replication_local_address="192.168.75.128:33061"
loose-group_replication_group_seeds="192.168.75.128:33061,192.168.75.129:33061,192.168.75.130:33061"
问题原因:msyql docker 实例内部不认识 192.168.75.128 ip 所以无法通信,需要在安装mysql 实例的时候增加 --net=host 参数,是mysql docker 实例与虚拟机共享网络空间;
通信的MEMBER_HOST 问题: There was an error when connecting to the donor server. Please check that group_replication_recovery channel credentials and all MEMBER_HOST column values of performance_schema.replication_group_members table are correct and DNS resolvable;
涉及参数:report_host=192.168.75.128 ,配置正确的ip 地址;
本文对mysql 的传统主从异步复制,半同步复制,组内复制进行了对比,已经通过3台虚拟机搭建了组内复制架构。
1 部署高可用、负载均衡的MySQL集群服务;
添加链接描述
2 MGR集群搭建及配置过程;