DB与ES组合应用内的数据实时同步

 问题 

1. 同步实时性:数据在DB更新后需多久才更新到Elasticsearch,多久的时间是应用系统可以接受范围,一般需要控制在1s以内,如果是分钟以上,属于离线同步。

2.数据一致性,数据频繁在DB变更修改,更新到ES后如何保证数据与DB一致,在容许的时间范围内应用系统查询的数据有效可接受的,如果变更出现覆盖等,那数据是无效的,应用系统是不可接受的,如何修复。

 同步模式

1.推送Push模式,数据源主动将变更数据推送到目标源,如RabbitMQ,服务端会主动MQ发送到客户端。

2. 拉取Pull模式,目标源定时去数据源拉取变更数据,如Mysql数据库的数据主从同步,Slave会去Master拉取变更数据。

3. 推拉结合,数据源与目标源之间,既有推送方式也有拉取方式,此种模式一般会借助于中间媒介实现,如基于Kafka的游戏日志应用,数据源(采集端)会将日志数据发送到Kafka集群,目标源会定期的从Kafka拉取数据更新。

技术方案

1. 同步双写,更新DB时同步更新ES。此技术方案最简单,附带问题最多,数据冲突,数据覆盖,数据丢失,处处是坑,谨慎选择。

2. 异步双写,更新DB之后,记录一条MQ,MQ通知消费端,消费端反向查询DB数据,最后更新到ES。此技术方案与业务系统耦合严重,需要每个业务专门编写相关程序,不利于快速响应需求。

3. CDC,全称Change Data Capture,变更数据捕捉,从数据库内部捕捉变更数据,将变更数据推送到中间程序中,中间程序逻辑实现同步推送到ES。CDC机制速度极快,数据精准,与应用程序耦合少,可抽象脱离业务系统,适合大规模使用。 

CDC机制原有设计是为了同类型数据库之间数据同步,应用在主从同步高可用方面,所以同类型数据库之间数据同步非常容易实现,数据库厂商本身天然支持,经过多年实战验证高效可靠。几乎所有数据库产品都支持:Postgresql 有 Logical Decoding,Sqlserver 有 Change data capture 和 Change Tracking,Oralce 有 Redo log和 Oralce Golden Gate,Mongodb 有 Replicate sets,Elasticsearch 有 Translog。

相反,在异构数据库之间实现数据同步是比较复杂的,数据链路长,中间涉及到的技术点特别多,且每一步都非常关键。

Mysql同步到ES

数据从Mysql同步到ES主要涉及到几个技术关键点

1.Binlog机制

2.Canal中间件

3.Kakfa中间件

4.同步应用程序(业务型开发中间件)

Binlog机制

Binlog是Mysql自带功能机制,设计之初是为了数据库之间主从同步;

1.Master主库,启动Binlog机制,将变更数据写入Binlog文件

2.Slave从库,从Master主库拉取binlon数据,回放Binlog,更新从库数据启用Binlog注意:

     Master主库一般会有多台Slave订阅,且Master主库要支持业务系统实时变更操作,服务器资源会有瓶颈

      需要同步的数据表一定要有主键

Canal中间件

Canal是Mysql的中间件产品,专门应用在数据同步

1.伪装Slave从库,

2.订阅Mysql同步

3.拉取Binlog变更数据,

4.回放Binlog变更数据,

5.解析Binlog数据为Json,报文记录了新旧数据,数据库数据表,更新方式;

6.输出变更数据,并保证变更顺序,输出目的源支持很多,常规的一般输出到kafka

    配置cannal注意点

1.Canal基于Jvm运行,数据处理能力不如Mysql,Canal需要配置集群模式。一组Canal集群不能支持太多的数据库实例。

2.若是数据库做了水平的分库分表,原有Canal是不能识别为一类数据源,需要稍微修改部分代码

3.建议Canal订阅Slave从机,因为Master是业务主库,主库承担的业务系统职责太多

4. Binlog日志模式建议启动Gtid,Canal订阅的数据库如果出现故障,需要基于此切换到其他数据库。

5.数据输出到Kafka,若数据库是做了分库分表的,需要修改Canal部分代码。

6.设置Kafka分区键相同,保障相同数据变更顺序。

Kafka中间件

使用Kafka作为中间缓存,主要基于以下方面考虑

1.分区特性,Kafka支持分区,并发性能好,数据吞吐能力超过mysql,性能不会成为瓶颈

2.分区顺序存储,Kafka数据存储是有顺序的,设置好主键,保障Binlog变更顺序

3.消费顺序,客户端消费Kafk数据,会基于Offset,按顺序消费,保障Binlog变更顺序

4.消费组:严格意义上讲,Kafka并非消息队列,应算消息流,一个数据表可能会映射到多个索引,这就需要设置不同的消费组,保障多个消费组之间不冲突覆盖,同样的变更数据有多次重复消费

同步程序

同步程序当前基于Java自主开发,当前的主流同步工具不能很好支持自定义需求,主要包括两大程序

1. 同步任务调度程序

同步调度配置,配置同步任务,配置同步映射关系,DB到ES的映射,Kafka到ES的映射

同步调度分配,同步任务操作,启动、停止、重新设置;同步任务分配,指定并行度等。

2.同步任务执行程序

执行任务,将数据从Kafka经过映射写入到ES中,主要由四大模块组成

(1)Kafka模块,拉取消费数据,记录消费位置

(2)Mapper模块,执行映射过程,数据表与索引映射,表字段与索引字段映射,生成指定的Json格式数据

(3)Elastic模块,将Mapper生成好的Json数据提交到ES中,Bulk局部更新,设置doc_as_upsert为true,成功则提交消费记录位置,失败则走异常逻辑

(4)Schedule模块,基于线程级别执行同步任务,支持同步任务启动暂停等状态操作,实时汇总同步任务的状态指标数据

数据同步全过程

1. 数据从DB更新到ES,中间经过多个环节,同步模式既有推送,也拉取,且多次结合完成。

2. Mysql写入到本地binlog,推送模式

3. Canal读取binlog写入Kafka,先是拉取模式,后是推送模式

4. Worker同步程序从Kafka读写数据,经过处理写入到ES,先是拉取模式,后是推送模式


注意事项

DB到ES实时同步整体项目链路很长,且涉及技术点较多,任意环节都会导致一些问题,特别注意:

1. DB刷数据问题,由于DB是批量更新,会出现部分性能瓶颈

2. DB多表关联深度问题,DB多表直接关联最好的关系是1对1,主要ES映射也可以基于主键关联更新,无需反向查询

3. ES高级类型限制问题,ES本身支持很多高级数据类型,但这些在同步程序中最好不要使用


有待探索问题

1.数据校验,DB数据虽然同步到ES中,但目前是没有有效的方法去校验正确性的,传统的方式校验方式是随机两边查询对比,非常的低效,需要探讨更好的数据比对方法;

2. 数据修复,当数据发现不正确时需要自动能够修复,但由于数据校验的低效,数据修复的准确性有待考量

3. 技术演进,数据同步程序基于Java开发,但做了很多非业务时间工作,程序大量的工作在调度,考虑引入Flink平台,由平台负责底层资源调度,上层只需配置同步映射。


   采取CDC这种方案也是基于马蜂窝已有的经验分享,设计思路一样,技术实现不一样。数据同步整体技术实现中间环节很多,任意技术点都需要了解透彻,否则会出现很多致命事故,需要多人团队协作完成。

你可能感兴趣的:(DB与ES组合应用内的数据实时同步)