mysql数据同步es踩坑记

匿名 (未验证) 提交于 2019-12-02 22:02:20

背景:

需要把mysql的数据同步到es中。由于没有维护canal集群, 我们选择了通过记录最后一次同步数据的update_time来进行数据同步。

?

具体的做法,当有数据变更的时候,发个消息,表示需要进行数据同步。

消息的监听者加锁串行执行,?从要同步数据的表中获取上一次update_time之后的数据,并且把最后一条记录的update_time更新回去。

比如说有用户表

user

id:int

name:varchar

update_time:datetime

?

sync_log

syc_table_name

last_update_time

?

从sync_log中获取last_update_time, 执行sql: select * from user where update_time>=last_update_time.

?

问题:

我们当时限制了一次取一千条出来,发现在有DB工单执行,批量更新数据出现了死循环,

导致所有MQ消费线程被占用,其他消息无法消费,产生了消息堆积,因为写了一段代码

结果集=select * from user where update_time>=last_update_time limit 1000

while(非空结果集合){

同步数据

结果集=select * from user where update_time>=last_update_time limit 1000

}

一般情况是不会有问题的,当一秒有大量更新的时候,比如说一秒有2000条更新记录就有问题了。

问题的核心就在于,如何进行分页。

因为当你进行同步数据的时候,可能这一秒还会有数据进行产生。

?

情景:

last_update_timeΪ03/11 08:00:00

在08:00:00这一秒有2000条数据被更新,?

那么当所有的数据都处理完以后last_update_time还是03/11 08:00:00, 因为要防止这次同步完成以后08:00:00还有数据?

如果每一次取出来所有数据,不进行分页可以处理,但是同步的数据量大要进行分页怎么办?

?

解决方案

每次进行数据获取(1000条), 拿到最后一条记录的update_time, count(update_time) 如果数量>=1000

则Sleep(1S)之后再次处理这一秒的所有数据,并且把last_update_time更新为update_time+1s跳出这1秒

?

另外可以加一个死循环跳出的判断,比方说一秒不可能产生1W的记录,那么循环10次以后就进行跳出。

其他坑:

1. 当有异常的时候进行重试,或者放弃。

2. 如果一次同步时间过长,其他的消费线程会进行等待,也可能会造成其他MQ主题消费阻塞,可以限制消费线程等待的最大时间,如果最大时间还没有被执行,丢入延迟队列,或者直接抛弃(这种造成延迟同步,需要等到下一次变动触发更新)

3. 当程序刷数据的时候,变更的MQ发送量会非常大,可以做一些处理,比方说1秒钟内超过了5个变更,那么sleep几秒(或者发送延迟队列)再进行消息发送,这X秒内变更直接抛弃。

?

?

?

?

?

?

?

?

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!