解决思路:ES无法正常同步数据

问题

近日接收到生产环境的一个bug——新注册的用户无法被搜索到

分析和定位

因为系统的搜索功能是通过ES去实现的,就以ES为例(无论是ES还是查数据库,思路都通用)

首先需要确认什么情况下会导致这种情况,1.没查到;2.没存到

没查到很好排除,先找ES中这个文档是否存在,再通过程序的查询条件去查就行

没存到也很好排除,找同步这个数据的接口方法去排查就行

具体步骤

首先确认数据库中的数据(ES的数据是从数据库同步过去的),数据库中存在该数据,再查询ES,ES也存在这条数据,但两条数据略有不同,ES中的某个字段值和数据库中不一致。

再对比没问题的数据,是ES的数据未能同步。

那么,问题的原因出在哪呢?接下来就该查日志了,很可惜的是,日志没有报错,说明程序运行一切正常,可程序运行一切正常,又怎么会同步不到呢?

于是对比正常的日志和那段时间的不正常的日志,发现ES同步更新的分片数不对,说明同步请求正常发送到了ES,但未更新,未更新的原因是什么呢?数据库的数据也没问题,为什么同步到ES的数据就有问题了?

带着问题继续往下分析:

现在要明确问题点是:数据库更新没问题,ES未能同步更新,但因为日志缺失,不知道发送到ES的数据有没有问题

接下来又到了假设环节,假设从数据库拿到的数据就有错,那确实可能出现这种问题,而拿到的数据没有错的话,那就是同步的环节出错了,而因为这个问题是偶发性的问题,无法实际确认

正当我准备为这个bug盖棺定论的时候,执行代码前的一些小东西引起了我的注意,因为这个接口在前面的程序员的努力下,这个接口的内容是极其混乱的,而我在回到方法开头的时候,发现方法加上了一个@Traditional的注解,也就是这个方法开启了事务,而在同步ES的代码逻辑这一块,可能是考虑到程序执行效率的问题,开启了线程池。

到这里,问题就很显而易见了;

接下来就去验证我们的想法,在线程池后面加上一个sleep,果然,每次的数据都无法同步到ES

原因

在事务中开启多线程会让事务失效

解决方法

相对于解决方法,思路是通用的,希望各位小伙伴好好看看思路

我是将线程池的逻辑单独抽离出来作为一个方法,在Service返回Controller后,也就是事务正常提交后,再调用线程池异步处理ES同步问题,这样既能保证程序运行效率,也能在ES同步出错的情况下不影响程序主流程的执行

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值