mysql重启后es同步失败_mysql数据同步es踩坑记

本文讲述了在没有使用canal的情况下,通过last_update_time进行MySQL数据同步到ES的挑战。核心问题在于处理高并发更新时的分页策略,作者提出了每秒分批处理和延时处理策略,以及应对异常和资源限制的方法。
摘要由CSDN通过智能技术生成

背景:

需要把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秒内变更直接抛弃。

?

?

?

?

?

?

?

?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值