• MySQL系列——集群复制方式及原理


    主从复制

    分布式扩展中最常用的一种模式就是主从复制,主从复制的主要作用是通过读写分离提高数据库的并发性能。复制指将主数据库的DDL(data definition language)和 DML(Data Manipulation Language) 操作通过二进制日志(bin log)传到从库服务器中,然后在从库上对这些日志重新执行,从而使得从库和主库的数据保持同步。Mysql支持一台主库同时向多台从库进行复制, 从库同时也可以作为其他从服务器的主库,实现链状复制。

    Mysql默认使用异步复制

    原理

    主从复制的原理如下所示,假设此时为单主单从模式
    请添加图片描述
    如上图所示

    • 当master节点执行insert、update和delete等DML操作时,对应的语句会按序写入到bin log中
    • slave节点需要使用mater节点提供的账号和密码连接到mater节点,并且对每一个slave节点都创建一个binlog dump线程
    • 当master节点的binlog发生改变时,binlog dump线程会通知所有的slave节点,并将相应的binlog内容推送到slave节点
    • 当IO线程接受到binglog内容后,就将内容写入到slave节点本地的relay log中
    • SQL线程就会读取IO线程写入的relay log,并且根据relay log的内容对slave节点的数据库做相应的操作;操作执行成功后,relay log中的内容将会被删除

    复制方式

    由于主从复制依赖于二进制日志文件(binlog),而binlog有三种格式

    • Statement:基于SQL语句级别,记录每条修改数据的SQL语句
    • Row:基于行级别,记录每行数据的详细变化;一致性更好,但更大
    • Mixed:混合模式,默认使用Statement
    开启二进制文件
    • log_bin=master-bin

    因此,主从复制也就有三种方式:

    • binlog_format=Statement:基于SQL语句的复制
    • binlog_format=Row:基于行的复制
    • binlog_format=Mixed:混合复制模式

    优势

    主从复制的优势主要包含如下几点:

    • 当master节点发生故障时,可以快速的切换到slave节点继续提供服务,保证数据库服务的可用性
    • 实现读写分离,降低mater节点的访问压力
    • 可以在slave节点中执行备份,以避免备份期间影响master节点的服务

    劣势

    主从ok的情况:在从库写入,不能写入主库

    主库挂掉,随便写个从库,数据不能同步

    异步复制

    异步复制是一个主库,一个或多个从库,数据异步同步到从库

    这种模式下,主节点不会主动推送数据到从节点,主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理

    这种模式下,如果主节点崩溃,此时主节点上已经提交的事务可能并没有传到从节点上,此时会将从节点提升为主节点,可能导致新主节点上的数据不完整

    半同步复制

    Mysql默认使用的是异步复制,由于异步操作所带来的延迟,当主库由于某种原因导致binlog日志的丢失,没有成功的同步到从库上,那么就会造成主从之间的不一致性。

    原因为:异步复制中,主库在执行完对binlog的commit操作后即可返回客户端,无需等待binlog日志成功的传送到从库上

    请添加图片描述
    而半同步复制执行时,为了保证主库中的binlog能够被可靠的复制到从库上,主库在每次成功提交事务后,并不是立即返回给客户端,而是等待binlog至少在一个从库上成功提交并写入到relaylog中。只有binlog成功的写入到了其中的一个从库中,主库才会给客户端反馈

    一致性的保证:

    1. 直到至少一个从库的relay log成功保存了日志,主库才会给客户端反馈
    2. 如果在1、2、3操作,主库宕机,事务未提交成功,这时从库也没有收到bin log日志

    注意

    1. 主库和从库都要启用半同步复制才会进行半同步复制功能,否则主库会还原为默认的异步复制
    2. 当主库等待超时时,也会还原为默认的异步复制。当至少有一个从库赶上时,主库会恢复到半同步复制

    并行复制

    基于DATABASE

    开启并行复制后,会启动多个 Worker 线程,原有的 SQL 线程变为 Coordinator 线程。

    可以并行的事务分发给 Worker 线程执行; 不能并行的事务等待 Worker 线程全部结束后,再由 Coordinator 线程自己执行。

    DDL 语句或者是跨 Schema 的语句不能并行执行。

    这种并行复制的模式,对于多个 DB 同时更新才能有较高的并行度,但是更常见的情况是更新集中在同个一个 DB。

    一个简单的改进,把 Schema 级别的并行复制改成 Table 级别,可以大幅度提高单库多表环境下的并行度。但是对于只有一个热点表的情况依然处理不了。

    基于LOGICAL_CLOCK

    相比 DATABASE 极大提高了并行度。

    Group Commit 实现了主库事务的并行提交。很显然的,主库能同时进入prepare阶段的事务之间不会冲突,那么这些事务在备库回放时也不会冲突。

    Group Commit 中,last_commited 相同的事务,可以在备库并行回放。

    MySQL bin log 里面维护了两个变量

    Logical_clock max_committed_transaction:记录上次 Group commit 时最大的 sequence_number,即上述 mysqlbinlog 中的 last_committed

    Logical_clock transaction_counter:sequence_number 来源,每次分配 sequence_number 时 transaction_counter 进行递增,即当前最大的 sequence_number

    5.7 的并行复制还有一点点弊端,如果如果主库并行度低,那么备库回放时也很难并行。

    为此,5.7 引入了两个参数:

    • binlog_group_commit_sync_delay:等待延迟提交的时间,binlog提交后等待一段时间再 fsync。让每个 group 的事务更多,人为提高并行度。
    • binlog_group_commit_sync_no_delay_count:等待提交的最大事务数,如果等待时间没到,而事务数达到了,就立即 fsync。达到期望的并行度后立即提交,尽量缩小等待延迟。
    基于 WriteSet 的并行复制

    为了提高备库回放的速度,需要在主库尽量提高并行度。

    8.0解决了这个问题,即使主库在串行提交的事务,只有互相不冲突,在备库就可以并行回放。

    8.0 引入了参数 binlog_transaction_dependency_tracking 来控制事务依赖模式,让备库根据 commit timestamps 或者 write sets 并行回放事务,有三个取值:

    • COMMIT_ORDERE:使用 5.7 Group commit 的方式决定事务依赖
    • WRITESET:使用 WriteSet 的方式决定判定事务直接的冲突,发现冲突则依赖冲突事务,否则按照 COMMIT_ORDERE 方式决定依赖
    • WRITESET_SESSION:在 WRITESET 方式的基础上,保证同一个 session 内的事务不可并行

    WRITESET 是一个 hash 数组,大小由参数 binlog_transaction_dependency_history_size 决定。

    参数 transaction_write_set_extraction 决定 hash 算法,可选值:OFF、MURMUR32、XXHASH64,默认值 XXHASH64,如果

    WriteSet 记录了事务的更新行信息,决定 commit_parent时,使用事务自己的 session WriteSet 和 history WriteSet 进行比对,找到最近的冲突行,设为 commit_parent。如果 WriteSet 找不到 commit_parent,则还是使用 COMMIT_ORDERE 决定 commit_parent

    多源复制

    在 MySQL 8.0 版本中,提供了多源复制,多源复制的出现对于分库分表的业务提供了极大的便利,

    多源复制的好处

    可以集中备份,在从库上备份,不会影响线上的数据正常运行

    节约购买从库服务器的成本,只需要一个从库服务器即可

    数据汇总在一起,方便后期做数据统计

    减轻DBA维护工作量。

  • 相关阅读:
    枚举与接口常量、类常量有什么区别?
    Python UI自动化 —— pytest常用运行参数解析、pytest执行顺序解析
    以太坊创始人V神:放弃对币价的关注,应专注于技术
    209. 长度最小的子数组
    uniapp 开发公众号 h5(openid,微信支付,订阅通知)
    Python玩转emoji表情 一行代码的事儿!
    四十五、ORM相关
    MySQL Insert 后獲得主鍵
    美团后端笔试2022.08.13
    1、C语言面向对象引入类和对象的概念
  • 原文地址:https://blog.csdn.net/Star_Inori/article/details/127405343