Canal 組件簡介與 vivo 賬號實踐

互聯網應用隨着業務的發展,部分單表數據體量愈來愈大,應對服務性能與穩定的考慮,有作分庫分表、數據遷移的須要,本文介紹了vivo賬號應對以上需求的實踐。java

1、前言

Canal 是阿里巴巴開源項目,關於什麼是 Canal?又能作什麼?我會在後文爲你們一一介紹。
在本文您將能夠了解到vivo賬號使用 Canal 解決了什麼樣的業務痛點,基於此但願對您所在業務能有一些啓示。mysql

2、Canal介紹

1. 簡介

Canal [kə'næl],譯意爲水道/管道/溝渠,主要用途是基於 MySQL 數據庫增量日誌解析,提供增量數據訂閱和消費。git

早期阿里巴巴由於杭州和美國雙機房部署,存在跨機房同步的業務需求,實現方式主要是基於業務 trigger 獲取增量變動。從 2010 年開始,業務逐步嘗試數據庫日誌解析獲取增量變動進行同步,由此衍生出了大量的數據庫增量訂閱和消費業務。github

2. 工做原理

2.1 MySQL 主備複製原理

Canal最核心的運行機制就是依賴於MySQL的主備複製,咱們優先簡要說明下MySQL主備複製原理。sql

 

MySQL master 將數據變動寫入二進制日誌( binary log, 其中記錄叫作二進制日誌事件binary log events,能夠經過 show binlog events 進行查看)。數據庫

MySQL slave 將 master 的 binary log events 拷貝到它的中繼日誌(relay log)。api

MySQL slave 重放 relay log 中事件,將數據變動反映它本身的數據。數組

2.2 MySQL Binary Log介紹

MySQL-Binlog是 MySQL 數據庫的二進制日誌,用於記錄用戶對數據庫操做的SQL語句(除了數據查詢語句)信息。緩存

若是後續咱們須要配置主從數據庫,若是咱們須要從數據庫同步主數據庫的內容,咱們就能夠經過 Binlog來進行同步。網絡

2.3 Canal 工做原理

Canal 模擬MySQL slave的交互協議,假裝本身爲MySQL slave,向MySQL master發送dump協議。

MySQL master收到dump請求,開始推送binary log給slave(也就是Canal)。

Canal 解析 binary log 對象(原始爲byte流)。

Canal 把解析後的 binary log 以特定格式的進行推送,供下游消費。

2.4 Canal 總體架構

說明:

  • server 表明一個canal運行實例,對應於一個jvm
  • instance 對應於一個數據隊列 (1個server對應1..n個instance)

instance模塊:

  • EventParser(數據源接入,模擬slave協議和master進行交互,協議解析)
    與數據庫交互模擬從庫,發送dump binlog請求,接收binlog進行協議解析並作數據封裝,並將數據傳遞至下層EventSink進行存儲,記錄binlog同步位置。
  • EventSink(Parser和Store連接器,進行數據過濾,加工,分發的工做)
    數據過濾、數據歸併、數據加工、數據路由存儲。
  • EventStore(數據存儲)
    管理數據對象存儲,包括新binlog對象的寫入管理、對象訂閱的位置管理、對象消費成功的回執位置管理。
  • MetaManager(增量訂閱&消費信息管理器)

    負責binlog對象總體的發佈訂閱管理器,相似於MQ。

2.5 Canal 數據格式

下面咱們來一塊兒看下Canal內部封裝的 Binlog對象格式,更好的理解 Canal。

Canal可以同步 DCL、 DML、 DDL。

業務一般關心 INSERT、 UPDATE、 DELETE引發的數據變動。

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       [具體的內容,注意爲文本]

2.6 Canal 示例 demo

下面咱們經過實際代碼邏輯的判斷,查看 Binlog解析成Canal 對象的數據模型,加深理解

  • insert 語句

  • delete語句

  • update語句

2.7 Canal HA 機制

線上服務的穩定性極爲重要,Canal是支持HA的,其實現機制也是依賴Zookeeper來實現的,與HDFS的HA相似。

Canal的HA分爲兩部分,Canal server和Canal client分別有對應的HA實現。

  • Canal Server:爲了減小對mysql dump的請求,不一樣server上的instance要求同一時間只能有一個處於running,其餘的處於standby狀態。
  • Canal Client:爲了保證有序性,一份instance同一時間只能由一個canal client進行get/ack/rollback操做,不然客戶端接收沒法保證有序。

依賴Zookeeper的特性(本文不着重講解zookeeper特性,請在網絡上查找對應資料):

  • Watcher機制
  • EPHEMERAL節點(和session生命週期綁定)

大體步驟:

Canal server要啓動某個canal instance時都先向zookeeper進行一次嘗試啓動判斷 (實現:建立EPHEMERAL節點,誰建立成功就容許誰啓動)。

建立 ZooKeeper節點成功後,對應的Canal server就啓動對應的Canal instance,沒有建立成功的Canal instance就會處於standby狀態。

一旦ZooKeeper發現Canal server A建立的節點消失後,當即通知其餘的Canal server再次進行步驟1的操做,從新選出一個Canal server啓動instance。

Canal client每次進行connect時,會首先向ZooKeeper詢問當前是誰啓動了Canal instance,而後和其創建連接,一旦連接不可用,會從新嘗試connect。

2.8 Canal 使用場景

上面介紹了Canal 的原理與運行機制,下面咱們從實際場景來看,Canal 可以爲咱們業務場景解決什麼樣的問題。

2.8.1 不停服遷移

業務在發展初期,爲了快速支撐業務發展,不少數據存儲設計較爲粗放,好比用戶表、訂單表可能都會設計爲單表,此時常規手段會採用分庫分表來解決容量和性能問題。

但數據遷移會面臨最大的問題:線上業務須要正常運行,若是數據在遷移過程當中有變動,如何保證數據一致性是最大的挑戰。

基於Canal,經過訂閱數據庫的 Binlog,能夠很好地解決這一問題。

可詳見下方vivo賬號的不停機遷移實踐。

2.8.2 緩存刷新

互聯網業務數據源不只僅爲數據庫,好比 Redis 在互聯網業務較爲經常使用,在數據變動時須要刷新緩存,常規手段是在業務邏輯代碼中手動刷新。

基於Canal,經過訂閱指定表數據的Binlog,能夠異步解耦刷新緩存。

2.8.3 任務下發

另外一種常見應用場景是「下發任務」,當數據變動時須要通知其餘依賴系統。

其原理是任務系統監聽數據庫變動,而後將變動的數據寫入MQ/Kafka進行任務下發。

好比賬號註銷時下游業務方須要訂單此通知,爲用戶刪除業務數據,或者作數據歸檔等。

基於Canal能夠保證數據下發的精確性,同時業務系統中不會散落着各類下發MQ的代碼,從而實現了下發歸集,以下圖所示:

2.8.4 數據異構

在大型網站架構中,數據庫都會採用分庫分表來解決容量和性能問題,但分庫分表以後帶來的新問題。

好比不一樣維度的查詢或者聚合查詢,此時就會很是棘手。通常咱們會經過數據異構機制來解決此問題。

所謂的數據異構,那就是將須要join查詢的多表按照某一個維度又聚合在一個DB中。

基於Canal能夠實現數據異構,以下圖示意:

三、Canal 的安裝及使用

Canal的詳細安裝、配置與使用,請查閱官方文檔 >\> 連接

3、賬號實踐

一、實踐一:分庫分表

1.1 需求

  • 難點:

表數據量大,單表3億多。

常規定時任務遷移全量數據,時間長且對業務有損。

  • 核心訴求:

不停機遷移,最大化保證業務不受影響

「給在公路上跑着的車換輪胎」

1.2 遷移方案

1.3 遷移過程

總體過程大體以下:

  • 分析賬號現有痛點
單表數據量過大:賬號單表3億+

用戶惟一標識過多

業務劃分不合理

  • 肯定分庫分表方案
  • 存量數據遷移方案
使用傳統的定時任務遷移,時長過長,且遷移過程當中爲了保證數據一致性,須要停機維護,對用戶影響較大。

肯定使用canal進行遷移,對canal作充分調研與評估,與中間件及DBA共同肯定,可支持全量、以及增量同步。

  • 遷移過程經過開關進行控制,單表模式 → 雙寫模式 → 分表模式。
  • 數據遷移週期長,遷移過程當中遇到部分未能預估到的問題,進行了屢次遷移。
  • 遷移完成後,正式切換至雙寫模式,即單表及分表一樣寫入數據,此時數據讀取仍然在單表模式下讀取數據,Canal仍然訂閱原有單表,進行數據變動。
  • 運行兩週後線上未產生新問題,正式切至分表模式,此時原有單表再也不寫入數據,即單表不會再有新的Binlog產生,切換後線上出現了部分問題,即時跟進處理,「有驚無險」。

二、實踐二:跨國數據遷移

2.1 需求

在vivo海外業務開展初期,海外部分國家的數據存儲在中立國新加坡機房,但隨着海外國家法律合規要求愈來愈嚴格,特別是歐盟地區的GDPR合規要求,vivo賬號應對合規要求,作了比較多的合規改造工做。

部分非歐盟地區的國家合規要求隨之變化,舉例澳洲當地要求知足GDPR合規要求,原有存儲在新加坡機房的澳洲用戶數據須要遷移至歐盟機房,總體遷移複雜度增長,其中涉及到的難點有:

  • 不停機遷移,已出貨的手機用戶須要能正常訪問賬號服務。
  • 數據一致性,用戶變動數據一致性須要保證。
  • 業務方影響,不能影響現網業務方正常使用賬號服務。

2.2 遷移方案

2.3 遷移過程

  • 在新加坡機房搭建備庫,主從同步 Binlog。
  • 搭建 Canal 的server及client端,同步訂閱消費Binlog。
  • client端基於訂閱的Binlog進行解析,將數據加密傳輸至歐盟GDPR機房。
  • 歐盟應用數據解析傳輸的數據,落地存儲。
  • 數據同步完成後運維同事協助將上層域名的DNS解析轉發至歐盟機房,完成數據切換。
  • 觀察新加坡機房Canal服務運行狀況,沒有異常後中止Canal服務。
  • 經過業務方,賬號側完成切換。
  • 待業務方同步切換完成後,將新加坡機房的數據清除。

三、經驗總結

3.1數據序列化

Canal底層使用protobuf做爲數據數據列化的方式,Canal-client在訂閱到變動數據時,爲null的數據會自動轉換爲空字符串,在ORM側數據更新時,因判斷邏輯不一致,致使最終表中數據更新爲空字符串。

3.2  數據一致性

賬號本次線上Canal-client只有單節點,但在數據遷移過程當中,因業務特性,致使數據出現了不一致的現象,示例大體以下:

  • 用戶換綁手機號A。
  • Canal此時在還未訂閱到此 Binlog position。
  • 用戶又換綁手機號B。
  • 在對應時刻,Canal消費到更新手機號A的Binlog,致使用戶新換綁的手機號作了覆蓋。

3.3 數據庫主從延時

出於數據一致性地考慮(結合賬號業務數據未達到須要分庫的必要性),賬號分表在同一數據庫進行,即遷移過程當中分表數據不斷地進行寫入,加大數據庫負載的同時形成了從庫讀取延時。

解決方案:增長速率控制,基於業務的實際狀況,配置不一樣的策略,例如白天業務量大,能夠適當下降寫入速度,夜間業務量小,能夠適當提高寫入速度。

3.4 監控告警

在總體數據遷移過程當中,vivo賬號在client端增長了實時同步數據的簡易監控手段,即基於業務表基於內存作計數。

總體監控粒度較粗,包括以上數據不一致性,在數據同步完成後,未能發現異常,致使切換至分表模式下出現了業務問題,好在邏輯數據能夠經過補償等其餘手段彌補,且對線上數據影響較小。

4、拓展思考

一、現有問題分析

以上是基於 Canal現有架構畫出的簡易圖,雖然基於HA總體高可用,但細究後仍是會發現一些隱患,其中標記紅色X的節點,能夠視爲可能出現的故障點。

二、通用組件複用

基於以上可能出現的問題點,咱們能夠嘗試作上圖中的優化。

三、延展應用-多數據中心同步

在互聯網行業,你們對「異地多活」已經耳熟能詳,而數據同步是異地多活的基礎,全部具有數據存儲能力的組件如:數據庫、緩存、MQ等,數據均可以進行同步,造成一個龐大而複雜的數據同步拓撲,相互備份對方的數據,才能作到真正意義上"異地多活」。

本邏輯不在本次討論範圍內,你們能夠參閱如下文章內容,筆者我的認爲講解較爲詳細:http://www.tianshouzhi.com/api/tutorials/canal/404

5、參考資料

做者:vivo 產品平臺開發團隊
相關文章
相關標籤/搜索