mysql到kudu,canal读取mysql的binlog实时同步数据到kudu的数据异构方案

如今准备作mysql实时同步数据到kudu,为之后的实时即席查询分析作数据支撑,kudu+impala速度仍是挺快的。mysql

由于实时性要求比较高,并且须要同步的时候对mysql的压力不能太大,否则会影响业务系统的稳定性。web

介于上面的一些要求,咱们选择采用阿里的canal读取mysql的binlog,对binlog解析后对kudu进行操做。由于canal只是模拟mysql的slave,经过主从复制的协议从mysql节点上面拉取binlog信息而后解析转换(其中mysql的binlog模式应该设置为ROW,这种模式会记录操做的详细信息,好比操做类型是增长仍是删除,某个字段是否是主键,字段是否容许为空,更新的时候该列是否改变等等),这样不会印象到业务系统的运行。sql

而后下面分为两个块:数据库

1.对canal数据拉取并分类转换

以下图所示:json

f1583e3e17ef1e1375d419e2472cbe00.png

(1)咱们须要实现本身的一个读取canal的Reader,由于存在多个canal实例因此须要启动多个线程建立不一样canal实例的消费者。bash

(2)由于一个库的binlog只有一个,若是咱们操做了数据库:对A表更新了10条数据而后对B表删除了5条数据而后又对A表新增了6条数据,Reader的一次拉取数据可能会将上面的操做封装到一个message里面,而且解析都是有顺序性的,咱们能够将拉取到的数据进行分类,将对A表和B表的操做进行分类,一次Reader的拉取到时候发送到kafka的数据对一个表的操做就是一条信息(若是不分类的话,上面的操做就会产生3条kafka数据,而且对后面的kudu操做去重性能有影响),分类后对后面的入库kudu操做去重有好处。svg

例如: a表 添加10条数据,b表 修改5条数据,a表 删除6条数据oop

不合并会生成3条json:性能

json1:{a表添加10条数据}

json2:{b表修改5条数据}

json3:{a表删除6条数据}

合并只会生成2条json:spa

json1:{a表添加10条数据而且a表删除6条数据}

json2:{b表修改5条数据}

这样合并以后会减小后面的批量查询操做(操做去重),提升性能。

(3)对上面分类的信息进行转换,转换成固定的json格式。格式以下:(参考了宜信的dbus方案),其中payload里面是每条数据的具体信息,schema的fields是每一个字段的元信息,其中ums_id(该ID是为了防止重复操做,消费端可能重复消费一条数据屡次或者某些缘由可能会屡次操做,ums_id是对单个库的一个操做(增删改这些)来讲是惟一且不变的,到时候消费端消费数据后会先根据id查看库中是否有这个ID若是库中的ums_id小于当前这个ums_id则操做,相反就说明该操做已经执行过就丢弃,而且若是存在真实删除数据,kudu端口也只能作逻辑删除,由于若是kudu端删除了,那么之前的数据重复过来了发现没有该ID ,那消费端那边又会去执行一次)是binlog名字(好比:mysql-bin.000010)加上该条数据的偏移量(其中偏移量前面补0暂时定为偏移量长度为30,好比下面的00000000000000090222)做为单个数据库每一个操做的惟一标识,ums_ts就是这条语句执行的具体时间戳。上面这些信息均可以从canal消费的数据获取到

{

"payload": [

{

"tupe": [

"mysql-bin.00001000000000000000090222",1517194451453,"i","14","lijieinsert"],

"mysql-bin.00001000000000000000090345",1517194455643,"u","14","lijieupdate"],

"mysql-bin.00001000000000000000090465",1517194459643,"d","14","lijiedelete"]

}

],

"schema": {

"fields": [

{

"is_pk": false,

"name": "__ums__id__",

"nullable": false,

"type": "long"

},

{

"is_pk": false,

"name": "__ums__ts__",

"nullable": false,

"type": "long"

},

{

"is_pk": false,

"name": "__ums__op__",

"nullable": false,

"type": "string"

},

{

"is_pk": false,

"name": "id",

"nullable": false,

"type": "int(11)"

},

{

"is_pk": false,

"name": "name",

"nullable": false,

"type": "varchar(50)"

}

],

"kudu_table_name": "mytest01",

"namespace": "mysql.lijie"

}

}

(4)自定义一个Writer而后须要重写kafka的partition,对库名+表名进行hash分组,保证对于一个表的操做只能在一个partition里面而且是有序的(若是不这样的话,可能一个表的操做会被负载到多个partition里面,消费端拿到的数据就是非顺序性的)。

2.对kafka中转换好的数据进行操做

以下图所示:

be170a81a16746bea602d83c2df7c59b.png

(1)自定义一个kafka的Reader拉取以前转换好的数据。

(2)对拉取到的json数据进行解析字段filter和操做filter顺序不要紧

字段filter就是:一个表可能有10个字段,可是我只须要其中的6个字段就能够本身对字段过滤。可能mysql进行了alter操做,加了字段等操做这些暂时不考虑固然也能够自动处理,如今想的是若是有字段变动须要dba那边提早通知,咱们手动处理。

操做filter就是:可能会有重复的数据,须要先用一个操做集合的全部ums_id进行批量查询(kudu支持批量查询),若是查询到数据就将集合中查询到的ums_id所有抛弃掉,只操做没有查询到的,防止重复操做。

(3)最后就是将信息转换成kudu相应的增删改操做了。

第一次同步的时候采用sqoop,而后再增量,若是中间遇到失败或者什么的异常状况,还有待讨论。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值