美文网首页
SQL 分布式集群、主从复制

SQL 分布式集群、主从复制

作者: 李霖弢 | 来源:发表于2022-06-22 16:44 被阅读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台,负责读写,或仅负责写
  • 从机可以有1台或多台,负责读
  • 同步延迟问题
    采用读写分离必然引起同步延迟,存在如下解决方案
    • 同步写入从库
      主从同步默认为异步,如果改为同步,则所有从库写入完成后,主库的写入请求才返回。
      弊端:性能较差,当有多个从库时,严重影响请求速度
    • 缓存中间件
      每当发生写请求时,记录一个key,失效时间设置为主从同步的延时。发生读请求时检查key是否存在,存在则走主库,否则走从库。
    • 关键业务读主库
      关键业务读写操作全部指向主机,非关键业务采用读写分离。
      如整个系统都对数据一致性要求不高,不处理同步延迟问题也没关系。
      弊端:开发时需要特殊场景特殊处理
读写分离
分库

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

  • join查询问题
    基于性能、安全性等原因通常禁止跨库join,可以通过建立全局表(数据字典)、重要表做多库同步、重要字段做冗余、HBase+ElasticSearch等方案解决
  • 分布式事务
分表
  • 单表数据过多时,其查询效率本身就会下降,因此分表后即使不分散到其他数据库,也能带来性能提升
  • 分为 垂直分表水平分表(通常行数到达千万级别后开始考虑水平分表)

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

  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的主从同步配置

  • GITD (Global Transaction ID 全局事务ID)
    由事务发起的服务器ID(server_uuid)以及单调递增的事务ID(transaction_id)组合而成,在集群内全局唯一,如:3E11FA47-71CA-11E1-9E33-C80AA9429562:1。

  • 原理
    当一个事务在主库端执行并提交时,产生 GTID,并记录到 binlog 日志。
    slave 接收进 relaylog 后,读取GTID值设置为 gtid_next 变量(下一个执行的GTID)
    sql 线程从 relay log 中获取 GTID,然后对比 slave 端的 binlog 记录看是否重复。
    无记录才会执行,并记录到自身的 binlog(防止重复执行)。

  • 优点
    无需找到 master_log_file 和 master_log_pos
    master无需等待slave的ACK信息,延迟更低,性能更好
    确保每个事务只执行一次,且连续递增的GTID可避免丢失
    方便快速定位事务最初的提交来源

  • 缺点
    为生成GTID,slave需开启binlog
    在一个复制组中,必须统一开启GTID或是关闭GTID
    不允许一个SQL同时更新一个事务引擎和非事务引擎的表
    不支持部分语法,如create temporary tableCREATE TABLE …SELECT

  • 原本已做过同步的主从机要改为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

重置主从同步

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

  • RESET MASTER;
    清空binlog索引文件及其列出的日志文件,创建一个新的binlog文件
    清空系统变量 gtid_purged 、gtid_executed,清空 mysql.gtid_executed 表。
  • RESET SLAVE;
    清除slave 复制时的master binlog的位置
    清空master info, relay log info
    删除所有的relay log文件,并创建一个新的relay log文件。
    重置复制延迟(CHANGE MASTER TO 的 MASTER_DELAY参数指定的)为0。
  • RESET SLAVE ALL;
    RESET SLAVE;清除的内容外,还重置CHANGE MASTER TO的所有参数
  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

相关文章

  • SQL 分布式集群、主从复制

    主机通过binlog(详见上一章)进行主从同步,保证从机/备机与主机数据一致,每个节点都存储了所有的业务数据。在主...

  • 【5分钟背八股】redis集群方案有哪些?

    常见集群分类 主从复制集群 分片集群 redis有那些: 主从复制集群,手动切换 带有哨兵的HA的主从复制集群 客...

  • Redis的高可用

    Redis主从复制 什么是主从复制 Redis有三种集群方案,主从复制,哨兵,cluster集群,主从复制是指将一...

  • redis的三种集群方式

    redis的三种集群方式 redis有三种集群方式:主从复制,哨兵模式和集群。 1.主从复制 主从复制原理: 从服...

  • MySQL集群篇

    1 集群之主从复制 1.1 主从复制概述 MySQL主从复制也可以称为MySQL主从同步,它是构建数据库高可用集群...

  • Redis 集群概念

    1.Redis 分布式集群 , 这里不讨论主从复制 ,着重介绍分区 1.假设有 20 个节点 ,数据进来后 , 会...

  • mysql8.0主从复制

    mysql主从复制作用:数据库备份、读写分离、高可用、集群原理:二进制sql执行文件(binlog)。主机有写的操...

  • 更强大的实时数仓构建能力!分析型数据库PostgreSQL 6.

    阿里云 AnalyticDB for PostgreSQL 为采用MPP架构的分布式集群数据库,完备支持SQL 2...

  • AnalyticDB for PostgreSQL 6.0 新特

    阿里云 AnalyticDB for PostgreSQL 为采用MPP架构的分布式集群数据库,完备支持SQL 2...

  • redis包含三种集群策略

    redis包含三种集群策略1,主从复制,2,哨兵3,集群 主从复制 在主从复制中,数据库分为俩类,主数据库(mas...

网友评论

      本文标题:SQL 分布式集群、主从复制

      本文链接:https://www.haomeiwen.com/subject/jwdevrtx.html