主从集群
1. 主从架构的目的
- 缓解数据存储及访问压力
- 可做数据备份,增强数据安全
- 大部分系统读多写少,主从为可做读写分离的基础
- 实现高可用实现故障转移的前提条件(MMM,MHA,MGR)
- 也是其他所有集群方案的基础
2. 准备:两个MySQL节点,开启远程登录权限
# 开启远程登录
use mysql;
update user set host='%' where user='root';
flush privileges;
3. 同步原理
- binlog日志文件是关键
- 从节点IO线程与主服务建立TCP连接,请求binlog文件传输
- 主节点的IO dump线程负责将binlog文件传输给从节点
- 从节点读取到binlog数据后,写入relay日志文件
- 从节点另外的SQL线程将读取relay日志,将操作重演
binlog除用于主从同步外,还可用于缓存数据同步等场景,如Canal,可模拟一个slave节点,发起binlog同步后,可将数据落到Redis kafka等组件。
4. 搭建要点
- 各节点版本最好一致,至少主节点版本需低于从
- 各节点的时间需要同步(保证binlog执行顺序)
- 编辑/etc/my.cnf,指定serverId,保证集群内唯一
- 开启binlog
server-id=101
# 开启binlog
log_bin=master-bin
# 指定binlog日志文件名
log_bin-index=master-bin.index
- 重启,给用户分配replication slave权限
#登录主数据库
mysql -u qinchen -p
GRANT REPLICATION SLAVE ON *.* TO 'qinchen'@'%'; flush privileges;
#查看主节点同步状态: show master status;
- show master status 结果中,file及position字段即为当前日志文件及文件中的索引位置,slave节点即从此位置开始同步数据。
- do_db 及 ignore_db 为配置哪些库需记录binlog,哪些忽略,默认为全库记录
- 从节点的配置,打开relay-log及binlog
#主库和从库需要不一致
server-id=48
#打开MySQL中继日志
relay-log-index=slave-relay-bin.index relay-log=slave-relay-bin
#打开从服务二进制日志
log-bin=mysql-bin
#使得更新的数据写进二进制日志中
log-slave-updates=1
- 启动服务,设置主节点同步状态
# 设置同步主节点:
CHANGE MASTER TO
MASTER_HOST='192.168.1.101', MASTER_PORT=3306, MASTER_USER='root',
MASTER_PASSWORD='root',
MASTER_LOG_FILE='master-bin.000004', MASTER_LOG_POS=156
GET_MASTER_PUBLIC_KEY=1;
# 开启slave
start slave;
# 查看主从同步状态
show slave status;
# 或用 show slave status \G; 这样查看比较简洁
需要注意:file 及 pos 字段需与master查到的状态一致,后续查看主从架构是否搭建成功,也可比对这2个值是否一致。
- 从从节点状态信息可以看出,还可配置同步哪些库,哪些表,默认为所有。思考这个配置是否其他的用处。
- 测试主从,可以创建database table 写入一些数据验证。如果搭建失败,可能从库是进行了写操作,与同步的SQL有冲突,也有可能是从节点重启后又事务回滚等所致。
集群搭建扩展要点
- 一般建议主节点配置针对哪些库记录binlog配置,从节点也可配置是否全部同步,同步哪些库哪些表等。
# 需要同步的二进制数据库名
binlog-do-db=masterdemo
# 只保留7天的二进制日志,以防磁盘被日志占满(可选)
expire-logs-days = 7
# 不备份的数据库
binlog-ignore-db=information_schema
binlog-ignore-db=performation_schema
binlog-ignore-db=sys
# 如果salve库名称与master库名相同,使用本配置
replicate-do-db = masterdemo
# 如果master库名[mastdemo]与salve库名[mastdemo01]不同,使用以下配置[需要做映射] 一般很少用
replicate-rewrite-db = masterdemo -> masterdemo01 # 如果不是要全部同步[默认全部同步],则指定需要同步的表 replicate-wild-do-table=masterdemo01.t_dict replicate-wild-do-table=masterdemo01.t_num
-
主从同步是单向的,为保证数据一致性,一般应用只在主节点上执行写操作,从节点提供读,这就是所谓读写分离。而MySQL本身不提供该机制,需由业务系统自己实现。(可以学习框架shardingSphere)
-
为防止数据不一致,通常设置从节点为只读节点。该配置不会影响slave同步复制,且限定的一般是普通用户的操作,具有super权限的用户依然可以对数据进行修改。
set global read_only=1;
-
若需限定super用户也禁止写数据,可设置
super_read_only=0
。另外:若想阻止主从同步,可执行lush tables with read lock
-
其他集群方式:
- 想进一步提升集群读能力,可扩展一主多从
- 想提高高可用能力,可扩展出多主,多主可为互主模式或环形主从,实现多活
- 打开互主,也只需在主节点上打开slave进程,并将binlog及位置指向从服务状态即可
- GTID集群同步:本质也是基于binlog日志,只是会通过一个全局事务ID标识同步进度,此GTID为全局事务ID,全局唯一且趋势递增
- 5.6版本后引入GTID集群同步,搭建好可以查看状态 Executed_Grid_Set 字段
-
集群扩容,只需增加一个binlog复制,且提前用MySQL dump工具将已有数据导出到SQL文件。再导入到新从,注意应用最好停掉。
-
关于主从架构数据延迟问题,一般小规模应用很难出现,当有高并发业务发生时,若出现多线程并发写入数据,靠单线程慢慢拉去binlog,效率很低。可启动从服务启用多线程并行复制binlog机制,5.7版本后支持。
设置 slave_parallel_workers = n
设置 slave_parallel_type = LOGICAL_CLOCK