背景
在实际项目开发中,我们经常将MySQL作为业务数据库,ES作为查询数据库,用来实现读写分离,缓解MySQL数据库的查询压力,应对海量数据的复杂查询,这其中有一个很重要的问题,就是如何实现MySQL数据库和ES的数据同步,今天和大家聊聊MySQL和ES数据同步的各种方案,我们先看看下面5种常用的数据同步。
在生产上,为了便于商品的聚合搜索,高速搜索,采用两大优化方案:
- 把商品数据冗余存储在Elasticsearch中,实现高速搜索
- 把商品数据冗余存储在redis 中,实现高速缓存
要保持分布式数据的一致性,这个问题其实是一样的,关于redis的一致性问题在 《聊聊数据库和缓存一致性的几种实现方式》 。
一、同步双写
这是一种最为简单的方式,在将数据写到MySQL时,同时将数据写到ES。

优点: 1、业务逻辑简单 2、实时性高
缺点
-
业务耦合,这种方式代码侵入性强,商品的管理中耦合大量数据同步代码,在每个写 mysql 的地方也都要加写 es 的代码。
-
高风险:存在双写失败丢数据风险
-
影响性能,写入两个存储,响应时间变长,本来 MySQL 的性能不是很高,再加一个 ES,系统的性能必然会下降。
二、异步双写
针对多数据源写入的场景,可以借助MQ实现异步的多源写入。

异步双写优点:
- 性能高;
- 不易出现数据丢失问题,主要基于 MQ 消息的消费保障机制,比如 ES 宕机或者写入失败,还能重新消费 MQ 消息;
- 多源写入之间相互隔离,便于扩展更多的数据源写入。
异步双写缺点
- 硬编码问题,接入新的数据源需要实现新的消费者代码;
- 系统复杂度增加,引入了消息中间件;
- MQ是异步消费模型,用户写入的数据不一定可以马上看到,造成延时。
三、定时同步
上面两种方案中都存在硬编码问题,代码的侵入性太强,如果对实时性要求不高的情况下,可以考虑用定时器来处理。

1、数据库的相关表中增加一个字段为 timestamp 的字段,任何 CURD 操作都会导致该字段的时间发生变化;
2、原来程序中的 CURD 操作不做任何变化;
3、增加一个定时器程序,让该程序按一定的时间周期扫描指定的表,把该时间段内发生变化的数据提取出来;
4、逐条写入到 ES 中。
优点
- 不改变原来代码,没有侵入性,没有硬编码。
- 没有业务强偶合,不改变原来程序的性能。
- worker代码编写简单,不需要考虑增删改查。
缺点
- 时效性较差,由于是采用定时器,根据固定频率查询表来同步数据,尽管将同步周期设置到秒级,也还是会存在一定时间的延迟。
- 对数据库有一定的轮询压力,改进方法是将轮询放到压力不大的从库 上,经典方案借助logstash 实现数据同步,其底层实现原理就是,根据配置定期使用SQL查询新增的数据写入ES中,实现数据的增量同步。
四、Binlog实时同步
上面三种方案要么有代码侵入,要么有硬编码,要么有延迟,那么有没有一种方案既能保证数据同步的实时性又没有代码侵入呢?
当然有,可以利用MySQL的Binlog来进行同步。

具体步骤如下:
1、读取MySQL的binlog日志,获取指定表的日志信息;
2、将读取的信息转为MQ;
3、编写一个MQ消费程序;
4、不断消费MQ,每消费完一条消息将消息写入到ES中;
优点:
- 没有代码侵入,没有硬编码
- 原有系统不需要任何变化,没有感知
- 性能高
- 业务解耦,不需要关注原来系统的业务逻辑
缺点
- 构建binlog系统复杂
- 如果采用MQ消费解析的binlog信息,也会像方案二一样存在MQ延时的风险
MySQL通过binlog订阅实现主从同步,Canal Server 就是一个伪装的slave节点,接收到binlog日志后,发送到MQ,从而实现CDC(Change Data Capture),将已提交的更改发送到下游,包括insert,delete,update。

主要流程为:
1、Canal服务端向MySQL的master节点传输dumb协议。
2、MySQL的master节点接收到dump请求后推送binlog日志给Canal服务端,解析binlog对象(原始为byte 流)转成Json格式。
3、Canal客户端通过TCP协议或MQ形式监听Canal服务端,同步数据到ES。

下面是canal执行的核心流程:

五、etl工具
MySQL同步到Redis、MySQL同步到hbase、MySQL同步到es、或机房同步、主从同步等,都可以考虑使用etl工具。
什么是etl工具呢?
ETL,是英文 Extract-Transform-Load 的缩写,用来描述将数据从来源端经过抽取(extract)、转换(transform)、加载(load)至目的端的过程。ETL一词较常用在数据仓库,但其对象并不限于数据仓库。
ETL是构建数据仓库的重要一环,用户从数据源抽取出所需的数据,经过数据清洗,最终按照预先定义好的数据仓库模型,将数据加载到数据仓库中去。
常用的etl工具有: databus、canal (方案四用了这个组件,有etl 的部分功能)、otter 、kettle等。
本文的一些专业名词是跟大数据有关的,所以放上一张大数据架构图,方便大家理解。

欢迎大家点赞、观看、收藏,一键三连~