一.业务场景举例
需求:
一个卖房业务,双十一前一天,维护楼盘的运营人员突然接到合作开发商的通知,需要上线一批热门的楼盘列表,上传完成后,C端小程序支持按楼盘的名称、户型、面积等产品属性全模糊搜索热门楼盘。
需求分析,提取其中的关键点:
1.功能需求:按楼盘的名称、户型、面积等产品属性全模糊搜索;
2.非功能需求(比如性能、安全等):双十一期间,楼盘搜索QPS预计在800左右,搜索完成后展示的楼盘字段信息非常多。
假设底层使用Mysql数据库存储,用户输入楼盘的名称、户型、面积等产品属性,支持全模糊查询,就无法走索引,如果QPS并发上来后,数据库很容易被打爆,所以我们需要考虑其他的存储方案。
通过技术调研发现,在全文搜索领域,ES已经成为事实的标准方案,它有很多优势:
(1)高性能;
(2)分布式部署,水平扩容;
(3)准实时。
所以综合考虑,最终我们在方案选型上选择了ES,热门楼盘在运营后台完成新增或修改,写入Mysql后,将数据库的变更记录同步到ES中,那如何保证Es与Mysql的数据一致性?
解决方案:
1.ES与数据库双写方案;
2.MQ异步写入方案(大厂第二推荐);
3.定时任务同步方案;
4.监听Binlog异步同步方案(大厂第一推荐)。
具体使用哪种方案,还需根据自身业务场景来定,接下就对这四种方案分别进行优缺点的分析。
二.ES与数据库双写方案
在数据库写入Mysql的同时,通过编程逻辑将相同的数据写入ES。(串行写入数据)
优点:
1.实时性:数据变更能够立即反映到Elasticsearch,保证了查询的实时性;
2.简单性:实现起来相对简单,不需要引入额外的组件或复杂逻辑。
缺点:
1.性能影响:每次写入MySQL的同时写入Elasticsearch,可能会对两个系统的性能都产
生影响;
2.数据一致性风险:在高并发情况下,可能会遇到双写失败导致数据不一致的问题;
3.系统耦合:每个写入操作都需要双写逻辑,增加了业务逻辑的复杂性和维护难度。
实现步骤:
1.代码修改:在业务逻辑中,对于每次对MySQL的写入操作,复制相同的逻辑到Elasticsearch;
2.事务管理:使用数据库事务确保操作的原子性,避免数据不一致;
3.性能优考:虑使用批量写入或异步处理来减少对性能的影响。
三.MQ异步写入方案
利用消息队列(MQ)异步处理数据写入操作。(通过订阅MQ来写如ES,可以优化同步写入性能问题)
优点:
1.性能提升:通过异步处理,减少了对MySQL写入性能的影响;
2.容错性:利用消息队列的持久化和重试机制,提高了数据同步的可靠性(即使MQ挂了,重启MQ以后,还是可以继续消费消息进行同步)。
缺点:
1.数据延迟:由于是异步处理,存在数据同步的延迟问题;
2.系统复杂度:需要引入消息队列和额外的消费者逻辑,增加了系统的复杂性(因为在MQ的下游还需要编写一个消费者来同步更新ES)。
实现步骤:
1.消息队列集成:选择并集成一个消息队列系统,如Kafka或RabbitMQ;
2.业务逻辑修改:将数据写入MySQL后,将变更信息发送到消息队列;
3.消费者开发:开发消费者服务,从消息队列中读取消息并异步写入ES;
4.异常处理:为消息队列的消费者实现异常处理和重试逻辑。
四.定时任务同步方案
通过定时任务,根据数据库中的时间戳字段变化来抽取并同步到ES。(这个方式还需要在表中增加以一个时间戳的字段来进行记录,才能方便同步的应用抽取数据)
优点:
1.无侵入性:不需要修改现有业务逻辑,对原系统无感知;
2.简单实现:通过定时任务实现,逻辑简单,易于理解和维护。
缺点:
1.时效性差:数据同步存在延迟,无法满足实时性要求(因为定时任务的脚本并不是实时的,所以会导致ES中的数据要比Mysql中的数据慢很多);
2.性能压力:定时任务可能会对数据库产生额外的查询压力(原本Mysql只需要支持系统应用的运行,现在还需要支持定时任务的查询,就可能导致额外的查询压力)。
实现步骤:
1.时间截字段添加:在MySQL的数据表中添加时间戳字段,用于记录数据变更时间;
2.定时任务配置:设置定时任务,按照固定频率查询MySQL中自上次同步以来发生变化的数据;
3.数据抽取:定时任务将查询结果抽取出来,准备同步到ES;
4.数据同步:将抽取的数据写入ES,完成同步过程。
五.监听Binlog异步同步方案
利用Mysql的Binlog日志,通过消息队列或者直接消费Binlog变化来同步数据至ES。(相比于用Binlog的组件替代了定时任务,Binlog组件伪装成一个从节点,当主节点发送了数据变更后,它就回把数据发送到子子节点,也就是Binlog组件中,然后组件收到数据后就同步到ES)
优点:
1.无侵入性:不需要修改现有的亚务代码,对现有系统无感知;
2.数据一致性:可以利用Binlog精确捕捉到数据库的所有变更,确保数据同步的完整;
3.高性能:Binog可以高效地处理数据变更,对原数据库性能影响较小(因为只是伪装了一个从节点,也就是相当于多一个节点需要同步数据);
4.容错性:通常配合消息队列使用,即使在网络波动或服务故障的情况下,也能保证数据最终一致性。
缺点:
1.系统复杂性:需要搭建和维护Binlog监听和消息队列系统,增加了系统架构的复杂度;
2.延时问题:虽然是基于实时同步,但在极端情况下,如消息队列积压,仍然可能遇到数据同步延迟。
实现步骤:
1.Binlog启用:确保MySQL实例开启了Binog功能,并且Binlog格式(row或mixed)能够支持所需的数据同步需求;
2.Binlog监听器配置:部署并配置Binlog监听器(如Debezium),监听指定的MySQL实例和数据库。
消息队列集成:将Binlog监听器与消息队列(如Kafka)集成,确保Binlog变更能够被转换成消息并发送到队列中;
3.消息消费者开发:开发消息消费者服务,该服务从消息队列中读取Binog变更消息并将其转换为Elasticsearch能够理解的格式;
4.数据同步:消息消费者服务将转换后的数据写入Elasticsearch,完成数据同步异常处理:实现异常处理机制,确保在数据同步失败时能够进行重试或记录日志以便后续处理。
推荐使用数据同步工具:Canal。
PS:
如果还需要了解更多的ElasticSerache的使用方法,可以查看《ElasticSearch7.6.x 快速入门到实战案例》文章。