暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

关于ES数据同步方案

爱搞事的程序猿 2021-10-13
3340

前言:

       最近在公司里我们小组的技术选型进行了一次更新,影响说大也不大 说小也不小。笔者所在的小组是做订单中台业务的,与其他中台的关联非常的多,所以无论是在PC端还是在APP端对于订单这块的数据"读"操作有很多,而这次更改的技术应用方案则是需要保持订单列表的数据强一致性(目前查询是使用的ES)。


先来说说目前的几个可用方案。



第一种:同步双写


这是一种最为简单的实现方式,在将数据写入mysql时,同时也将数据写入到es中。

优点:逻辑比较简单,容易理解


缺点:风险比较高,有可能存在双写或者是单写的数据失败问题,即有可能因为应用间网络故障而导致写入es失败,或者是出现数据库的写入失败等一系列问题,从而导致不能保证强一致性。有人说可以将双写添加事务来保证写入到mysql和es中的数据一致,但是添加事务后,性能下降更加明显。




第二种:异步双写


针对上面的同步双写可能出现的性能和数据丢失问题,可以考虑引入MQ来实现异步双写(笔者公司使用的kafka和RabbitMq)

优点:由于MQ的性能基本比mysql高出一个数量级,所以性能可以得到显著的提高。


缺点:增加了业务耦合度,代码中复杂度增加。使用MQ时有可能出现网络故障等原因导致消费者不能及时消费(即数据不能及时写入),最终导致用户写入的数据不能及时查看到。



第三种:定时器(笔者所在小组目前使用的技术)


我们在数据库的相关表中增加一个类型为timestamp的字段,任何crud操作都会导致该字段的时间发生变化;原来程序中的crud操作不做任何变化;增加一个定时器程序(京东内部叫Worker),让该程序按一定的时间周期扫描指定的表,把该时间段内发生变化的数据提取出来;逐条写入到ES中。如下图所示


我们自己设定的时间是隔两分钟执行一次定时任务,并且同时新增两个数据同步接口,第一个接口是可以根据单个或者是多个订单id去同步数据到es中;第二个接口是同步所有订单数据到es中。这两个接口的原理都比较简单,主要是应用于在定时任务未执行的时间间隔去同步数据,以及防止定时任务执行期间数据未同步的问题(手动同步)


优点:不改变原来的代码,没有侵入性;没有业务强耦合。


缺点:时效性比较差,因为定时器的工作周期不可能设定在秒级。频繁的轮询数据库,导致给数据库一定的压力



第四种:使用同步插件


具体插件的使用可以看看这篇文章:

https://www.cnblogs.com/jpfss/p/10832918.html,其实其中的原理和第三种方都是相近的,只不过实现的方式不一样。



PS:目前笔者小组打算暂时放弃掉ES,因为目前ES同步的方法并不能完全解决数据展示的延迟性问题。所以关于列表的"读"操作直接通过读取mysql来解决一致性问题。当然这种方式也会存在弊端,比如数据量猛增而出现的性能瓶颈,或者是高并发情况下的效率问题,乃至于有可能因为订单这个模块的查询业务影响到了其他模块对mysql的读写操作。很多时候鱼与熊掌不可兼得,希望在接下来可以想到更加好的解决方案。


文章转载自爱搞事的程序猿,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论