• 希望一个数据同步,包治百病


     

     

    写在前面

    数据同步 是一个脏活,而且是个高风险的活

    大多数情况下,应用架构设计不好,引入什么新存储,引入什么DDD,治标不治本,都是扯淡。

    但万一灵验呢?这就是数据同步的需求基础。且看下面需求场景。

    应用场景

    • 业务数据发展到一定水平,需要将大部分冷热数据从熟悉的DB迁移到其他存储进行复杂查询和分析

    • 分库分表后,某些报表类查询无法工作,需要汇总到单库表进行操作

    • 分库分表有多个维度,需要拷贝多份数据达成冗余

    • 通过伪数据共享(没办法引入MQ、无法共享库表)进行业务改造

    • 慢存储→Cache之间的同步

    • 不停服数据迁移/scheme变更

    • 导数据导数据

    • 归档

    很多时候,DataBus提供的仅仅是一个工具集。要完成最终的功能,大多数需要引入其他组件,如MQ、JOB等进行配合。同时,大部分数据同步工具需要有规范的数据库支持。所以,在忙着进行数据同步之前,需要对遗留数据进行一次集中数据治理。

    一般数据同步,可以 应用驱动 双写:应用层同时向数据库或者多个存储写数据。因为代码在自己手中,这种方式在直觉上是简单可控的。但它引入的一致性问题将会是非常大的减分,因为没有复杂的协调协议(比如两阶段提交协议或者paxos算法),当出现问题时,很难保证多个存储处于相同的锁定状态。两个系统需要精确完成同样的写操作,并以同样的顺序完成序列化。如果写操作是有条件的或是有部分更新的语义,那么事情就会变得更麻烦。

    基于 数据库日志 :将数据库作为唯一真实数据来源,并将变更从事务或提交日志中提取出来。这可以解决一致性问题,但是很难实现,MySQL这样的数据库有私有的交易日志格式和复制冗余解决方案,难以保证版本升级之后的可用性。由于要解决的是处理应用代码发起的数据变更,然后写入到另一个数据库中,冗余系统就得是用户层面的,而且要与来源无关。对于快速变化的技术公司,这种与数据来源的独立性非常重要,可以避免应用栈的技术锁定,或是绑死在二进制格式上。

    数据同步方式

    目前的数据同步解决方案,大体有以下三种:

    • 针对特定AB方数据同步进行的私有定制,如trigger

    • binlog、wal日志级别的精确数据同步

    • 基于lastUpdateTime的查询结果集数据同步

    针对于数据同步方式,有增量和全量同步两种:

    • 全量 一次性导出倒入完毕

    • 增量 数据随到随倒,小溪汇大海~

    数据同步考虑的因素

    基本特性

    • 同机房同步实时性(RTT)

    • 增量同步/全量同步策略

    • 事务支持粒度

    • 峰值应对策略 (消峰降级、延迟写入、扩容策略)

    多机房(X一般公司不到这水平)

    • 数据库异地灾备

    • 多机房同步延迟

    • 机房切换(单元化切流/全站切流)

    • 数据对其方案

    • 双活

    AB端数量和质量

    • 支持常见的SQL,如MySQL、Postgres

    • 其他AB端支持,如:Redis、Mongo、ES

    • 数据同步的

    • 扩展方式和社区活跃度

    高吞吐、低延迟

    • 并行化(并行读、并行写)

    • 顺序场景串行化

    高可用

    • 监控、故障恢复

    • A(源端)端故障感知

    • B (目的端)端故障感知

    • 主从切换(或为对等节点)

    • 支持服务演练

    • 动态配置、故障重启

    数据完整性

    • 较高的SLA高可用服务水准

    • 故障数据有回放机制和降级策略

    • A/B端数据自动校验功能(一致性验证)

    其他

    • 数据过滤机制

    • 学习、部署成本

    • 硬件成本

    实现

    我们从几个典型实现、来看一下数据同步的复杂性。阿里在数据同步上可谓吓足了功夫,如: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

    最新的Canal已经支持MQ

    在这里插入图片描述

    如上图,除了需要搭建canal服务,将其伪装成一个slave,然后通过zookeeper做HA。我们还需要编码一个Canal Client服务,用来读取和解析数据。更多的情况,可能要引进一个MQ组件,用来缓解Canal的压力并承担一些扩展性功能。

    一些限制

    • Canal源端只支持MySQL,并且只支持基于ROW模式的同步复制

    • 同步的表必须要有主键,无主键表update会是一个全表扫描 ,如果出现重复记录的话,同步会导致数据错乱

    • 支持部分ddl同步,ddl语句不支持幂等性操作,所以出现重复同步时,会导致同步挂起,可通过配置高级参数:跳过ddl异常,来解决这个问题(支持create table / drop table / alter table / truncate table / rename table / create index / drop index,其他类型的暂不支持,比如grant,create user,trigger等等)

    • 不支持带外键的记录同步

    • 数据库慎用或者禁用trigger

    • Canal是吃内存的,注意内存相关的调优

    • 堆积能力有限,这也是外部MQ的优势

    maxwell

    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

    我觉得有必要提一下debezium。随着postgres的性能和特性越来越强,国内采用PG的公司逐渐增多。像这种场景,canal就无能为力了,debezium同时支持源端MySQL和Postgres、MongoDB,值得一试。同maxwell类似,同样需要kafka的支持。
    缺点也是显而易见的,文档的质量不高,实践资料太少。

    DataBus

    Linkedin开源作品。Databus支持多种数据来源的变更抓取,包括Oracle和MySQL。是一个低延迟、可靠的、支持事务的、保持一致性的数据变更抓取系统。
    大同小异,databus在MySQL的处理方式上,也是通过解析binlog的方式进行数据抓取。使用MySQL Binlog解析库,我们也可以构造一个自己的数据同步中间件。DataBus做了更多的缓冲区relay、事件优化和回溯处理。在整个技术架构中,可以充当数据总线的作用。

    DataX

    与Databus类似,DataX是一个在异构的数据库/文件系统之间高速交换数据的工具,实现了在任意的数据处理系统之间的数据交换,更像是一个ETL工具。
    DataX支持的AB端数据源非常丰富,但因为它使用的定时抓取的方式,其延迟相比较Canal等基于日志的方式,是比较大的。同时,DataX对数据的要求较高,比如你的数据库如果没有最后更新时间之类的字段,从源端读取变更数据将有一定的困难。

    总结

    整体而言,Canal、DataX、DataBus的使用人数多,社区活跃,框架也比较成熟。在满足应用场景的前提下,优先选择,它们都有自己的HA方案,代价适中。

    Canal、DataBus源端支持类型有限,但延迟低,需要手写Client来处理数据。大多数情况下需要加入MQ进行配合。

    DataX支持丰富,使用简单,但延迟较大(依赖获取频率),只需要手写规则文件,对复杂同步自定义性不强。

    文章地址:https://www.imooc.com/article/295278

  • 相关阅读:
    查看数据库表中的数据
    exec和execsql
    CPI
    百度硬盘可以检索的字节测试
    HDU2095
    Vigenere密码
    斌神无所不能
    HDU p1017
    POJ1316
    head区的代码详解
  • 原文地址:https://www.cnblogs.com/shoshana-kong/p/14767908.html
Copyright © 2020-2023  润新知