异构数据同步之如何发送Binlog?

378 阅读3分钟

链接:mp.weixin.qq.com/s/3mOdxTteXnqdmW-f3JhWsA 作者:潘新宇

更多干货关注公众号 勾勾的Java宇宙(Javagogo)


基于 Binlog 完成数据同步的全量缓存的读服务架构方案,可以实现平均性能在一百毫秒以内的高可用方案。不仅可以满足缓存同步的实时性要求,还能够降低同步的复杂度,以及解决分布式事务问题。

如何发送 Binlog?

以 MySQL 作为示例,MySQL 的 Binlog 分为三种数据格式:statementrowmixed,示例:

create table demo_table{
  id bigint not null auto_increment comment '主键',
  message varchar(100) not null comment '消息',
  status tinyint not null comment '状态',
  created datetime not null '创建时间',
  modified datetime not null '修改时间',
  primary key ('id') using btree
}

1. statement 格式

statement 格式是把每次执行的 SQL 语句记录到 Binlog 文件里,在主从复制时,基于 Binlog 里的 SQL 语句进行回放来完成主从复制。

比如执行了如下 SQL 成功后:

update demo_table set status='无效' where id =1

Binlog 中记录的便是上述这条具体的 SQL。

采用 SQL 格式的 Binlog 的好处是内容太少,传输速度快。但存在一个问题,在基于 Binlog 进行数据同步时,需要解析上述的 SQL 获取变更的字段,存在一定的开发成本。

2. row 格式

row 格式的 Binlog 会把当次执行的 SQL 命中的那条数据库行的变更前和变更后的内容,都记录到 Binlog 文件里。以上述 statement 格式里的 SQL 作为示例,该 SQL 在 row 格式下执行后会产生如下的数据:

{
  "before":{
    "id":1,
    "message":"文本""status":"有效",
    "created":"xxxx-xx-xx",
    "modified":"xxxx-xx-xx"
  },
  "after":{
    "id":1,
    "message":"文本""status":"无效",
    "created":"xxxx-xx-xx",
    "modified":"xxxx-xx-xx"
  },
  "change_fields":["status"]
}

上述案例记录的 Binlog 数据非常全面,包含了 demo_table 中所有字段对应的变更和未变更的数据,同时标记了具体哪些字段发生了变更。在数据同步时,可以完全以它为准。

基于上述格式的数据同步的实现代码会非常简单,但缺点是,产生的数据量较大。

  1. mixed 格式

mixed 是上述两种模式的动态结合。采用 mixed 格式的 Binlog 会根据每一条执行的 SQL 动态判断是记录为 row 格式还是 statement 格式。

比如一些 DDL 语句,如新增加字段的 SQL,就没有必要记录为 row 格式,记录为 statement 即可,因为它本身并没有涉及数据变更。

在实际应用中,推荐使用 row 或者 mixed

  • 原因一:这两种格式的数据量全,可以让你做更多的逻辑。因为随着业务需求的发展,同步逻辑会出现非常多的个性化需求,越多信息的数据,在编写代码时会越简单。

  • 原因二:row 格式无须解析 SQL,实现复杂度非常低。在执行的 SQL 非常复杂时,对 statement 格式里记录的 SQL 的解析需要耗费大量开发精力,越复杂的解析越容易产生 Bug,所以推荐更加简单的 row 格式的数据。


链接:mp.weixin.qq.com/s/3mOdxTteXnqdmW-f3JhWsA 作者:潘新宇

更多干货关注公众号 勾勾的Java宇宙(Javagogo)