MySQL高可用的基石

在分布式系统中,单机节点在产生故障时无奈提供服务,这可能导致长期的服务不可用,从而影响其余节点的运作,导致的结果十分重大

为了满足服务的高可用,往往是通过节点冗余(新增雷同性能的从节点),当产生故障时进行主从切换,让从节点成为新的主节点来持续提供服务

比方:MySQL的主从、Redis的主从、MQ broker的主从...思维大体相似的

作为高可用的基石——主从架构功不可没,本篇文章就来聊聊MySQL的主从的一些细节

binlog

binlog作为逻辑上复原数据的日志,是主从数据同步、数据恢复的根底

binlog分为三种格局:statement、row、mixed

statement :记录写操作的SQL,语句轻量、传输快,应用该格局可能会导致数据不统一(因为从机与主机所处的环境不同,比方从机工夫与主机不同时,应用now()函数)

row : 记录数据的批改,数据量大、传输慢,误操作时能够复原数据(反向操作),主从同步时数据统一

mixed :联合statement、row的长处,主动混合选择格局

大多数状况下都是抉择格局为row,因为数据统一并且能够复原数据

主从复制

往期文章中说过当收到写操作须要批改数据时,为了满足数据的一致性,会写undo log(原子性)、redo log(持久性)、binlog等日志

当主节点接管到写操作更改数据时,也须要对从节点进行数据的批改以此来达到数据统一

在主从复制数据依附的就是binlog,大抵流程分为三个阶段:

  1. 主节点dump线程监听binlog变动告诉从节点
  2. 从节点应用IO线程接管binlog并将其写入本地 relay log(中继日志)
  3. 从节点应用SQL线程依据relay log复原数据

在单机中写完日志即可提交事务响应,而在主从中依据响应阶段的不同,主从复制的形式分为多种:

同步复制:所有从节点都响应(复原完数据)主节点才响应,性能差、数据强统一

异步复制:主节点告诉完从节点就立马响应,性能最好,存在提早有数据一致性问题

半同步复制:只有有一个从节点响应主节点就响应,一主一从下与同步复制统一,网络超时进化为异步复制

加强半同步复制:在半同步复制的根底上,主节点收到响应后才提交事务,数据一致性会比半同步好,但性能稍差

提早复制:从节点提早一段时间复原数据,这样即便产生误操作也能够进行回滚数据

主从切换

当主机产生故障时须要将从机切换为主机

不同策略

个别中间件的主从切换都只能在CAP实践中满足其二,即在分区容错(P)下只能满足牢靠(C)或可用(A)

binlog上会记录主节点写操作的工夫,从节点会保护一个 seconds_behind_master 来记录主从提早的工夫

在牢靠策略下,须要等到旧的从节点实现所有的数据恢复(即seconds_behind_master为0)才成为主节点,提供写服务

在此期间只提供读服务、无奈提供写服务,因而牢靠策略会损失肯定的可用性,取决于主从提早的工夫

在可用策略下会立刻将从节点设置为新的主节点提供读写服务,某些场景下可能导致数据不统一

假如id自增,记录格局为(id,name),新增数据a,b,c

  1. 主节点曾经新增(1,a),(2,b),(3,c)时宕机
  2. 从节点可能只重做数据(1,a),(2,b) 而(3,c)还在中继日志中
  3. 此时旧的从节点成为新的主节点又持续提供写服务,须要新增d,新增完d后才将中继日志的数据进行复原

如果应用的binlog格局为statement或mixed,则会新增为(3,d)和(4,c)

如果格局为row,则会主键抵触报错,新增(3,d)后中继日志为(3,c)

在可用策略下可能导致数据不统一,应用row会提前裸露数据不统一的问题

基于GTID的主从切换

GTID 全局事务ID

格局为 server_uuid:gno

server_uuid 为节点标识

gno 为事务标识(事务提交时取得,全局自增)

在进行主从切换时,每个从节点同步数据的日志偏移量都不同,个别会找最新偏移量的从节点为新的主节点(这个偏移量是须要运维去定位的)

在GTID 全局事务ID进去后,binlog中每个事务有对应的GTID则能够通过GTID主动定位偏移量,不必手动定位

主从提早

起源

默认状况下主从复制会应用异步复制,而在主从架构下个别会应用读写拆散,主机服务写操作,从机服务读操作

因为应用异步复制,主从之间的数据一致性会存在肯定的提早,物理上主从会放在同一机房中,网络通信忽略不计,老本最大的就是从机SQL线程解析日志复原数据的过程

如果复原数据是一些大事务时会导致很长的提早,比方在主机上执行批量操作耗时5s,在从机上执行时也会耗时那么久(资源大略统一)

可能写完操作就会进行读操作,如果此时从库还未重做数据就会导致写完查不到的数据不统一状况

先来看看哪些状况可能会导致主从提早太长:

  1. 业务高峰期频繁读写(高TPS),从机不仅要同步数据,还要解决读操作
  2. 解决大事务,大事务导致延迟时间太久
  3. 从机硬件配置低,导致跟不上主机IO速度
  4. 主从机器可能参数不同(缓冲池、IO参数...)
  5. 从机自身就是提早复制

...

当主从提早过长时能够思考应用计划缩短提早:

  1. 调整redo log\bin log刷盘策略,加强IO
  2. canal监听(告诉改为监听)
  3. 从机并行复制

从机并行复制借助于redo log、bin log两阶段提交时,redo log prepare阶段不会有锁抵触,能够并行执行

并行复制就是基于两阶段提交中的组提交,能够调整以下两个参数拉长组提交的工夫,减慢主机写,放慢从机重做数据

binlog_group_commit_sync_delay 提早多少微秒后才调用 fsync

binlog_group_commit_sync_no_delay_count 累积多少次当前才调用 fsync

数据不统一解决方案

为了防止长时间的主从提早,从机应该和主机有雷同的参数、配置,并且要防止大事务

在业务高峰期还是可能存在主从提早导致数据不统一,须要应用一些计划进行防止:

  1. 沟通业务:期待一段时间,比方用户批改完材料后进行审核状态
  2. 强一致性的读也走主库:这样就不存在主从提早,使用方便,大量强一致性读操作就会导致主机压力大
  3. 期待从机没提早(三种判断形式):

    • 比拟 seconds_behind_master 是否为0,为0阐明没提早
    • 比拟主从上的位点 Master_Log_File 和 Read_Master_Log_Pos(主库的最新位点)Relay_Master_Log_File 和 Exec_Master_Log_Pos(备库执行的最新位点)判断是否雷同,雷同则没提早
    • 比拟从机上GTID汇合 Retrieved_Gtid_Set 和 Executed_Gtid_Set (备库收到的所有日志的 GTID 汇合 和 备库所有曾经执行实现的 GTID 汇合)是否雷同,雷同则没提早

    这个计划粒度大(实际上只须要判断事务是否重做,这里是始终判断是否有提早),如果高峰期始终有提早就会始终期待判断,不应用

  4. 批改主从复制形式为同步复制:数据强一致性,性能差
  5. 批改主从复制形式为半同步复制:一主一从下与同步复制雷同,一主多从下查问不确定,须要判断该事务是否已重做

计划5须要做到细粒度的判断事务是否在从机上曾经重做,有两种形式且实现较为简单

判断偏移量

select master_pos_wait(file, pos,[timeout]) 用于判断以后偏移量是否曾经超过该地位

file 为 binlog 文件,pos 为 偏移量,timeout为期待的工夫

应用半同步复制时,一个从节点曾经响应,其余从节点应该也是快要响应的状态,因而能够期待一段时间 50ms,100ms...

如果超时则能够在业务中再去查主机,要留神如果都超时就相当于又全打在主机上

通过该SQL可能以主库日志中偏移量的形式判断是否已执行该事务(已执行返回0):

  1. 写操作实现时顺便获取binlog文件和偏移量的信息
  2. 携带这两个参数加上超时工夫应用该SQL判断是否已执行
  3. 如果返回0(已执行)则查从机,否则查主机(留神限流)
判断GTID

判断GTID的思路与下面类似

select wait_for_executed_gtid_set(gtid_set, [timeout])

SQL的作用是判断是否曾经执行GTID汇合 返回0,超时返回1

流程相似:

  1. 写操作时获取GTID汇合
  2. 依据GTID汇合判断从机是否已执行事务
  3. 已执行查问,否则查主库或限流

主从架构

因为binlog的数据复制,主从架构能够十分丰盛,想怎么搭就怎么搭

一主一从:主负责写,从负责读,读写压力平分

一主多从:主负责写,从负责读,适宜读多于写

双主热备:两个节点互为主从,读写压力平分,但存在循环同步的问题

当AB节点互为主从时,A收到写申请,要把bin log给B重做,B重做完(相当于写申请)又会把bin log给A重做,这样就会导致循环同步数据

在同步数据时携带节点的id(server id)解决循环同步问题

A收到写申请,binlog给B并携带本人的id,B重做完又把binlog给A,A发现binlog上server id是本人则不进行重做

总结

本篇文章以MySQL高可用为终点,聊到MySQL中的主从复制、切换、提早、架构等

binlog的statement格局记录SQL,数据量小、传输快,但可能导致数据不统一

binlog的row格局记录批改数据,数据量大,传输慢,能够修复误操作数据

binlog的mixed混用statement、row的长处,在可用策略的主从切换还是会导致数据不统一

主从复制时主机dump线程监听binlog变更告诉从机拉取,从机io线程将日志写入realy log中继日志,再由sql线程解析日志重做数据

同步复制须要所有从机响应,领有强一致性,但性能最差

默认的异步复制性能最好,但可能提早时会有数据一致性

半同步复制只须要一个从机响应,多从下性能好于同步复制,网络超时会应用异步复制

加强的半同步复制会在从机响应时才提交事务,相比于半同步复制一致性略好

提早复制能够让从机提早一段时间重做数据,误操作数据能够复原

主从切换时只能满足CAP中其二,满足牢靠会导致一段时间不可写,满足可用可能会呈现数据不统一

把从机参数、配置调整为主机雷同,防止应用大事务能够防止主从提早太长

当主从提早太长能够通过调整从机IO参数加强IO能力

产生主从提早的数据一致性问题时:

  1. 沟通业务,是否应用审核等中间状态,等提早过了再查看
  2. 强制走主机,留神压力可能太大
  3. 应用同步复制,性能差
  4. 应用半同步复制,一主多从下须要判断事务是否执行(偏移量/GTID),实现艰难

罕用的主从架构有:一主一从、一主多从、双主热备(通过server id解决循环同步问题)...

最初(不要白嫖,一键三连求求拉\~)

本篇文章被支出专栏 MySQL进阶之路,感兴趣的同学能够继续关注喔

本篇文章笔记以及案例被支出 gitee-StudyJava、 github-StudyJava 感兴趣的同学能够stat下继续关注喔\~

有什么问题能够在评论区交换,如果感觉菜菜写的不错,能够点赞、关注、珍藏反对一下\~

关注菜菜,分享更多干货,公众号:菜菜的后端私房菜

本文由博客一文多发平台 OpenWrite 公布!