👽System.out.println(“👋🏼嗨,大家好,我是代码不会敲的小符,双非大四,Java实习中…”);
📚System.out.println(“🎈如果文章中有错误的地方,恳请大家指正!共同进步,共同成长✊”);
🌟System.out.println(“💡如果文章对您有所帮助,希望您可以三连支持一下博主噢🔥”);
🌈System.out.println("🚀正在完成计划中:接下来的三个月里,对梦想的追逐 ");
背景:在写毕设的全文检索功能时,要把题目的数据同步到es,考虑到一个问题,如何保证数据库和es的一致性呢?考虑方案如下:
- 双写:先操作数据库,再操作es
- mq异步: 先操作数据库,然后异步通知去操作es
- 定时同步:定时扫描数据库的表,批量操作es
- 监听binlog同步:通过监听数据库变更时产生的binlog更新es
最终实现:监听binlog同步es,基于canal做数据同步的方案
双写
@Transactional(rollbackFor = Exception.class)
public void subjectAdd(SubjectInfo subjectInfo) {
//更新数据库
updateDb(subjectInfo);
//更新ES
updateEs(subjectInfo);
}
实现简单,实时性高。需要把操作数据库和操作es放到一个事务中,如果有失败会异常回滚保证数据一致性。
- 问题:如果es仅是超时但是操作成功,这时数据库回滚,会导致数据库和es数据不一致
- 解决:重试,保证数据一致性
缺点:需要修改代码,有侵入性,事务拖长导致数据库连接被占用,影响性能
mq异步消费
方法一: 数据库和es各有一个监听,监听到消息后,各自去做数据变更,失败就重试
方法二: 数据库操作变更后,异步发消息通知es数据更新。
优点: 代码解耦,异步操作,提高了性能
缺点: 稍微有点延时
定时扫表同步
定时任务扫描数据库表, 然后批量更新ES
优点: 没有侵入性,原代码不需要修改
缺点: 实时性差,数据库压力可能会有性能问题
监听binlog同步
利用数据库变更时产生的binlog来更新ES。通过监听binlog来更新ES中的数据
优点: 没有侵入性,原代码不需要修改
缺点: 基于binlog监听,需要引入第三方框架。有一定的延迟
最后
慢慢的来,别着急!学会有质量的走过每一步
我是代码不会敲的小符,希望认识更多有经验的大佬,也在努力摸索出自己的道路
欢迎添加小符微信:A13781678921,一起加油