https://github.com/alibaba/canalnode
canal是阿里巴巴旗下的一款開源項目,純Java開發。基於數據庫增量日誌解析,提供增量數據訂閱&消費,目前主要支持了MySQL(也支持mariaDB)。mysql
起源:早期,阿里巴巴B2B公司由於存在杭州和美國雙機房部署,存在跨機房同步的業務需求。不過早期的數據庫同步業務,主要是基於trigger的方式獲取增量變動,不過從2010年開始,阿里系公司開始逐步的嘗試基於數據庫的日誌解析,獲取增量變動進行同步,由此衍生出了增量訂閱&消費的業務,今後開啓了一段新紀元。git
基於日誌增量訂閱&消費支持的業務:github
mysql主備複製實現:web
從上層來看,複製分紅三步:spring
原理相對比較簡單:sql
我的理解,數據增量訂閱與消費應當有以下幾個點:docker
能夠參考下圖:數據庫
說明:api
instance模塊:
整個parser過程大體可分爲幾部:
說明:
1 數據1:n業務 :
爲了合理的利用數據庫資源, 通常常見的業務都是按照schema進行隔離,而後在mysql上層或者dao這一層面上,進行一個數據源路由,屏蔽數據庫物理位置對開發的影響,阿里系主要是經過cobar/tddl來解決數據源路由問題。 因此,通常一個數據庫實例上,會部署多個schema,每一個schema會有由1個或者多個業務方關注。
2 數據n:1業務:
一樣,當一個業務的數據規模達到必定的量級後,必然會涉及到水平拆分和垂直拆分的問題,針對這些拆分的數據須要處理時,就須要連接多個store進行處理,消費的位點就會變成多份,並且數據消費的進度沒法獲得儘量有序的保證。 因此,在必定業務場景下,須要將拆分後的增量數據進行歸併處理,好比按照時間戳/全局id進行排序歸併.
目前實現了Memory內存、本地file存儲以及持久化到zookeeper以保障數據集羣共享。
Memory內存的RingBuffer設計:
定義了3個cursor
借鑑Disruptor的RingBuffer的實現,將RingBuffer拉直來看:
實現說明:
instance表明了一個實際運行的數據隊列,包括了EventPaser,EventSink,EventStore等組件。
抽象了CanalInstanceGenerator,主要是考慮配置的管理方式:
1. manager方式: 和你本身的內部web console/manager系統進行對接。(alibaba內部使用方式)
2. spring方式:基於spring xml + properties進行定義,構建spring配置.
server表明了一個canal的運行實例,爲了方便組件化使用,特地抽象了Embeded(嵌入式) / Netty(網絡訪問)的兩種實現:
具體的協議格式,可參見:CanalProtocol.proto
get/ack/rollback協議介紹:
流式api設計:
canal採用protobuff:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
Entry
Header
logfileName [binlog文件名]
logfileOffset [binlog position]
executeTime [發生的變動]
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
sqlType [jdbc type]
name [column name]
isKey [是否爲主鍵]
updated [是否發生過變動]
isNull [值是否爲
null
]
value [具體的內容,注意爲文本]
|
canal-message example:
好比數據庫中的表:
1
2
3
4
5
6
7
8
9
|
mysql> select * from person;
+----+------+------+------+
| id | name | age | sex |
+----+------+------+------+
|
1
| zzh |
10
| m |
|
3
| zzh3 |
12
| f |
|
4
| zzh4 |
5
| m |
+----+------+------+------+
3
rows
in
set
(
0.00
sec)
|
更新一條數據(update person set age=15 where id=4):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
****************************************************
* Batch Id: [
2
] ,count : [
3
] , memsize : [
165
] , Time :
2016
-
09
-
07
15
:
54
:
18
* Start : [mysql-bin.
000003
:
6354
:
1473234846000
(
2016
-
09
-
07
15
:
54
:
06
)]
* End : [mysql-bin.
000003
:
6550
:
1473234846000
(
2016
-
09
-
07
15
:
54
:
06
)]
****************************************************
================> binlog[mysql-bin.
000003
:
6354
] , executeTime :
1473234846000
, delay : 12225ms
BEGIN ----> Thread id:
67
----------------> binlog[mysql-bin.
000003
:
6486
] , name[canal_test,person] , eventType : UPDATE , executeTime :
1473234846000
, delay : 12225ms
id :
4
type=
int
(
11
)
name : zzh4 type=varchar(
100
)
age :
15
type=
int
(
11
) update=
true
sex : m type=
char
(
1
)
----------------
END ----> transaction id:
308
================> binlog[mysql-bin.
000003
:
6550
] , executeTime :
1473234846000
, delay : 12240ms
|
canal的HA分爲兩部分,canal server和canal client分別有對應的ha實現:
整個HA機制的控制主要是依賴了zookeeper的幾個特性,watcher和EPHEMERAL節點(和session生命週期綁定),能夠看下我以前zookeeper的相關文章。
Canal Server:
大體步驟:
HA配置架構圖(舉例)以下所示:
canal還有幾種鏈接方式:
1. 單連
2. 兩個client+兩個instance+1個mysql
當mysql變更時,兩個client都能獲取到變更
3. 一個server+兩個instance+兩個mysql+兩個client
4. instance的standby配置
從總體架構上來講canal是這種架構的(canal中沒有包含一個運維的console web來對接,但要運用於分佈式環境中確定須要一個Manager來管理):
一個整體的manager system對應於n個Canal Server(物理上來講是一臺服務器), 那麼一個Canal Server對應於n個Canal Instance(destinations). 大致上是三層結構,第二層也須要Manager統籌運維管理。
那麼隨着Docker技術的興起,是否能夠試一下下面的架構呢?
這裏總結了一下Canal的一些點,僅供參考: