做者介紹:呂磊,Better 隊成員、美團點評高級 DBA,Better 隊參加了 TiDB Hackathon 2019,其項目「基於 TiDB Binlog 的 Fast-PITR」得到了最佳貢獻獎。
維護過數據庫的同窗應該都能體會,數據備份對於數據庫來講能夠說相當重要,尤爲是關鍵業務。TiDB 原生的備份恢復方案已經在多家客戶獲得穩定運行的驗證,可是對於業務量巨大的系統存在以下幾個痛點:git
<center>圖 1 原生 binlog 備份恢復</center>github
咱們在線上使用 TiDB 已經超過 2 年,從 1.0 RC 版本到 1.0 正式版、2.0、2.1 以及如今的 3.0,咱們能感覺到 TiDB 的飛速進步和性能提高,但備份恢復的這些痛點,是咱們 TiDB 在關鍵業務中推廣的一個掣肘因素。因而,咱們選擇了這個題目: 基於 TiDB Binlog 的 Fast-PITR (Fast point in time recovery),即基於 TiDB Binlog 的快速時間點恢復,實現了基於 TiDB Binlog 的逐級 merge,以最小的代價實現快速 PITR,解決了現有 TiDB 原生備份恢復方案的一些痛點問題。數據庫
<center>圖 2 binlog merge 原則</center>併發
咱們將 binlog 按照時間分段,舉例說,天天的 binlog 爲一個分段,每段按照上面的原則進行 merge,這段 binlog 合併後成爲一個備份集,備份集是一些獨立的文件。因爲每個備份集在 merge 階段已經去掉了衝突,因此一方面對體積進行了壓縮,另外一方面能夠以行級併發回放,提升回放速度,結合 full backup 快速恢復到目標時間點,完成 PITR 功能。並且,這種合併的另外一個好處是,生成的備份集與原生 binlog file 能夠造成互備關係,備份集可以經過原生 binlog file 重複生成。app
<center>圖 3 binlog 並行回放</center>工具
binlog 分段方式能夠靈活定義起點和終點:性能
-start-datetime string recovery from start-datetime, empty string means starting from the beginning of the first file -start-tso int similar to start-datetime but in pd-server tso format -stop-datetime string recovery end in stop-datetime, empty string means never end. -stop-tso int similar to stop-datetime, but in pd-server tso format
<center>圖 4 優化後</center>測試
備份集的格式與 TiDB Binlog 相同,因此,備份集之間能夠根據須要再次合併,造成新的備份集,加速整個恢復流程。優化
因爲須要將同一 key(主鍵或者惟一索引鍵)的全部變動合併到一條 Event 中,須要在內存中維護這個 key 所在行的最新合併數據。若是 binlog 中包含大量不一樣的 key 的變動,則會佔用大量的內存。所以設計了 Map-Reduce 模型來對 binlog 數據進行處理:spa
<center>圖 5 binlog 合併方式</center>
| 原 Event 類型 | 新 Event 類型 | 合併後的 Event 類型 |
| ---- | ---- |---- |
| INSERT | DELETE | Nil |
| INSERT | UPDATE |INSERT |
| UPDATE | DELETE | DELETE |
| UPDATE | UPDATE | UPDATE |
| DELETE | INSERT | UPDATE |
Drainer 輸出的 binlog 文件中只包含了各個列的數據,缺少必要的表結構信息(PK/UK),所以須要獲取初始的表結構信息,而且在處理到 DDL binlog 數據時更新表結構信息。DDL 的處理主要實如今 DDL Handle 結構中:
<center>圖 6 DDL 處理</center>
首先經過配置 TiDB 的 Restful API 獲取 TiKV 中保存的歷史 DDL 信息,經過這些歷史 DDL 獲取 binlog 處理時的初始表結構信息,而後在處理到 DDL binlog 時更新表結構信息。
因爲 DDL 的種類比較多,且語法比較複雜,沒法在短期內完成一個完善的 DDL 處理模塊,所以使用 tidb-lite 將 mocktikv 模式的 TiDB 內置到程序中,將 DDL 執行到該 TiDB,再從新獲取表結構信息。
Hackathon 比賽時間只有兩天,時間緊任務重,咱們實現了上面的功能外,還有一些沒來得及實現的功能。
<center>圖 7 方案展望</center>
增量備份集,邏輯上是一些 insert+update+delete 語句。
全量備份集,是由 mydumper 生成的 create schema+insert 語句。
咱們能夠將增量備份中的 insert 語句前置到全量備份集中,全量備份集配合 Lightning 工具 急速導入到下游 TiKV 集羣,Lightning 恢復速度是邏輯恢復的 5 - 10 倍 ,再加上一份更輕量的增量備份集 (update+delete) 直接實現 PITR 功能。
PIRT 工具其實是一個 binlog 的 merge 過程,處理一段 binlog 期間,爲了保證數據的一致性,理論上若是遇到 DDL 變動,merge 過程就要主動斷掉,生成備份集,再從這個斷點繼續 merge 工做,所以會生成兩個備份集,影響 binlog 的壓縮率。
爲了加速恢復速度,咱們能夠將 DDL 作一些預處理,好比發現一段 binlog 中包含某個表的 Drop table 操做,那麼徹底能夠將 Drop table 前置,在程序一開始就忽略掉這個表的 binlog 不作處理,經過這些「前置」或「後置」的預處理,來提升備份和恢復的效率。
<center>圖 8 DDL 預處理</center>
咱們是在坤坤(李坤)的熱心撮合下組建了 Better 戰隊,成員包括黃瀟、高海濤、我,以及 PingCAP 的王相同窗。感謝幾位大佬不離不棄帶我飛,最終拿到了最佳貢獻獎。比勝過程驚險刺激(差點翻車),比賽快結束的時候才調通代碼,強烈建議之後參加 Hackathon 的同窗們必定要抓緊時間,儘早完成做品。參賽的短短兩天讓咱們學到不少,收穫不少,見到很是多優秀的選手和炫酷的做品,咱們還有很長的路要走,但願這個項目能繼續維護下去,期待明年的 Hackathon 能見到更多優秀的團隊和做品。
原文閱讀:https://pingcap.com/blog-cn/fast-pitr-based-on-binlog/