MySQL与ES数据同步方案

1,693 阅读4分钟

背景

随着系统业务的不断发展,部分核心业务的数据规模愈发庞大,查询统计等场景愈发复杂,mysql的性能逐渐无法满足日常的使用需求,特别是各种维度的搜索场景。

这种情况下,一般都会选择将搜索的数据源从Mysql转移到ElasticSearch,但同时也需要面对两个数据源的数据如何同步问题。

方案

总的来说,数据同步方案基本分为“同步写”和“异步写”两个大方向,并在这两个大方向上进行具体实现,同时都伴随着各自的优缺点。

同步双写

同步双写,顾名思义,就是数据写入MySQL同时,需要调用ES进行数据写入,如下图:

优点:

  • 实现简单;
  • 相较于其他方案,数据实时性较高。

缺点:

  • 代码耦合性强。
  • 同步双写事务问题,性能较低。
  • 系统可用性同时受多个数据源可用性影响,系统可用性降低;

为何强调该方案数据实时性高是相较于其他方案呢?

在默认情况下,ElasticSearch并非实时写入的,而是近实时,即对文档的修改,默认最多等待1s,就可以查询到。由于其他方案大多不是同步写,所以相对来说,本方案实时性较高。

异步双写

由于同步双写会造成系统可用性降低,那很容易想到优化方案,就是同步改成异步,如下图

关于该方案中的异步,其实有不同的实现方式,比如异步线程、异步消息订阅等实现方式。在实际工作中,一般基于消息中间件的异步消息订阅的方式来实现。

优点:

  • 代码耦合性低,业务代码无需关注数据同步;
  • 性能高,避免了双写的事务问题,系统可用性较高;
  • 拓展性强,基于消息中间件的消息订阅,非常容易进行多数据源和异构数据的拓展。

缺点:

  • 数据实时性相对同步写稍低。
  • 引入其他中间件,增加系统复杂度。

定时同步

基于消息中间件的异步双写是个不错的方案,但是需要同时引入消息中间件,对于部分“小步快跑”的项目来说,增加了时间和金钱的成本,那么此时继续定时任务的数据同步,是个不错的临时选择。

定时任务同步的实现方式,是基于对MySQL表进行定时扫描读取数据后,写入到ElasticSearch中,如下图

优点:

  • 实现简单,对原有代码无侵入性;

缺点:

  • 实时性取决与定时任务的周期,实时性难以保证;
  • 当对实时性有较高要求时,对MySQL会造成较大的压力,可能导致系统整体可用性下降(可将轮询方到MySQL从库在一定程度避免)。

binlog订阅同步

众所周知,binlog是MySQL的逻辑日志,可以用来进行数据的同步和复制,MySQL主从同步就是基于binlog日志实现的。那么,MySQL与ElasticSearch间的数据同步,是否也可以基于binlog日志呢,答案是可以的。

一般来说,该方案需要引入一个中间件工具,作用是伪装成MySQL从库,接收主库binlog,然后同步到的其他数据源,如MySQL、ElasticSearch、HBase等等。市面上常见中间件工具如Flink-CDC、Canal、Otter、DataX等等,其基本原理如下图。

如图所示,实际上,我们往往会将binlog中间件接收到的binlog数据,转换成异步消息后推向消息中间件,方便其他服务订阅消费。其实binlog订阅同步的方案,可以说是前面“异步双写”方案的升级版,其进一步将“数据同步”功能下沉,与业务代码进一步解耦,这也符合软件开发中的“单一职责”原则。

优点:

  • 对业务代码的入侵极少,开发过程中无感知;
  • 数据实时性较高;

缺点:

  • 需要引入中间件,架构上增加了复杂度,且同时增加了维护成本;

总结

本文只对MySQL与ES数据同步实现方案的基本思路进行简单介绍,并未涉及具体业务场景的实践。在实际中,需要对业务场景进行分析,权衡利弊,选择适合自己的方案,并在具体的实现细节上进行调整。