CQRS(Lagom)架构下Elasticsearch读侧数据可靠性与一致性问询
关于Elasticsearch在CQRS(Lagom)读侧的持久性与一致性问题解答
嘿,咱们一步步来拆解你的问题,结合你类Twitter地理应用的场景,把这些点讲清楚:
首先,先搞懂「数据持久性」到底是什么
简单来说,数据持久性就是系统承诺:一旦你确认写入成功,这些数据就不会因为系统重启、硬件故障、网络问题等意外情况丢失,能稳定地被存储起来,在需要的时候可以完整读取。
Cassandra的设计核心就是优先保证持久性和可用性,它的写入流程会把数据同步到多个副本,就算个别节点挂了,数据也不会丢;而Elasticsearch的核心目标是搜索性能和实时性,它的写入机制是为了更快地让数据可搜索,所以在持久性上做了一些权衡——这也是为什么大家说它不是最可靠的存储的原因。
读侧用ES会不会出现数据未导入、丢失的情况?
答案是:会,但都是有特定场景的,不是“随机”发生的:
- 数据未正确导入:比如你用批量导入(
bulk)的时候,个别请求失败没处理(比如字段类型不匹配、集群过载拒绝写入),就会导致这些数据没进ES;还有ES的写入是先写内存缓冲区,默认1秒才会刷到磁盘的分段文件,如果这期间节点突然挂了,缓冲区里的数据就没了。 - 数据丢失风险:极端情况下会有。比如你没配置副本(
number_of_replicas: 0),主节点挂了且数据没备份,那这部分数据就没了;或者主节点挂的时候,副本还没同步完最新的数据,新选的主节点就会用旧的副本数据,导致最新的几条数据丢失。但正常配置(比如至少1个副本)的话,全部数据消失的概率极低,一般都是局部的、少量的数据丢失。
类Twitter地理应用场景下,ES作为读侧的可靠性够不够?
完全够!你的场景里,ES只是用来做读侧的搜索、地理范围查询,核心的事件数据都存在Cassandra(写侧)里,这就相当于有了“唯一真相源”。
哪怕ES偶尔丢几条数据,用户可能只是刚发的内容搜不到,过会儿重放事件补进去就好了,这种程度的不一致在社交应用里用户是可以接受的——毕竟Twitter本身也偶尔会有“刚发的推文搜不到”的情况。而且ES的地理查询性能是Cassandra没法比的,用它做读侧刚好能发挥它的优势。
怎么重放事件保证ES和写侧数据一致?
结合Lagom的CQRS架构,你可以这么做:
- 保证事件日志的不可变性:Cassandra里的事件必须是只读的,不能修改或删除,这样重放的时候才能拿到完整的历史数据。
- 实现事件消费者的幂等性:给每个事件分配唯一的ID,ES在导入的时候,先检查这个事件ID是否已经处理过(比如用ES的
_id绑定事件ID),避免重复导入导致数据重复。 - 利用Lagom的事件流偏移量管理:Lagom会记录消费者的偏移量(也就是已经处理到哪个事件了),一旦发现ES数据不一致或者丢失,你可以重置偏移量,从某个时间点或者从头开始重放事件到ES。
- 定期快照ES状态:定期给ES做快照备份,万一ES集群彻底挂了,可以先恢复快照,再只重放快照之后的事件,不用从头处理所有历史事件,节省时间。
- 监控导入状态:监控ES的写入成功率、消费者的偏移量进度,如果发现偏移量落后太多或者写入失败率高,自动触发重放流程。
- 增量重放机制:平时可以只重放最近未同步的事件,比如每小时检查一次ES和Cassandra的事件差,把缺失的补进去,保持数据的一致性。
总结一下:ES作为CQRS读侧是非常合适的选择,只要你依赖写侧Cassandra的可靠事件存储,再配上完善的事件重放和监控机制,就能把ES的持久性风险降到最低,同时享受到它的搜索性能优势。
内容的提问来源于stack exchange,提问作者Trace
相关产品推荐
相关产品推荐

