MySQL同步到ES

当业务场景中涉及MySQL同步到ES时,可以考虑以下几种方式:

#同步双写

优点:业务逻辑简单。

缺点:

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

双写失败风险,包括以下几种:

  • ES系统不可用;
  • 程序和ES之间的网络故障;
  • 程序重启,导致系统来不及写入ES等。

针对这种情况,有数据强一致性要求的,就必须双写放到事物中来处理,而一旦用上事物,则性能下降更加明显。

#异步双写(MQ方式)

优点:

  • 性能高;
  • 不存在丢数据问题。

缺点:

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

#异步双写(Worker方式)

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

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

优点:

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

缺点:

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

#Binlog同步方式

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

具体步骤如下:

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

优点:

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

缺点:

  • 构建Binlog系统复杂;
  • 存在MQ延时的风险。