互聯網應用隨着業務的發展,部分單表數據體量愈來愈大,應對服務性能與穩定的考慮,有作分庫分表、數據遷移的須要,本文介紹了vivo賬號應對以上需求的實踐。java
Canal 是阿里巴巴開源項目,關於什麼是 Canal?又能作什麼?我會在後文爲你們一一介紹。
在本文您將能夠了解到vivo賬號使用 Canal 解決了什麼樣的業務痛點,基於此但願對您所在業務能有一些啓示。mysql
Canal [kə'næl],譯意爲水道/管道/溝渠,主要用途是基於 MySQL 數據庫增量日誌解析,提供增量數據訂閱和消費。git
早期阿里巴巴由於杭州和美國雙機房部署,存在跨機房同步的業務需求,實現方式主要是基於業務 trigger 獲取增量變動。從 2010 年開始,業務逐步嘗試數據庫日誌解析獲取增量變動進行同步,由此衍生出了大量的數據庫增量訂閱和消費業務。github
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 中事件,將數據變動反映它本身的數據。數組
MySQL-Binlog是 MySQL 數據庫的二進制日誌,用於記錄用戶對數據庫操做的SQL語句(除了數據查詢語句)信息。緩存
若是後續咱們須要配置主從數據庫,若是咱們須要從數據庫同步主數據庫的內容,咱們就能夠經過 Binlog來進行同步。網絡
Canal 模擬MySQL slave的交互協議,假裝本身爲MySQL slave,向MySQL master發送dump協議。
MySQL master收到dump請求,開始推送binary log給slave(也就是Canal)。
Canal 解析 binary log 對象(原始爲byte流)。
Canal 把解析後的 binary log 以特定格式的進行推送,供下游消費。
說明:
instance模塊:
負責binlog對象總體的發佈訂閱管理器,相似於MQ。
下面咱們來一塊兒看下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 [具體的內容,注意爲文本]
下面咱們經過實際代碼邏輯的判斷,查看 Binlog解析成Canal 對象的數據模型,加深理解
線上服務的穩定性極爲重要,Canal是支持HA的,其實現機制也是依賴Zookeeper來實現的,與HDFS的HA相似。
Canal的HA分爲兩部分,Canal server和Canal client分別有對應的HA實現。
依賴Zookeeper的特性(本文不着重講解zookeeper特性,請在網絡上查找對應資料):
大體步驟:
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。
上面介紹了Canal 的原理與運行機制,下面咱們從實際場景來看,Canal 可以爲咱們業務場景解決什麼樣的問題。
業務在發展初期,爲了快速支撐業務發展,不少數據存儲設計較爲粗放,好比用戶表、訂單表可能都會設計爲單表,此時常規手段會採用分庫分表來解決容量和性能問題。
但數據遷移會面臨最大的問題:線上業務須要正常運行,若是數據在遷移過程當中有變動,如何保證數據一致性是最大的挑戰。
基於Canal,經過訂閱數據庫的 Binlog,能夠很好地解決這一問題。
可詳見下方vivo賬號的不停機遷移實踐。
互聯網業務數據源不只僅爲數據庫,好比 Redis 在互聯網業務較爲經常使用,在數據變動時須要刷新緩存,常規手段是在業務邏輯代碼中手動刷新。
基於Canal,經過訂閱指定表數據的Binlog,能夠異步解耦刷新緩存。
另外一種常見應用場景是「下發任務」,當數據變動時須要通知其餘依賴系統。
其原理是任務系統監聽數據庫變動,而後將變動的數據寫入MQ/Kafka進行任務下發。
好比賬號註銷時下游業務方須要訂單此通知,爲用戶刪除業務數據,或者作數據歸檔等。
基於Canal能夠保證數據下發的精確性,同時業務系統中不會散落着各類下發MQ的代碼,從而實現了下發歸集,以下圖所示:
在大型網站架構中,數據庫都會採用分庫分表來解決容量和性能問題,但分庫分表以後帶來的新問題。
好比不一樣維度的查詢或者聚合查詢,此時就會很是棘手。通常咱們會經過數據異構機制來解決此問題。
所謂的數據異構,那就是將須要join查詢的多表按照某一個維度又聚合在一個DB中。
基於Canal能夠實現數據異構,以下圖示意:
Canal的詳細安裝、配置與使用,請查閱官方文檔 >\> 連接
表數據量大,單表3億多。
常規定時任務遷移全量數據,時間長且對業務有損。
不停機遷移,最大化保證業務不受影響
「給在公路上跑着的車換輪胎」
總體過程大體以下:
單表數據量過大:賬號單表3億+用戶惟一標識過多
業務劃分不合理
使用傳統的定時任務遷移,時長過長,且遷移過程當中爲了保證數據一致性,須要停機維護,對用戶影響較大。肯定使用canal進行遷移,對canal作充分調研與評估,與中間件及DBA共同肯定,可支持全量、以及增量同步。
在vivo海外業務開展初期,海外部分國家的數據存儲在中立國新加坡機房,但隨着海外國家法律合規要求愈來愈嚴格,特別是歐盟地區的GDPR合規要求,vivo賬號應對合規要求,作了比較多的合規改造工做。
部分非歐盟地區的國家合規要求隨之變化,舉例澳洲當地要求知足GDPR合規要求,原有存儲在新加坡機房的澳洲用戶數據須要遷移至歐盟機房,總體遷移複雜度增長,其中涉及到的難點有:
Canal底層使用protobuf做爲數據數據列化的方式,Canal-client在訂閱到變動數據時,爲null的數據會自動轉換爲空字符串,在ORM側數據更新時,因判斷邏輯不一致,致使最終表中數據更新爲空字符串。
賬號本次線上Canal-client只有單節點,但在數據遷移過程當中,因業務特性,致使數據出現了不一致的現象,示例大體以下:
出於數據一致性地考慮(結合賬號業務數據未達到須要分庫的必要性),賬號分表在同一數據庫進行,即遷移過程當中分表數據不斷地進行寫入,加大數據庫負載的同時形成了從庫讀取延時。
解決方案:增長速率控制,基於業務的實際狀況,配置不一樣的策略,例如白天業務量大,能夠適當下降寫入速度,夜間業務量小,能夠適當提高寫入速度。
在總體數據遷移過程當中,vivo賬號在client端增長了實時同步數據的簡易監控手段,即基於業務表基於內存作計數。
總體監控粒度較粗,包括以上數據不一致性,在數據同步完成後,未能發現異常,致使切換至分表模式下出現了業務問題,好在邏輯數據能夠經過補償等其餘手段彌補,且對線上數據影響較小。
以上是基於 Canal現有架構畫出的簡易圖,雖然基於HA總體高可用,但細究後仍是會發現一些隱患,其中標記紅色X的節點,能夠視爲可能出現的故障點。
基於以上可能出現的問題點,咱們能夠嘗試作上圖中的優化。
在互聯網行業,你們對「異地多活」已經耳熟能詳,而數據同步是異地多活的基礎,全部具有數據存儲能力的組件如:數據庫、緩存、MQ等,數據均可以進行同步,造成一個龐大而複雜的數據同步拓撲,相互備份對方的數據,才能作到真正意義上"異地多活」。
本邏輯不在本次討論範圍內,你們能夠參閱如下文章內容,筆者我的認爲講解較爲詳細:http://www.tianshouzhi.com/api/tutorials/canal/404
做者:vivo 產品平臺開發團隊