1,背景
随着业务发展,公司初创伊始延续下来的it项目,会出现:边界不清晰,指责混乱,重构在所难免。
重构的时候,需要重新设计库表,并重新编码实现业务。一般会对系统进行模块拆分和边界划分,同时为了安全起见,还会引入金丝雀发布环境。
所以在一段时间内,系统是存在两个异构的底层数据,以及新旧两个系统共存。这就要处理好异构数据的双向同步问题。
2,方案
使用canal,上传binlog到kfk,然后写py脚本消费kfk消息。https://blog.csdn.net/yehongzhi1994/article/details/107880162
3,问题
3.1,主键冲突问题
新旧数据同时增加记录,可能会出现id相同但是业务意义不同的记录。双向同步的时候会主键冲突。
3.2,数据回环问题
如果同一时刻,新旧数据的同一个记录的相同字段都发生了修改。那么新旧数据都会发送binlog到对方,对方更新后还会继续向对方发送binlog。
4,解决方案
4.1,主键冲突问题
新旧表的主键全部使用雪花id生成器,而不再使用自增id。
4.2,数据回环问题
网上有几种解决方案:https://blog.csdn.net/zl1zl2zl3/article/details/88921769
解决思路就是:如何丢弃掉binlog被消费后产生的binlog,新旧数据都有修改时允许作出取舍,但是要保证新旧数据一致性。
我们采用了一种投机的方案:新库的表都增加一个字段 sync_remak datetime ON UPDATE CURRENT_TIMESTAMP。具体原理是:如果是业务代码修改数据,那么sync_remark字段的值就是当前时间,如果是binlog消费过程中修改了数据,就指定一个很早的时间点(比如1980年)。这样在消费binlog的时候,只要判断binlog的sync_remark是1980,就认为是通过binlog更新的数据,直接丢弃这个binlog。
我还想到一个方案:
新库消费binlog前,先查询本地对应的记录。对比updatetime:
如果binlog的updatetime大于本地的updatetime,就更新;
如果binlog的updatetime小于或等于本地的updatetime,就丢弃,同时根据本地的当前数据伪造一个binlog发送到kfk,让旧库去消费。
旧库消费binlog,正常消费。