MySQL之不得不说的keepsync和trysync

勿忘初心2018-10-19 18:30

此文已由作者温正湖授权网易云社区发布。

欢迎访问网易云社区,了解更多网易技术产品运营经验。


开宗明义,keepsync和trysync是网易MySQL分支版本InnoSQL的两个参数,非常重要的两个参数。从某种程度上说,他们决定了MySQL主从复制实例是采用异步复制(async)还是半同步复制(semi-sync)。为什么不得不说呢,因为不断有同学问怎么看当前RDS实例是同步还是异步状态,keepsync和trysync这两个参数是干嘛用的,怎么进行设置?于是简单写下semi-sync和这两个参数关系。


MySQL semi-sync

在MySQL中有个非常著名的semi-sync插件(plugin),或者叫半同步插件。如果将主从复制作为一个系统, 处于半同步下的主从复制系统,即使主库MySQL宕机且无法修复,只要从库MySQL正常, 用户向该系统发送的已经返回commit的请求数据仍然不会丢失,满足事务ACID中的D(Durability)。这是在MySQL传统的异步复制体系下迈出的非常具有里程碑意义的一步,其实在这一点上,InnoSQL一直处于领先的位置。为什么叫半同步复制,而不是同步(全同步)复制,这是因为在semi-sync复制下,主库MySQL上事务记录的Binlog信息,发送给从库MySQL,在从库MySQL的IO Thread将其以Relay-Log形式(本质上还是Binlog,只不过披了一个马甲)持久化后即向主库MySQL返回ACK信息,而不是在SQL Thread(其实已经不是一个Thread了,姑且这么说吧)将该事务对应的Relay-Log在从库MySQL上执行后才返回ACK(这个就是全同步)。semi-sync之所以不丢数据,原因就在于主库只有收到从库ACK信息后,才会给用户/客户端返回事务已提交。显然此时只要从库存放Relay-Log的硬盘不坏,数据是不会丢的。不过最近看来,很不乐观。:)


虽然有这么牛X一个插件,但默认情况下MySQL复制还是异步的。要开启semi-sync,还是简单做几个操作。先要在主从上都安装semi-sync插件(主: INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';从:INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';);然后还要设置几个参数(主:rpl_semi_sync_master_enabled=1;从:rpl_semi_sync_slave_enabled=1);当然,要从异步状态切为同步状态,还需要重新start slave。在上述都做了之后,通过Rpl_semi_sync_slave_status 状态值可以查看当前复制是否已经是semi-sync状态(状态为ON)。是不是敲简单。正常的,人一旦理解了一个技术或掌握了一个知识点,就会觉得其实挺简单的。需要注意的是,semi-sync在某些场景下会退化为异步,如果用户不知情,刚好这个时候主库MySQL挂了,那就悲剧了(丢数据了),所以,监控Rpl_semi_sync_slave_status状态挺重要,当然,MySQL还提供了其他几个状态用来观察semi-sync复制状态。那么什么时候会退化为异步呢,就得来说说rpl_semi_sync_master_timeout,超过所设置的微秒数后,主库MySQL退化为异步复制。默认时间为1000,也就是如果主库发送Binlog后,从库1s之内没有返回ACK,主库就切异步了。如果用户不想轻易切异步,就需要设置一个更大的值。但设置大了又会带来了其他问题。


InnoSQL增强

为了更好得掌控实例semi-sync和async状态切换,在InnoSQL中新增了两个参数rpl_semi_sync_master_keepsyncrepl和rpl_semi_sync_master_trysyncrepl。用来更灵活得控制状态切换行为,部分取代rpl_semi_sync_master_timeout的作用,两者的取值均为ON/OFF。当然,这两个参数不是独立起作用的,而是在前面所述的参数基础上发挥作用的。不知不过前面所述的参数变为了必要条件而非充分条件。


也就是说,即使rpl_semi_sync_master_enabled、rpl_semi_sync_slave_enabled均为1,如果rpl_semi_sync_master_trysyncrepl为OFF,复制状态也无法从async切换为semi-sync。处于semi-sync状态,即使rpl_semi_sync_master_timeout微秒内从库未返回ACK信息,如果rpl_semi_sync_master_keepsyncrepl为ON,则复制状态也无法从semi-sync切为async。只有在用户/系统管理员将rpl_semi_sync_master_keepsyncrepl改为OFF后才能切为async。


这里引出一个问题,用户怎么决定要不要切异步,根据什么状态来进行判断呢? 显然,一个事务已经花了多少时间等待ACK这个状态非常关键,但MySQL并没有提供该信息给用户,于是在InnoSQL中加入了事务的ACK等待时间状态,可用通过show processlist获取ACK_WAIT_TIME或information_schema.processlist中的ACK_WAIT_TIME来了解每个事务已花费的等待ACK时间状态。用户可规定一个阈值,通过查询ACK_WAIT_TIME字段,如果有事务超过了阈值,那么就设置rpl_semi_sync_master_keepsyncrepl为OFF切异步。


RDS使用方式

接下来进一步聊下网易云RDS如何使用semi-sync。RDS提供了两种高可用实例,分别是同步实例和异步实例,但不管同步还是异步实例,semi-sync插件均启用,且rpl_semi_sync_master_enabled、rpl_semi_sync_slave_enabled均为ON。区别在于rpl_semi_sync_master_trysyncrepl和rpl_semi_sync_master_keepsyncrepl值,同步实例两个参数均为ON,异步实例两个参数均为OFF。RDS支持用户将异步实例修改为同步实例,重要的一步就是rpl_semi_sync_master_trysyncrepl和rpl_semi_sync_master_keepsyncrepl设置为ON,也支持同步实例修改为异步实例,即将其设置为OFF。


同步实例在出现从库MySQL返回ACK超时(卡主)的时候,目前超时设置为5s,会由RDS管理服务器将该实例设置为修复中,实例复制临时转为异步模式(关闭rpl_semi_sync_master_trysyncrepl和rpl_semi_sync_master_keepsyncrepl),重试从库MySQL重启,重新建立到主库的复制关系,并尝试转为同步模式(开启rpl_semi_sync_master_trysyncrepl和rpl_semi_sync_master_keepsyncrepl),确认Rpl_semi_sync_slave_status为ON之后(即转同步成功),将实例重新置为可用/运行中。


最后,上述描述仅聚焦于semi-sync的一些参数和状态,并没有详细介绍semi-sync的原理、实现,介绍说明启用semi-sync的具体步骤。


网易云数据库RDS是一种稳定可靠、可弹性伸缩的在线关系型数据库服务,当前支持MySQL引擎,提供基础版,高可用版,金融版针对不同业务场景的高可用解决方案,点击可免费试用


网易云免费体验馆,0成本体验20+款云产品! 

更多网易技术、产品、运营经验分享请点击


相关文章:
【推荐】 SpringBoot入门(二)——起步依赖