哎!这是一个脏活,而且是个高风险的活。
大多数情况下,应用架构设计不好,引入什么新存储,引入什么DDD,治标不治本,都是扯淡。
但万一灵验呢?这就是数据同步的需求基础。且看下面需求场景。
MQ
、无法共享库表)进行业务改造很多时候,DataBus提供的仅仅是一个工具集。要完成最终的功能,大多数需要引入其他组件,如MQ、JOB等进行配合。同时,大部分数据同步工具需要有规范的数据库支持。所以,在忙着进行数据同步之前,需要对遗留数据进行一次集中数据治理。
一般数据同步,可以应用驱动
双写:应用层同时向数据库或者多个存储写数据。因为代码在自己手中,这种方式在直觉上是简单可控的。但它引入的一致性问题将会是非常大的减分,因为没有复杂的协调协议(比如两阶段提交协议或者paxos算法),当出现问题时,很难保证多个存储处于相同的锁定状态。两个系统需要精确完成同样的写操作,并以同样的顺序完成序列化。如果写操作是有条件的或是有部分更新的语义,那么事情就会变得更麻烦。
基于数据库日志
:将数据库作为唯一真实数据来源,并将变更从事务或提交日志中提取出来。这可以解决一致性问题,但是很难实现,MySQL这样的数据库有私有的交易日志格式和复制冗余解决方案,难以保证版本升级之后的可用性。由于要解决的是处理应用代码发起的数据变更,然后写入到另一个数据库中,冗余系统就得是用户层面的,而且要与来源无关。对于快速变化的技术公司,这种与数据来源的独立性非常重要,可以避免应用栈的技术锁定,或是绑死在二进制格式上。
目前的数据同步解决方案,大体有以下三种:
trigger
binlog
、wal
日志级别的精确数据同步lastUpdateTime
的查询结果集数据同步针对于数据同步方式,有增量和全量同步两种:
全量
一次性导出倒入完毕增量
数据随到随倒,小溪汇大海~X一般公司不到这水平
)MySQL
、Postgres
Redis
、Mongo
、ES
我们从几个典型实现、来看一下数据同步的复杂性。阿里在数据同步上可谓吓足了功夫,如:datax(ETL工具)、canal、otter、drc、dts、drds愚公精卫等。其中,使用最广泛的就是canal和datax。 另外,还有一些其他较活跃的工具,如sqoop、Maxwell 、debezium等
基于数据库的组件,一般都是伪装成一个DB的从库接收一份数据,剩下的都是框架内玩的事情了。如
MySQL
一般使用基于row的binlog
、postgres
基于wal日志
进行复制。以MySQL
为例、如果通过Binlog
方式,将数据同步到ES
、Hbase
等其他盲区,就需要手写大量代码,包括组装数据、批量、顺序、HA等等很多场景都需要考虑。
我们限定一下一个最简单的使用场景,然后追踪在其上需要哪些工作量,又有哪些优缺点。场景如下: 将MySQL数据库的数据,同步一份数据到Postgres
最新的Canal已经支持MQ
如上图,除了需要搭建canal服务,将其伪装成一个slave,然后通过zookeeper做HA
。我们还需要编码一个Canal Client
服务,用来读取和解析数据。更多的情况,可能要引进一个MQ
组件,用来缓解Canal的压力并承担一些扩展性功能。
一些限制
ROW
模式的同步复制同步挂起
,可通过配置高级参数:跳过ddl异常,来解决这个问题(支持create table / drop table / alter table / truncate table / rename table / create index / drop index,其他类型的暂不支持,比如grant,create user,trigger等等)trigger
maxwell干脆就将这个过程更近了一步:直接将binlog
解析成json
存储在kafka
中。用户使用的时候,直接订阅kafka
的topic
即可。
数据可能长这样:
mysql> update test.maxwell set daemon = 'firebus! firebus!' where id = 1;
maxwell: {
"database": "test",
"table": "maxwell",
"type": "update",
"ts": 1449786341,
"xid": 940786,
"commit": true,
"data": {"id":1, "daemon": "Firebus! Firebus!"},
"old": {"daemon": "Stanislaw Lem"}
}
maxwell
为用户提供了默认的解决方式,需要额外引入kafka
组件,这也是大部分数据分发共享的思路。由其github star数看来,要小canal一个数量级。在此基础上,有类似bireme更专某个场景的产品,不过都偏小众。
我觉得有必要提一下debezium
。随着postgres
的性能和特性越来越强,国内采用PG的公司逐渐增多。像这种场景,canal就无能为力了,debezium同时支持源端MySQL
和Postgres
、MongoDB
,值得一试。同maxwell
类似,同样需要kafka
的支持。
缺点也是显而易见的,文档的质量不高,实践资料太少。
DataBus
Linkedin开源作品。Databus支持多种数据来源的变更抓取,包括Oracle
和MySQL
。是一个低延迟、可靠的、支持事务的、保持一致性的数据变更抓取系统
。
大同小异,databus在MySQL的处理方式上,也是通过解析binlog的方式进行数据抓取。使用MySQL Binlog解析库,我们也可以构造一个自己的数据同步中间件。DataBus
做了更多的缓冲区relay
、事件优化和回溯处理。在整个技术架构中,可以充当数据总线的作用。
与Databus
类似,DataX
是一个在异构的数据库/文件系统之间高速交换数据的工具,实现了在任意的数据处理系统之间的数据交换,更像是一个ETL
工具。
DataX
支持的AB端数据源非常丰富,但因为它使用的定时抓取的方式,其延迟相比较Canal
等基于日志的方式,是比较大的。同时,DataX
对数据的要求较高,比如你的数据库如果没有最后更新时间
之类的字段,从源端读取变更数据将有一定的困难。
整体而言,Canal
、DataX
、DataBus
的使用人数多,社区活跃,框架也比较成熟。在满足应用场景的前提下,优先选择,它们都有自己的HA
方案,代价适中。
Canal
、DataBus
源端支持类型有限,但延迟低,需要手写Client来处理数据。大多数情况下需要加入MQ
进行配合。
DataX
支持丰富,使用简单,但延迟较大(依赖获取频率),只需要手写规则文件,对复杂同步自定义性不强。