双主复制的数据补偿

双主复制,难点在于数据一致性的保证,这个在复制层面非常难实现,只有在某些特定的场景下才有折中的解决办法。

我们的双主复制方案的实际开发中,数据接入层对底层双向复制屏蔽了发生数据不一致的可能性。比如对数据进行切分,两地业务系统操作不同的业务数据,这样就不会导致数据不一致的发生,也就是核心在于两地的业务系统不能对同一行数据进行同时的更新。由于网络的不确定等因素,极易导致数据不一致的发生。于是在数据接入层的屏蔽后,底层的双向复制只需要专注于复制和控制回环的逻辑,而不必考虑数据一致性的判断。

这种架构将保证数据一致性的工作放入到了数据接入层,整套系统在正常运行的时候,是不会有异常情况的,然而在某个机房无法提供服务进行切换的时候,就没那么简单了。比如我们现有两个机房分别是A和B,假设A机房出现异常而无法继续对外提供服务,那么A的业务系统肯定切向B机房的数据库集群来继续对外提供服务,不然这套异地双活就没有意义了。

切换是一个非常危险的操作,虽然危险,但是对于停机很久的业务来说,还是一个比较好的解决方案。在发生异常的切换操作中,最主要的问题在于,A机房产生的同步数据,很有可能还没有传向B机房。这是一个很麻烦的问题,但是在A机房不可用的情况下,这部分数据肯定就认为是不可用了,所有的数据,应该以B机房的数据为准。

第二次切换,发生在A机房恢复,将A机房的业务回迁到A的时候发生。这个切换比第一次切换更加危险,因为流量都在B机房,而我们保证数据一致性的前提是不能对多个机房多写,所以在数据接入层,原先属于A的流量必须一次性切入A机房,不能存在某些连接在B机房,而某些连接在A机房的情况。

这种在数据接入层其实是可以实现的,实现方法这里就不多说了,不属于本文的范畴。在切换到A之前,由于A之前可能有部分同步数据没有同步到B,那么A中这部分数据在开启复制之后,很有可能会把新的在B中的数据覆盖,造成数据不一致,所以在开启同步之前,必须将A中的数据消耗完,并对这部分数据进行筛选和复制。这个概念就是数据补偿

数据补偿的基本思路就是分析binlog中的数据,并比对目标库中的行数据,在一个能比较版本新旧的维度上,进行过滤。所以版本新旧是一个必须要做的概念。binlog中的时间戳的精度为秒,肯定无法在秒级别做比较,所以我们在上层的代理层,自动添加一个字段并填充为微秒数值,我们的数据补偿在分析到binlog中的字段和目标库后的字段后,会进行分析,主要有以下几种情形:

Write rows
  • binlog中的版本比目标库新,这个情况不可能发生

  • binlog中的版本比目标库旧,说明目标库已经操作过这个字段了,我们需要将此行丢弃

  • binlog中的数据在目标库中不存在,说明目标库还未同步到此数据,这时候是否要丢弃,可能得看业务情况

Update rows
  • binlog中的版本比目标库新,应用到目标库

  • binlog中的版本比目标库旧,丢弃

  • binlog中的数据在目标库中不存在,说明目标库可能已经删除了此行数据,是否补偿看业务情况

Delete rows
  • binlog中的版本比目标库新,这个情况不可能发生,直接删除此行

  • binlog中的版本比目标库旧,说明业务可能在未切换前删除了某个记录,然而切换后此记录又出现了(未同步到新机房),此时用户没有删除,并且做了某些更新操作,这种情况处理具体得看业务情况,建议不删除

  • binlog中的数据在目标库中不存在,说明目标库也删除了此行数据,是否补偿不妨碍最后结果

很多策略都是需要考虑到业务情况才能做出具体的解决方式,建议在处理的时候,遇到无法判别的场景,需要操作者来手工确认该数据。这部分数据建议也归档,便于后期根据逆向执行binlog来恢复数据。

共 0 条回复
暂时没有人回复哦,赶紧抢沙发
发表新回复

作者

sryan
today is a good day