IE盒子

搜索
查看: 96|回复: 1

MySQL同步到ES的实践方案

[复制链接]

3

主题

13

帖子

19

积分

新手上路

Rank: 1

积分
19
发表于 2022-12-21 19:12:49 | 显示全部楼层 |阅读模式
由于MySQL对全文检索或模糊查询支持的能力不强,需要将数据发送到搜索引擎ES上,那么怎么将MySQL的数据同步到ES上嘞?下面我将给出四个方案:
1. 同步双写

这是一种最为简单的方式,在将数据写到mysql时,同时将数据写到ES。
优点:

  • 业务逻辑很简单
缺点:

  • 硬编码,有需要写入mysql的地方都需要添加写入ES的代码;
  • 业务强耦合
  • 存在双写失败丢数据风险;
  • 性能较差:本来mysql的性能不是很高,再加一个ES,系统的性能必然会下降。
上面说的双写失败风险,包括以下几种:

  • ES系统不可用;
  • 程序和ES之间的网络故障;
  • 程序重启,导致系统来不及写入ES等。
针对这种情况,有数据强一致性要求的,就必须双写放到事务中来处理,而一旦用上事务,则性能下降更加明显。
2. 异步双写(MQ方式)

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

  • 性能高
  • 不存在丢失数据的问题
缺点:

  • 还存在硬编码、业务强耦合等问题;
  • 系统中增加了mq的代码,复杂度增加;
  • 可能存在时延问题,程序的写入性能提高了,但是由于MQ的消费可能由于网络或其它原因导致用户写入的数据不一定可以马上看到。
3. 异步双写(worker方式)

上面两种方案中都存在硬编码问题,也就是有任何对mysq进行增删改查的地方要么植入ES代码,要么替换为MQ代码,代码的侵入性太强,若是实时要求不高的情况下,可以考虑用定时器来处理,具体步骤如下:

  • 数据库的相关表中增加一个字段为timestamp的字段,任何crud操作都会导致该字段的时间发生变化;
  • 原来程序中的crud操作不做任何变化;
  • 增加一个定时器程序,让该程序按一定的时间周期扫描指定的表,把该时间段内发生变化的数据提取出来;
  • 逐条写入到ES中。
优点:

  • 不改变原来代码,没有侵入性、没有硬编码;
  • 没有业务强耦合;
  • 不改变原来程序的性能;
  • Worker代码编写简单不需要考虑增删改查。
缺点:

  • 时效性较差,由于定时器工作周期不可能设在秒级,所以实时性没有上面2中好;
  • 对数据库有一定的轮询压力,一种改进方法是将轮询放到压力不大的从库上。
4. Binlog同步方式

上面三种方案要不有代码侵入、要不有硬编码、要不有时延,那么有没有一种更好的方法嘞?答案就是利用mysql的binlog!
具体步骤如下:

  • 读取mysql的binlog日志,获取指定表的日志信息;
  • 将读取的信息转为MQ;
  • 编写一个MQ消费程序;
  • 不断消费MQ,每消费完一条消息,将消息写入到ES中。
优点:

  • 没有代码侵入、没有硬编码;
  • 原有系统不需要任何变化,没有感知;
  • 性能高
  • 业务解耦,不需要关注原来系统的业务逻辑
缺点:

  • 构建Binlog系统复杂
  • 存在MQ延时的风险
当然目前市场上基于Binlog同步的工具有很多,比如Canal、阿里云的DTS(毫秒级延迟)!!!

摘自公众号:Java之禅
回复

使用道具 举报

2

主题

11

帖子

18

积分

新手上路

Rank: 1

积分
18
发表于 2025-4-4 09:22:33 | 显示全部楼层
啊啊啊啊啊啊啊啊啊啊啊
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表