Mysql集群--主从模式

数据可以从一个MySQL数据库服务器主节点复制到一个或多个从节点。MySQL 默 认采用异步复制方式,这样从节点不用一直访问主服务器来更新自己的数据。

 一,主从复制

 主从复制整体分为以下三个步骤:

  1. 主库将数据库的变更操作记录到Binlog日志文件中
  2. 从库读取主库中的Binlog日志文件信息写入到从库的Relay Log中继日志中
  3. 从库读取中继日志信息在从库中进行Replay,更新从库数据信息

主从复制时序图:

  1. Master服务器对数据库更改操作记录在Binlog中,BinlogDump Thread接到写入请求后,读取 Binlog信息推送给Slave的I/O Thread
  2. Slave的I/O Thread将读取到的Binlog信息写入到本地Relay Log中。
  3. Slave的SQL Thread检测到Relay Log的变更请求,解析relay log中内容在从库上执行。

主从复制存在的问题

  1. 主库宕机后,数据可能丢失
  2. 从库只有一个SQL Thread,主库写压力大,复制很可能延时 

二, 半同步复制

为了提升数据安全,MySQL让Master在某一个时间点等待Slave节点的 ACK消息,接收到ACK消息后才进行事务提交,这也是半同步复制的基础。

主库事务写入分为 4 个步骤:

  • InnoDB Redo File Write (Prepare Write)
  • Binlog File Flush & Sync to Binlog File
  • InnoDB Redo File Commit(Commit Write)
  • Send Binlog to Slave 

Master不需要关注Slave是否接受到Binlog Event时,即为传统的主从复制。

当Master需要在第三步等待Slave返回ACK时,即为 after-commit,半同步复制。

当Master需要在第二步等待 Slave 返回 ACK 时,即为 after-sync,增强半同步。

三,并行复制

为了解决主从复制的延迟问题,采用并行复制。在从库中有两个线程IO Thread和SQL Thread,都是单线程模式工作,因此有了延迟问题,我们可以采用多线程机制来加强,减少从库复制延迟。(IO Thread多线程意义不大,主要指的是SQL Thread多线程)

I.基于库的并行复制原理图解:

实现虽然简单,但是非多库的情况下这个用不了,或者当多库中单一库数据量太大的问题上,会发现提升并不大,基于库的并行复制颗粒度太大。

II.基于组提交的并行复制:

当事务提交时,它们将在单个操作中写入到二进制日志中。如果多 个事务能同时提交成功,那么它们意味着没有冲突,因此可以在Slave上并行执行,所以通过在主库上 的二进制日志中添加组提交信息。InnoDB事务提交采用的是两阶段提交模式。一个阶段是prepare,另一个是commit。

<并行复制基于一个前提,即所有已经处于prepare阶段的事务,都是可以并行提交的。这些当然也可以在从库中并行提交,因为处理这个阶段的事务都是没有冲突的。在一个组里提交的事务, 一定不会修改同一行。这是一种新的并行复制思路,完全摆脱了原来一直致力于为了防止冲突而做的分 发算法,等待策略等复杂的而又效率底下的工作>

通过mysqlbinlog工具分析binlog日志,就可以发现组提交的内部信息。

 III.基于write-set的并行复制

MySQL会有一个集合变量来存储事务修改的记录信息(主键哈 希值),所有已经提交的事务所修改的主键值经过hash后都会与那个变量的集合进行对比,来判断改行 是否与其冲突,并以此来确定依赖关系,没有冲突即可并行。这样的粒度,就到了 row级别了,此时并 行的粒度更加精细,并行的速度会更快。

IV.并行复制配置优化

控制集合变量的大小: binlog_transaction_dependency_history_size

控制binlog文件中事务间依赖关系,即last_committed值:binlog_transaction_depandency_tracking

  1. COMMIT_ORDERE: 基于组提交机制
  2. WRITESET: 基于写集合机制
  3. WRITESET_SESSION: 基于写集合,比writeset多了一个约束,同一个session中的事务 last_committed按先后顺序递增

控制事务的检测算法:transaction_write_set_extraction

  1. OFF
  2. XXHASH64
  3. MURMUR32

开启MTS功能后,务必将参数master_info_repostitory设置为TABLE,这样性能可以有50%~80% 的提升。这是因为并行复制开启后对于元master.info这个文件的更新将会大幅提升,资源的竞争 也会变大。 master_info_repository

若将slave_parallel_workers设置为0,则MySQL 5.7退化为原单线程复制,但将 slave_parallel_workers设置为1,则SQL线程功能转化为coordinator线程,但是只有1个worker 线程进行回放,也是单线程复制。然而,这两种性能却又有一些的区别,因为多了一次 coordinator线程的转发,因此slave_parallel_workers=1的性能反而比0还要差: slave_parallel_workers

MySQL 5.7后的MTS可以实现更小粒度的并行复制,但需要将slave_parallel_type设置为 LOGICAL_CLOCK,但仅仅设置为LOGICAL_CLOCK也会存在问题,因为此时在slave上应用事务的 顺序是无序的,和relay log中记录的事务顺序不一样,这样数据一致性是无法保证的,为了保证事 务是按照relay log中记录的顺序来回放,就需要开启参数: slave_preserve_commit_order

V.并行复制监控

show tables like 'replication%'

select * from replication_applier_status_by_worker;查看worker进程的工作情况

 四,读写分离

读写分离首先需要将数据库分为主从库,一个主库用于写数据,多个从库完成读数据的操作,主从库之 间通过主从复制机制进行数据的同步

 读写分离架构也能够消除读写锁冲突从而提升数据库的读写性能。使用读写分离架构需要注意:主从同步延迟和读写分配机制问题

一,同步延迟

使用读写分离架构时,数据库主从同步具有延迟性,数据一致性会有影响,对于一些实时性要求比较高 的操作,可以采用以下解决方案:

  • 写后立刻读

在写入数据库后,某个时间段内读操作就去主库,之后读操作访问从库。

  • 二次查询

先去从库读取数据,找不到时就去主库进行数据读取。该操作容易将读压力返还给主库,为了避免 恶意攻击,建议对数据库访问API操作进行封装,有利于安全和低耦合。

  • 根据业务特殊处理

根据业务特点和重要程度进行调整,比如重要的,实时性要求高的业务数据读写可以放在主库。对于次要的业务,实时性要求不高可以进行读写分离,查询时去从库查询。

二,读写分离分配机制

  • 基于编程和配置实现(应用端):

员在代码中封装数据库的操作,代码中可以根据操作类型进行路由分配,增删改时操作主库, 查询时操作从库。这类方法也是目前生产环境下应用最广泛的。优点是实现简单,因为程序在代码 中实现,不需要增加额外的硬件开支,缺点是需要开发人员来实现,运维人员无从下手,如果其中 一个数据库宕机了,就需要修改配置重启项目。

  • 基于服务器端代理实现(服务器端):

应用服务器并不直接进入 到master数据库或者slave数据库,而是进入MySQL proxy代理服务器。代理服务器接收到应用服 务器的请求后,先进行判断然后转发到后端master和slave数据库。

目前有很多性能不错的数据库中间件,常用的有MySQL Proxy、MyCat以及Shardingsphere等等

  • MySQL Proxy:是官方提供的MySQL中间件产品可以实现负载平衡、读写分离等。
  • MyCat:MyCat是一款基于阿里开源产品Cobar而研发的,基于 Java 语言编写的开源数据库中间 件。
  • ShardingSphere:ShardingSphere是一套开源的分布式数据库中间件解决方案,它由ShardingJDBC、Sharding-Proxy和Sharding-Sidecar(计划中)这3款相互独立的产品组成。已经在2020 年4月16日从Apache孵化器毕业,成为Apache顶级项目。
  • Atlas:Atlas是由 Qihoo 360公司Web平台部基础架构团队开发维护的一个数据库中间件。
  • Amoeba:变形虫,该开源框架于2008年开始发布一款 Amoeba for MySQL软件。

附: 参考资料《MySQL技术内幕 InnoDB存储引擎》  

猜你喜欢

转载自blog.csdn.net/qq_42773863/article/details/121322622