SQL 分布式集群、主从复制

2022-06-22  本文已影响0人  李霖弢

主机通过binlog(详见上一章)进行主从同步,保证从机/备机与主机数据一致,每个节点都存储了所有的业务数据。
在主从复制架构中,所有的更新必须在主服务器上进行,否则会造成数据不一致问题。

mysql主从同步原理
  1. master服务器开启binlog后,其数据改变都记录在二进制binary-log日志
  2. slave连接到master,并告诉master要从哪个binlog的哪个偏移量开始执行增量同步。期间slave会监控master二进制日志的变化,如有,则开始I/O线程和SQL线程
    I/O线程读取master的binary-log日志,保存在本地的中继日志relay-log里
    SQL线程读取relay-log,解析成SQL语句在本地重放,使数据和master一致
  3. 最后I/O Thread和SQL Thread将进入睡眠状态,等待下一次被唤醒。
主从同步

应用场景

  1. 主备架构:令一个 Slave 只进行复制,作为备用 Master,提高系统的可靠性。
  2. 读写分离:将读取压力分散到多个从机
  3. 一主多从架构:从机间负载均衡,提升性能
  4. 分库分表:同时缓解读取和写入压力
  5. 双主复制架构:适用于写压力大的场景,会存在更新冲突
  6. 级联复制架构:从机同时也充当主机,继续往下分从机,缓解主机的复制压力,但复制延迟会变大
读写分离

将读取压力分散到多个从机。
可以减少主机的索引,规避索引影响写入效率的问题。
读写分离会带来数据一致性问题,且过多的从机也会造成 Master 的 I/O 和网络压力。因此如果可以优化单机(如通过redis缓存等缓解读取压力等),则无需读写分离

读写分离
分库

通常按业务模块将数据分散到不同的数据库服务器。
分库后,每一个分片都可以分别采取主备架构或读写分离。

分表

基于日志节点的主从同步配置

  1. 确保主从库版本一致
  2. 主服务器开启二进制日志(binary log)并配置server-id,重启mysql生效
# master配置
[root@master] vim /etc/my.cnf

[mysqld]
.........
server-id=1  ### 服务器ID
log-bin=mysql-bin  ### 开启binlog
binlog_format=mixed   ### binlog模式为mixed
### 不需要canal和闪回时可以用MINIMAL减小体积
binlog_row_image=MINIMAL
### 在ROW/MIXED的注释中记录SQL语句
binlog-rows-query-log_events=1
### mysql用户名、密码等信息的库可以不同步
binlog-ignore-db=mysql
binlog-ignore-db=sys
........
  1. 在主库创建专用复制账户
    权限修改后需重启mysql,或执行flush privileges;生效。
[mysql] grant 权限 on 数据库名.表名 to 新用户名@登录主机 identified by "新用户密码";
[mysql] grant replication slave on *.* to 'slaver'@'%' identified by '123456'; 

其中%代表任意主机,可替换为IP地址、域名、localhost(仅可本地访问)、正则(如192.168.1.%)
在mysql8之后需要先创建用户,之后才能授权,例如:

[mysql] CREATE USER 'slaver'@'%' IDENTIFIED BY '123456';
[mysql] grant replication slave on *.* to 'slaver'@'%';
  1. 从主库导出数据
    MySQL会话结束时会自动unlock tables;,因此mysql命令行在此期间应保持激活
[mysql] flush tables with read lock; # 加锁,防止有新的写入
[root@master] mysqldump -uroot -p123456 --all-databases --flush-logs --events --single-transaction --master-data=2 --events > /tmp/all_bak.sql
[root@master] scp /tmp/all_bak.sql 从库IP地址:/tmp/ #
[mysql] unlock tables; #解锁
  1. 修改从库配置文件,重启mysql生效
[root@slave] vim /etc/my.cnf

[mysqld]
.........
server-id=2  ### 服务器ID,每个服务器上配置的server-id都必须不一致
relay-log=mysql-relay-log  ### 开启中继日志(relay log)

super_read_only = on ### 令所有用户(包括super权限用户)只读
skip_slave_start = 1 ### 禁用默认情况下从库mysql启动时自动触发的start slave,防止意外的同步
........
  1. 在从库导入主库数据
[root@slave] mysql -uroot -p123456 < /tmp/all_bak.sql 
  1. 从库使用change master命令配置同步参数,并开启服务
[mysql] change master to 
master_host='主库IP',
master_port=3306,
master_user='之前新建的主库用户',
master_password='之前新建的主库用户密码',
master_log_file='mysql-bin.000014', # 通过【--master-data=2】生成的内容获得,或在主库导出后执行show master logs获得
master_log_pos=599; # 同上

[mysql] start slave; # 开启主从复制
[mysql] show slave status; # 查看是否开启成功

可再次执行change master命令以修改同步参数,执行前需先停止同步。
执行change master时,未指定的参数将保持原值,因此修改时无需全部传入

[mysql] stop slave;
[mysql] change master to master_password='123456';
[mysql] start slave;

如有多个从机,则重复上述步骤 5~7


基于GTID的主从同步配置

# 主、从库都要新增以下配置以开启GTID模式
gtid_mode = on   # 开启gtid模式
enforce_gtid_consistency = on  # 强制gtid一致性
[mysql] change master to 
master_host='主库IP',
master_port=3306,
master_user='之前新建的主库用户',
master_password='之前新建的主库用户密码',
#master_log_file='mysql-bin.000014', # GTID复制模式无需该参数
#master_log_pos=599; # GTID复制模式无需该参数
master_auto_position=1; # 开启GTID复制模式

级联复制架构

对于既是主又是从的库,应在其步骤2配置文件中新增配置,把relay log记录写入binlog
否则只有自身的指令会记入binlog,来自master的指令不会记入

log_slave_updates=1

主主复制架构

两个主机都开启binlogrelay log
change master都指向对方,都执行start slave;

log-bin=mysql-bin  ### 开启binlog
relay-log=mysql-relay-log  ### 开启relay log

重置主从同步

当主从机数据出现不一致时,可重置主从双方的历史信息,重新同步

  1. 从库停止同步
[mysql] STOP SLAVE;
  1. 备份并重置主库
[mysql] FLUSH TABLES WITH READ LOCK;
[root@master] mysqldump -u root -p -databases db1 db2 > bak.sql
[mysql] RESET MASTER;
[mysql] UNLOCK TABLES;
  1. 从库导入数据并重置
[mysql] DROP DATABASE db1;DROP DATABASE db2;
[mysql] SOURCE /root/bak.sql;
[root@slave] RESET SLAVE;
[root@slave] START SLAVE;

异步复制

默认的复制方式。
主库提交事务后,仅通知 Dump 线程发送 Binlog 给从库,就返回COMMIT OK,并不保证从库能接收。
如此时主/从库故障,数据即丢失。例如:当主库崩溃,需要主备切换的场景。

同步复制

主库提交事务后,等待所有从库接收到 binlog 并写入 relay log,主库再返回COMMIT OK。
性能较差。

半同步复制

主库提交事务后,等待至少一个从库接收到 binlog 并写入 relay log,再返回COMMIT OK。

主库
[mysql] INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
rpl_semi_sync_master_enabled = 1  # 表示在master上开启半同步复制模式
rpl_semi_sync_master_timeout = 1000  # 表示主库在某次事务中的等待时间为10000毫秒
从库
[mysql] INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
rpl_semi_sync_slave_enabled = 1
上一篇 下一篇

猜你喜欢

热点阅读