MySQL 与 Elasticsearch 双写一致性
场景引入 如果你设计了一个类似 B 站的视频网站中的搜索系统,或许在初期 MySQL 的 like 模糊搜已经能满足你对视频的标题、简介的搜索需求。 SELECT * FROM videos WHERE title LIKE '%'||:search_term||'%' OR description LIKE '%'||:search_term||'%'; 如果后期系统视频的量级上来了,对性能有一定要求了,你或许已经开始考虑 ES 了。后面如果你还想让与搜索关键词相关的创作者名称、视频评论、关联标签也能级联视频搜出来,甚至弄一个各种业务维度的融合公式,那么 ES 这样的搜索引擎再适合不过了! 但是,如果数据写一份 MySQL,还要落一份 ES 来支撑筛选/搜索,要怎么写入两个异构的存储系统、并保证它们的一致性呢? [!NOTE] 如果你有更好的场景欢迎提出/补充~ 方案一:同步双写 优点 简单粗暴 ES 同步写入快 缺点 业务耦合,扩展性差,代码侵入性强(要在写 MySQL 的地方后写 ES 的代码,要在代码设计上做好收敛) 影响性能,写入两个存储,响应时间变长(本来 MySQL 的写入性能不是很高,再加一个 ES,系统的性能必然会下降),吞吐也会下降 存在双写失败丢数据风险(比如写完MySQL,ES 就挂了) 方案二:异步双写 优点 性能高 不易出现数据丢失问题,主要基于 MQ 消息的消费保障机制,比如 ES 宕机或者写入失败,还能重新消费 MQ 消息 多源写入之间相互隔离(业务侧只管发消息),解耦数据生产者和消费者,便于扩展更多的数据源写入 缺点 同样存在业务耦合的问题,写完 DB 之后,还需要发个 MQ(代码设计上做好收敛,也可以关注一下所用 orm 框架有没有 hook 之类的能力,支持你“写后 xxx”) 接入新的数据源需要实现新的消费者代码 系统复杂度增加,引入了消息中间件 MQ是异步消费模型,存在延迟问题 [!tip] MQ 可以缓冲和 DB 的负载能力不一致问题 ...