diff --git a/Introduction-en.md b/Introduction-en.md deleted file mode 100644 index 8be5567..0000000 --- a/Introduction-en.md +++ /dev/null @@ -1,44 +0,0 @@ -# Introduction - -**Canal** is a high performance data synchronization system based on MySQL binary log. Canal is widely used in Alibaba group (including [https://www.taobao.com](https://www.taobao.com/)) to provide reliable low latency incremental data pipeline. - -**Canal Server** is capable of parsing MySQL binlog and subscribe to the data change, while **Canal Client** can be implemented to broadcast the change to anywhere, e.g. database and [Apache Kafka](https://kafka.apache.org/). - -It has following features: - -1. Support all platforms. -2. Support fine-grained system monitoring, powered by [Prometheus](https://prometheus.io/). -3. Support parsing and subscription to MySQL binlog by different ways, e.g. by GTID. -4. Support high performance, real-time data synchronization. (See more at [Performance](https://github.com/alibaba/canal/wiki/Performance)) -5. Both Canal Server and Canal Client support HA/Scalability, powered by [Apache ZooKeeper](https://zookeeper.apache.org/) -6. Docker Supports. - -## Backgrounds - -In the early days, Alibaba B2B Company needed to syncrhonize servers' data between the United States and Hangzhou, China. Previous database synchronization machenism was based on the `trigger` to obtain incremental updates. Starting from 2010, Alibaba Group began to use dataset **binary log** to get the incremental updates and synchronize data across servers, which gave birth to our incremental subscription & consumption service (available now in Alibaba Cloud) and started a new era. - -## How it works - -### MySQL Master-Slave Replication Implementation - -![img](https://camo.githubusercontent.com/eec1605862fe9e9989b97dd24f28a4bc5d7debec/687474703a2f2f646c2e69746579652e636f6d2f75706c6f61642f6174746163686d656e742f303038302f333038362f34363863316131342d653761642d333239302d396433642d3434616335303161373232372e6a7067) - - - -Replication follows 3-step procedure: - -1. The Master server records the changes to the binlog (these records are called binlog events, which can be viewed through `show binary events`) -2. The Slave server copies master's binary log events to its relay log. -3. The Slave server redo events in the relay log will subsequently update its old data. - - - -### How Canal works - -![img](https://camo.githubusercontent.com/46c626b4cde399db43b2634a7911a04aecf273a0/687474703a2f2f646c2e69746579652e636f6d2f75706c6f61642f6174746163686d656e742f303038302f333130372f63383762363762612d333934632d333038362d393537372d3964623035626530346339352e6a7067) - -The principle is simple: - -1. Canal simulates MySQL the slave's interaction protocol, disguises itself as mysql slave, and sends dump protocol to MySQL Master server. -2. MySQL Master received the dump request and started pushing binary log to slave (which is canal). -3. Canal parses binary log object to its own data type (originally byte stream) \ No newline at end of file diff --git a/Introduction.md b/Introduction.md index be76948..8be5567 100644 --- a/Introduction.md +++ b/Introduction.md @@ -1,228 +1,44 @@ -
-
-

-

背景

-

早期,阿里巴巴B2B公司因为存在杭州和美国双机房部署,存在跨机房同步的业务需求。不过早期的数据库同步业务,主要是基于trigger的方式获取增量变更,不过从2010年开始,阿里系公司开始逐步的尝试基于数据库的日志解析,获取增量变更进行同步,由此衍生出了增量订阅&消费的业务,从此开启了一段新纪元。ps. 目前内部使用的同步,已经支持mysql5.x和oracle部分版本的日志解析

-

-

基于日志增量订阅&消费支持的业务:

-
    -
  1. 数据库镜像
  2. -
  3. 数据库实时备份
  4. -
  5. 多级索引 (卖家和买家各自分库索引)
  6. -
  7. search build
  8. -
  9. 业务cache刷新
  10. -
  11. 价格变化等重要业务消息
  12. -
-

项目介绍

-

名称:canal [kə'næl]

-

译意: 水道/管道/沟渠

-

语言: 纯java开发

-

定位: 基于数据库增量日志解析,提供增量数据订阅&消费,目前主要支持了mysql

-

关键词: mysql binlog parser / real-time / queue&topic

-

-

工作原理

-

mysql主备复制实现

-


从上层来看,复制分成三步:

-
    -
  1. master将改变记录到二进制日志(binary log)中(这些记录叫做二进制日志事件,binary log events,可以通过show binlog events进行查看);
  2. -
  3. slave将master的binary log events拷贝到它的中继日志(relay log);
  4. -
  5. slave重做中继日志中的事件,将改变反映它自己的数据。
  6. -
-

canal的工作原理:

-

-

原理相对比较简单:

-
    -
  1. canal模拟mysql slave的交互协议,伪装自己为mysql slave,向mysql master发送dump协议
  2. -
  3. mysql master收到dump请求,开始推送binary log给slave(也就是canal)
  4. -
  5. canal解析binary log对象(原始为byte流)
  6. -
-

架构

-

-

说明:

- -

instance模块:

- -

知识科普

-

MySQL 的 Binary Log 介绍

- -

简单点说:

- -

目前canal支持所有模式的增量订阅(但配合同步时,因为statement只有sql,没有数据,无法获取原始的变更日志,所以一般建议为ROW模式)

-

-

-

EventParser设计

-

大致过程:

-

-

整个parser过程大致可分为几步:

-
    -
  1. Connection获取上一次解析成功的位置 (如果第一次启动,则获取初始指定的位置或者是当前数据库的binlog位点)
  2. -
  3. Connection建立链接,发送BINLOG_DUMP指令
    // 0. write command number
    // 1. write 4 bytes bin-log position to start at
    // 2. write 2 bytes bin-log flags
    // 3. write 4 bytes server id of the slave
    // 4. write bin-log file name
  4. -
  5. Mysql开始推送Binaly Log
  6. -
  7. 接收到的Binaly Log的通过Binlog parser进行协议解析,补充一些特定信息
    // 补充字段名字,字段类型,主键信息,unsigned类型处理
  8. -
  9. 传递给EventSink模块进行数据存储,是一个阻塞操作,直到存储成功
  10. -
  11. 存储成功后,定时记录Binaly Log位置
  12. -
-

mysql的Binlay Log网络协议:

-

-

-

说明:

- -

EventSink设计

-

-

说明:

- -

数据1:n业务

-

为了合理的利用数据库资源, 一般常见的业务都是按照schema进行隔离,然后在mysql上层或者dao这一层面上,进行一个数据源路由,屏蔽数据库物理位置对开发的影响,阿里系主要是通过cobar/tddl来解决数据源路由问题。

-

所以,一般一个数据库实例上,会部署多个schema,每个schema会有由1个或者多个业务方关注

-

-

数据n:1业务

-

同样,当一个业务的数据规模达到一定的量级后,必然会涉及到水平拆分和垂直拆分的问题,针对这些拆分的数据需要处理时,就需要链接多个store进行处理,消费的位点就会变成多份,而且数据消费的进度无法得到尽可能有序的保证。

-

所以,在一定业务场景下,需要将拆分后的增量数据进行归并处理,比如按照时间戳/全局id进行排序归并.

-

-

EventStore设计

- -

RingBuffer设计:

-

-

定义了3个cursor

- -

借鉴Disruptor的RingBuffer的实现,将RingBuffer拉直来看:

-

实现说明:

- -

Instance设计

-


-

-

instance代表了一个实际运行的数据队列,包括了EventPaser,EventSink,EventStore等组件。

-

抽象了CanalInstanceGenerator,主要是考虑配置的管理方式:

- -

Server设计

-


-

server代表了一个canal的运行实例,为了方便组件化使用,特意抽象了Embeded(嵌入式) / Netty(网络访问)的两种实现

- -

增量订阅/消费设计

-

-

具体的协议格式,可参见:CanalProtocol.proto

-

get/ack/rollback协议介绍:

- -

canal的get/ack/rollback协议和常规的jms协议有所不同,允许get/ack异步处理,比如可以连续调用get多次,后续异步按顺序提交ack/rollback,项目中称之为流式api.

-

流式api设计的好处:

- -

流式api设计:

-

- -

数据对象格式:EntryProtocol.proto -

-
Entry
-	Header
-		logfileName [binlog文件名]
-		logfileOffset [binlog position]
-		executeTime [binlog里记录变更发生的时间戳]
-		schemaName [数据库实例]
-		tableName [表名]
-		eventType [insert/update/delete类型]
-	entryType 	[事务头BEGIN/事务尾END/数据ROWDATA]
-	storeValue 	[byte数据,可展开,对应的类型为RowChange]
-	
-RowChange
-	isDdl		[是否是ddl变更操作,比如create table/drop table]
-	sql		[具体的ddl sql]
-	rowDatas	[具体insert/update/delete的变更数据,可为多条,1个binlog event事件可对应多条变更,比如批处理]
-		beforeColumns [Column类型的数组]
-		afterColumns [Column类型的数组]
-		
-Column 
-	index		[column序号]
-	sqlType		[jdbc type]
-	name		[column name]
-	isKey		[是否为主键]
-	updated		[是否发生过变更]
-	isNull		[值是否为null]
-	value		[具体的内容,注意为文本]
-

说明:

- -

HA机制设计

-

canal的ha分为两部分,canal server和canal client分别有对应的ha实现

- -

整个HA机制的控制主要是依赖了zookeeper的几个特性,watcher和EPHEMERAL节点(和session生命周期绑定),可以看下我之前zookeeper的相关文章。

-

-

Canal Server:

-


大致步骤:

-
    -
  1. canal server要启动某个canal instance时都先向zookeeper进行一次尝试启动判断 (实现:创建EPHEMERAL节点,谁创建成功就允许谁启动)
  2. -
  3. 创建zookeeper节点成功后,对应的canal server就启动对应的canal instance,没有创建成功的canal instance就会处于standby状态
  4. -
  5. 一旦zookeeper发现canal server A创建的节点消失后,立即通知其他的canal server再次进行步骤1的操作,重新选出一个canal server启动instance.
  6. -
  7. canal client每次进行connect时,会首先向zookeeper询问当前是谁启动了canal instance,然后和其建立链接,一旦链接不可用,会重新尝试connect.
  8. -
-

Canal Client的方式和canal server方式类似,也是利用zookeeper的抢占EPHEMERAL节点的方式进行控制.

-

\ No newline at end of file +It has following features: + +1. Support all platforms. +2. Support fine-grained system monitoring, powered by [Prometheus](https://prometheus.io/). +3. Support parsing and subscription to MySQL binlog by different ways, e.g. by GTID. +4. Support high performance, real-time data synchronization. (See more at [Performance](https://github.com/alibaba/canal/wiki/Performance)) +5. Both Canal Server and Canal Client support HA/Scalability, powered by [Apache ZooKeeper](https://zookeeper.apache.org/) +6. Docker Supports. + +## Backgrounds + +In the early days, Alibaba B2B Company needed to syncrhonize servers' data between the United States and Hangzhou, China. Previous database synchronization machenism was based on the `trigger` to obtain incremental updates. Starting from 2010, Alibaba Group began to use dataset **binary log** to get the incremental updates and synchronize data across servers, which gave birth to our incremental subscription & consumption service (available now in Alibaba Cloud) and started a new era. + +## How it works + +### MySQL Master-Slave Replication Implementation + +![img](https://camo.githubusercontent.com/eec1605862fe9e9989b97dd24f28a4bc5d7debec/687474703a2f2f646c2e69746579652e636f6d2f75706c6f61642f6174746163686d656e742f303038302f333038362f34363863316131342d653761642d333239302d396433642d3434616335303161373232372e6a7067) + + + +Replication follows 3-step procedure: + +1. The Master server records the changes to the binlog (these records are called binlog events, which can be viewed through `show binary events`) +2. The Slave server copies master's binary log events to its relay log. +3. The Slave server redo events in the relay log will subsequently update its old data. + + + +### How Canal works + +![img](https://camo.githubusercontent.com/46c626b4cde399db43b2634a7911a04aecf273a0/687474703a2f2f646c2e69746579652e636f6d2f75706c6f61642f6174746163686d656e742f303038302f333130372f63383762363762612d333934632d333038362d393537372d3964623035626530346339352e6a7067) + +The principle is simple: + +1. Canal simulates MySQL the slave's interaction protocol, disguises itself as mysql slave, and sends dump protocol to MySQL Master server. +2. MySQL Master received the dump request and started pushing binary log to slave (which is canal). +3. Canal parses binary log object to its own data type (originally byte stream) \ No newline at end of file diff --git a/_Sidebar.md b/_Sidebar.md index 4e820a6..b18c7af 100644 --- a/_Sidebar.md +++ b/_Sidebar.md @@ -1,7 +1,7 @@

目录

* [[Home]] -* [[Introduction]] +* [Introduction](Introduction.md) / [简介](简介.md) * Quick Start * [[QuickStart]] * [[Docker QuickStart]] diff --git a/简介.md b/简介.md new file mode 100644 index 0000000..be76948 --- /dev/null +++ b/简介.md @@ -0,0 +1,228 @@ +
+
+

+

背景

+

早期,阿里巴巴B2B公司因为存在杭州和美国双机房部署,存在跨机房同步的业务需求。不过早期的数据库同步业务,主要是基于trigger的方式获取增量变更,不过从2010年开始,阿里系公司开始逐步的尝试基于数据库的日志解析,获取增量变更进行同步,由此衍生出了增量订阅&消费的业务,从此开启了一段新纪元。ps. 目前内部使用的同步,已经支持mysql5.x和oracle部分版本的日志解析

+

+

基于日志增量订阅&消费支持的业务:

+
    +
  1. 数据库镜像
  2. +
  3. 数据库实时备份
  4. +
  5. 多级索引 (卖家和买家各自分库索引)
  6. +
  7. search build
  8. +
  9. 业务cache刷新
  10. +
  11. 价格变化等重要业务消息
  12. +
+

项目介绍

+

名称:canal [kə'næl]

+

译意: 水道/管道/沟渠

+

语言: 纯java开发

+

定位: 基于数据库增量日志解析,提供增量数据订阅&消费,目前主要支持了mysql

+

关键词: mysql binlog parser / real-time / queue&topic

+

+

工作原理

+

mysql主备复制实现

+


从上层来看,复制分成三步:

+
    +
  1. master将改变记录到二进制日志(binary log)中(这些记录叫做二进制日志事件,binary log events,可以通过show binlog events进行查看);
  2. +
  3. slave将master的binary log events拷贝到它的中继日志(relay log);
  4. +
  5. slave重做中继日志中的事件,将改变反映它自己的数据。
  6. +
+

canal的工作原理:

+

+

原理相对比较简单:

+
    +
  1. canal模拟mysql slave的交互协议,伪装自己为mysql slave,向mysql master发送dump协议
  2. +
  3. mysql master收到dump请求,开始推送binary log给slave(也就是canal)
  4. +
  5. canal解析binary log对象(原始为byte流)
  6. +
+

架构

+

+

说明:

+
    +
  • server代表一个canal运行实例,对应于一个jvm
  • +
  • instance对应于一个数据队列 (1个server对应1..n个instance)
  • +
+

instance模块:

+
    +
  • eventParser (数据源接入,模拟slave协议和master进行交互,协议解析)
  • +
  • eventSink (Parser和Store链接器,进行数据过滤,加工,分发的工作)
  • +
  • eventStore (数据存储)
  • +
  • metaManager (增量订阅&消费信息管理器)
  • +
+

知识科普

+

MySQL 的 Binary Log 介绍

+ +

简单点说:

+
    +
  • mysql的binlog是多文件存储,定位一个LogEvent需要通过binlog filename + binlog position,进行定位
  • +
  • mysql的binlog数据格式,按照生成的方式,主要分为:statement-based、row-based、mixed。
    mysql> show variables like 'binlog_format';
    ++---------------+-------+
    +| Variable_name | Value |
    ++---------------+-------+
    +| binlog_format | ROW   |
    ++---------------+-------+
    +1 row in set (0.00 sec)
    +
  • +
+

目前canal支持所有模式的增量订阅(但配合同步时,因为statement只有sql,没有数据,无法获取原始的变更日志,所以一般建议为ROW模式)

+

+

+

EventParser设计

+

大致过程:

+

+

整个parser过程大致可分为几步:

+
    +
  1. Connection获取上一次解析成功的位置 (如果第一次启动,则获取初始指定的位置或者是当前数据库的binlog位点)
  2. +
  3. Connection建立链接,发送BINLOG_DUMP指令
    // 0. write command number
    // 1. write 4 bytes bin-log position to start at
    // 2. write 2 bytes bin-log flags
    // 3. write 4 bytes server id of the slave
    // 4. write bin-log file name
  4. +
  5. Mysql开始推送Binaly Log
  6. +
  7. 接收到的Binaly Log的通过Binlog parser进行协议解析,补充一些特定信息
    // 补充字段名字,字段类型,主键信息,unsigned类型处理
  8. +
  9. 传递给EventSink模块进行数据存储,是一个阻塞操作,直到存储成功
  10. +
  11. 存储成功后,定时记录Binaly Log位置
  12. +
+

mysql的Binlay Log网络协议:

+

+

+

说明:

+ +

EventSink设计

+

+

说明:

+
    +
  • 数据过滤:支持通配符的过滤模式,表名,字段内容等
  • +
  • 数据路由/分发:解决1:n (1个parser对应多个store的模式)
  • +
  • 数据归并:解决n:1 (多个parser对应1个store)
  • +
  • 数据加工:在进入store之前进行额外的处理,比如join
  • +
+

数据1:n业务

+

为了合理的利用数据库资源, 一般常见的业务都是按照schema进行隔离,然后在mysql上层或者dao这一层面上,进行一个数据源路由,屏蔽数据库物理位置对开发的影响,阿里系主要是通过cobar/tddl来解决数据源路由问题。

+

所以,一般一个数据库实例上,会部署多个schema,每个schema会有由1个或者多个业务方关注

+

+

数据n:1业务

+

同样,当一个业务的数据规模达到一定的量级后,必然会涉及到水平拆分和垂直拆分的问题,针对这些拆分的数据需要处理时,就需要链接多个store进行处理,消费的位点就会变成多份,而且数据消费的进度无法得到尽可能有序的保证。

+

所以,在一定业务场景下,需要将拆分后的增量数据进行归并处理,比如按照时间戳/全局id进行排序归并.

+

+

EventStore设计

+
    +
  • 1. 目前仅实现了Memory内存模式,后续计划增加本地file存储,mixed混合模式
  • +
  • 2. 借鉴了Disruptor的RingBuffer的实现思路
  • +
+

RingBuffer设计:

+

+

定义了3个cursor

+
    +
  • Put : Sink模块进行数据存储的最后一次写入位置
  • +
  • Get : 数据订阅获取的最后一次提取位置
  • +
  • Ack : 数据消费成功的最后一次消费位置
  • +
+

借鉴Disruptor的RingBuffer的实现,将RingBuffer拉直来看:

+

实现说明:

+
    +
  • Put/Get/Ack cursor用于递增,采用long型存储
  • +
  • buffer的get操作,通过取余或者与操作。(与操作: cusor & (size - 1) , size需要为2的指数,效率比较高)
  • +
+

Instance设计

+


+

+

instance代表了一个实际运行的数据队列,包括了EventPaser,EventSink,EventStore等组件。

+

抽象了CanalInstanceGenerator,主要是考虑配置的管理方式:

+
    +
  • manager方式: 和你自己的内部web console/manager系统进行对接。(目前主要是公司内部使用)
  • +
  • spring方式:基于spring xml + properties进行定义,构建spring配置.
  • +
+

Server设计

+


+

server代表了一个canal的运行实例,为了方便组件化使用,特意抽象了Embeded(嵌入式) / Netty(网络访问)的两种实现

+
    +
  • Embeded : 对latency和可用性都有比较高的要求,自己又能hold住分布式的相关技术(比如failover)
  • +
  • Netty : 基于netty封装了一层网络协议,由canal server保证其可用性,采用的pull模型,当然latency会稍微打点折扣,不过这个也视情况而定。(阿里系的notify和metaq,典型的push/pull模型,目前也逐步的在向pull模型靠拢,push在数据量大的时候会有一些问题)
  • +
+

增量订阅/消费设计

+

+

具体的协议格式,可参见:CanalProtocol.proto

+

get/ack/rollback协议介绍:

+
    +
  • Message getWithoutAck(int batchSize),允许指定batchSize,一次可以获取多条,每次返回的对象为Message,包含的内容为:
    a. batch id 唯一标识
    b. entries 具体的数据对象,对应的数据对象格式:EntryProtocol.proto +
  • +
  • void rollback(long batchId),顾命思议,回滚上次的get请求,重新获取数据。基于get获取的batchId进行提交,避免误操作
  • +
  • void ack(long batchId),顾命思议,确认已经消费成功,通知server删除数据。基于get获取的batchId进行提交,避免误操作
  • +
+

canal的get/ack/rollback协议和常规的jms协议有所不同,允许get/ack异步处理,比如可以连续调用get多次,后续异步按顺序提交ack/rollback,项目中称之为流式api.

+

流式api设计的好处:

+
    +
  • get/ack异步化,减少因ack带来的网络延迟和操作成本 (99%的状态都是处于正常状态,异常的rollback属于个别情况,没必要为个别的case牺牲整个性能)
  • +
  • get获取数据后,业务消费存在瓶颈或者需要多进程/多线程消费时,可以不停的轮询get数据,不停的往后发送任务,提高并行化. (作者在实际业务中的一个case:业务数据消费需要跨中美网络,所以一次操作基本在200ms以上,为了减少延迟,所以需要实施并行化)
  • +
+

流式api设计:

+

+
    +
  • 每次get操作都会在meta中产生一个mark,mark标记会递增,保证运行过程中mark的唯一性
  • +
  • 每次的get操作,都会在上一次的mark操作记录的cursor继续往后取,如果mark不存在,则在last ack cursor继续往后取
  • +
  • 进行ack时,需要按照mark的顺序进行数序ack,不能跳跃ack. ack会删除当前的mark标记,并将对应的mark位置更新为last ack cusor
  • +
  • 一旦出现异常情况,客户端可发起rollback情况,重新置位:删除所有的mark, 清理get请求位置,下次请求会从last ack cursor继续往后取
  • +
+

数据对象格式:EntryProtocol.proto +

+
Entry
+	Header
+		logfileName [binlog文件名]
+		logfileOffset [binlog position]
+		executeTime [binlog里记录变更发生的时间戳]
+		schemaName [数据库实例]
+		tableName [表名]
+		eventType [insert/update/delete类型]
+	entryType 	[事务头BEGIN/事务尾END/数据ROWDATA]
+	storeValue 	[byte数据,可展开,对应的类型为RowChange]
+	
+RowChange
+	isDdl		[是否是ddl变更操作,比如create table/drop table]
+	sql		[具体的ddl sql]
+	rowDatas	[具体insert/update/delete的变更数据,可为多条,1个binlog event事件可对应多条变更,比如批处理]
+		beforeColumns [Column类型的数组]
+		afterColumns [Column类型的数组]
+		
+Column 
+	index		[column序号]
+	sqlType		[jdbc type]
+	name		[column name]
+	isKey		[是否为主键]
+	updated		[是否发生过变更]
+	isNull		[值是否为null]
+	value		[具体的内容,注意为文本]
+

说明:

+
    +
  • 可以提供数据库变更前和变更后的字段内容,针对binlog中没有的name,isKey等信息进行补全
  • +
  • 可以提供ddl的变更语句
  • +
+

HA机制设计

+

canal的ha分为两部分,canal server和canal client分别有对应的ha实现

+
    +
  • canal server: 为了减少对mysql dump的请求,不同server上的instance要求同一时间只能有一个处于running,其他的处于standby状态.
  • +
  • canal client: 为了保证有序性,一份instance同一时间只能由一个canal client进行get/ack/rollback操作,否则客户端接收无法保证有序。
  • +
+

整个HA机制的控制主要是依赖了zookeeper的几个特性,watcher和EPHEMERAL节点(和session生命周期绑定),可以看下我之前zookeeper的相关文章。

+

+

Canal Server:

+


大致步骤:

+
    +
  1. canal server要启动某个canal instance时都先向zookeeper进行一次尝试启动判断 (实现:创建EPHEMERAL节点,谁创建成功就允许谁启动)
  2. +
  3. 创建zookeeper节点成功后,对应的canal server就启动对应的canal instance,没有创建成功的canal instance就会处于standby状态
  4. +
  5. 一旦zookeeper发现canal server A创建的节点消失后,立即通知其他的canal server再次进行步骤1的操作,重新选出一个canal server启动instance.
  6. +
  7. canal client每次进行connect时,会首先向zookeeper询问当前是谁启动了canal instance,然后和其建立链接,一旦链接不可用,会重新尝试connect.
  8. +
+

Canal Client的方式和canal server方式类似,也是利用zookeeper的抢占EPHEMERAL节点的方式进行控制.

+

\ No newline at end of file