数据源监听

数据源监听

源数据变化捕获是数据集成的起点,获取数据源变化主要有三种方式:

  • 基于日志的解析模式;
  • 基于增量条件查询模式;
  • 数据源主动推送模式。

基于日志的解析模式常用于各种类型的数据库,例如MySQLBinlogOracleRedo&Achieve LogSQL Server Change Tracking & CDC等。

不同数据库日志解析的原理差别很大,以MySQL Binlog模式为例,解析程序本身是一个Slave,能够实时收到MySQL Master的数据流推送,并解析还原成DDLDML操作。而SQL ServerCT模式下,增量是通过定期查询Change Tracking表实现的。

基于增量条件的查询模式不依赖于源端开启日志记录,但对于数据源通常有额外的格式要求。例如,数据库表或文档对象需要有标志更新时间的字段,这在一些业务系统中是无法满足的。

数据源主动推送模式的常见形式为业务插码,即应用系统通过打点或者配置切面的方式,将数据变化封装为事件,额外发送一份给数据集成平台。这种方式一般需要对源端系统代码进行一定程度的修改。

数据库日志增量捕获

通常而言,基于数据库的日志进行增量捕获应当被优先考虑。其具备以下几个显著优点:

  • 能够完整获取数据变化的操作类型,尤其是Delete操作,这是增量条件查询模式很难做到的;
  • 不依赖特别的数据字段语义,例如更新时间;
  • 多数情况下具备较强的实时性。

当然,事物都具有两面性。开启数据库日志通常会对源库性能产生一定的影响,需要额外的存储空间,甚至一些解析方法也会对源库资源造成额外消耗。因此,实施过程中需要在DBA的配合下,根据数据库特点和解析原理进行DB部署规划。

推荐使用数据库的复制和灾备能力,在独立服务器对从库进行日志解析。此外,当数据库产生批量更新时,会在短时间内产生大量日志堆积,如果日志留存策略设置不当,容易出现数据丢失。这些都需要根据具体的业务数据增长特点,在前期做好规划,并在上线后根据业务变化定期进行评估和调整。

数据源推送

数据源主动push模式下,由于事件发送和业务处理很难做到事务一致性,所以当出现异常时,数据一致性就无从保证,比较适合对于数据一致性要求不高的场景,例如用户行为分析。

CDC模块

变更数据抓取通常需要针对不同数据源订制实现,而针对特定数据源,实现方式一般有两种:

  • 基于自增列或上次修改时间做增量查询;
  • 利用数据源本身的事务日志或Slave同步等机制实时订阅变更;

第一种方式实现简单,以SQL为例:相信大家都写过类似的SQL,每次查询时,查询[last_query_time, now)区间内的增量数据,lastmodified列也可以用自增主键来替代。这种方式的缺点是实时性差,对数据库带来了额外压力,并且侵入了表设计:所有要实现变更抓取的表都必须有用于增量查询的列并且在该列上构建索引。另外,这种方式无法感知物理删除(Delete),删除逻辑只能用一个delete列作为flag来实现。第二种方式实现起来相对困难,但它很好地解决了第一种方式的问题,因此前文提到的开源方案也都采用了这种方式。下面我们着重分析在MySQL中如何实现基于事务日志的实时变更抓取。

MySQL的事务日志称为Binlog,常见的MySQL主从同步就是使用Binlog实现的:

MySQL Database Replication Internals

我们把Slave替换成CDC模块,CDC模块模拟MySQL Slave的交互协议,便能收到MasterBinlog推送:

CDC 模块架构

CDC模块解析Binlog,产生特定格式的变更消息,也就完成了一次变更抓取。但这还不够,CDC模块本身也可能挂掉,那么恢复之后如何保证不丢数据又是一个问题。这个问题的解决方案也是要针对不同数据源进行设计的,就MySQL而言,通常会持久化已经消费的Binlog位点或Gtid(MySQL 5.6之后引入)来标记上次消费位置。其中更好的选择是Gtid,因为该位点对于一套MySQL体系(主从或多主)是全局的,而Binlog位点是单机的,无法支持主备或多主架构。

MySQL CDC模块的一个挑战是如何在Binlog变更事件中加入表的Schema信息(如标记哪些字段为主键,哪些字段可为null)Debezium在这点上处理得很漂亮,它在内存中维护了数据库每张表的Schema,并且全部写入一个backupKafka Topic中,每当Binlog中出现DDL语句,便应用这条DDL来更新Schema。而在节点宕机,Debezium实例被调度到另一个节点上后,又会通过backup topic恢复Schema信息,并从上次消费位点继续解析Binlog

另一个挑战是,我们数据库已经有大量的现存数据,数据迁移时的现存数据要如何处理。这时,Debezium独特的Snapshot功能就能帮上忙,它可以实现将现有数据作为一次”插入变更”捕捉到Kafka中,因此只要编写一次客户端就能一并处理全量数据与后续的增量数据。

开源方案对比

  • databus: Linkedin的分布式数据变更抓取系统;
  • Yelp’s data pipeline: Yelp的数据管道;
  • Otter & Canal:阿里开源的分布式数据库同步系统;
  • Debezium: Redhat开源的数据变更抓取组件;

这些解决方案关注的重点各有不同,但基本思想是一致的:使用变更抓取模块实时订阅数据库变更,并分发到一个中间存储供下游应用消费。下面是四个解决方案的对比矩阵:

方案 变更抓取 分发平台 消息格式 额外特性
databus DatabusEventProducer,支持OracleMySQL的变更抓取 DatabusRelay,基于Netty的中间件,内部是一个RingBuffer存储变更消息 Apache Avro BootstrapService组件存储历史变更用以支持全量
Yelp’s data pipeline MySQL Streamer,基于Binlog抓取变更 Apache Kafka Apache Avro Schematizer,作为消息的Avro Schema注册中心的同时提供了Schema文档
Otter Canal,阿里的另一个开源项目,基于Binlog work node内存中的ring buffer protobuf 提供了一个完善的admin ui
Debezium 提供MySQL, MongoDB, PostgreSQL三种Connector Apache Kafka Apache Avro / json Snapshot mode支持全量导入数据表

databus

Linkedin databus的论文有很强的指导性,但它的MySQL变更抓取模块很不成熟,官方支持的是OracleMySQL只是使用另一个开源组件OpenReplicator做了一个demo。另一个不利因素databus使用了自己实现的一个Relay作为变更分发平台,相比于使用开源消息队列的方案,这对维护和外部集成都不友好。

databus 架构图

Otter & Canal

OtterCanal在国内相当知名,Canal还支持了阿里云DRDS的二级索引构建和小表同步,工程稳定性上有保障。但Otter本身无法很好地支持多表聚合到新表,开源版本也不支持同步到分片表当中,能够采取的一个折衷方案是直接将Canal订阅的变更写入消息队列,自己写下游程序实现聚合同步等逻辑。该方案也是我们的候选方案。

Otter 架构图

data pipeline

Yelp’s data pipeline是一个大而全的解决方案。它使用Mysql-Streamer(一个通过Binlog实现的MySQL CDC模块)将所有的数据库变更写入Kafka,并提供了Schematizer这样的Schema注册中心和定制化的Python客户端库解决通信问题。遗憾的是该方案是Python构建的,与我们的Java技术栈相性不佳。

Debezium

Debezium不同于上面的解决方案,它只专注于CDC,它的亮点有:

  • 支持MySQL、MongoDB、PostgreSQL三种数据源的变更抓取,并且社区正在开发OracleCassandra支持;

  • Snapshot Mode可以将表中的现有数据全部导入Kafka,并且全量数据与增量数据形式一致,可以统一处理;

  • 利用了KafkaLog Compaction特性,变更数据可以实现”不过期”永久保存;

  • 利用了Kafka Connect,自动拥有高可用与开箱即用的调度接口;

  • 社区活跃:Debezium很年轻,面世不到1年,但它的Gitter上每天都有百余条技术讨论,并且有两位Redhat全职工程师进行维护;

上一页
下一页