1. 程式人生 > >MySQL Backup in Facebook • cenalulu's Tech Blog

MySQL Backup in Facebook • cenalulu's Tech Blog

本文將較為詳細的介紹Facebook對於MySQL資料庫的備份策略和方法

準備知識

在進入詳細介紹之前,先簡要介紹一些Facebook相關的架構關鍵字

  • python Facebook幾乎所有的資料庫自動化運維繫統都是通過python實現的,所有可文件化的手工操作都有他對應的Python Library庫來代替。此外,Facebook內部各個基礎服務之間使用thrift作為通訊API的定義。為了很快速的開發基於thrift通訊的python service,Facebook內部使用叫做BaseController的框架,同時github上也有其對應的開源版本sparts

    。本文將提到的backup-agent也基於它實現。

  • 部署方式 Master/Slave的部署方式,並且所有資料在5個機房中都在其中的2個或兩個以上存在副本,本文把整個叢集在後文用Recpliaset表示。(5個機房分部見下圖)

  • 資料備份的要素 任何資料備份都離不開這幾個要素:備份儲存形式,備份儲存地,備份策略,備份有效性檢驗,備份來源。後文也會用這樣的劃分方式,對每一個要素用一個小節來具體介紹。

map_mk

備份形式

Facebook的MySQL備份形式可能會讓你感到有些許驚訝。我們所有的Production MySQL資料都使用mysqldump進行邏輯備份。你一定和我最早聽到這個事實的時候一樣疑惑:那為什麼不選擇更為備份速度更快的基於xtrabackup的物理備份呢?主要有以下幾點原因:

  • 壓縮率:這個是最根本的因素。在Facebook由於資料基數巨大。1%的儲存空間節省,往往等同於省下了幾十萬美元的經費。由於物理備份中索引的存在,邏輯備份使用gzip後的壓縮率仍然明顯優於物理備份。儘管我們已經大規模的使用了Innodb Compress的功能,同樣的資料庫邏輯備份壓縮後的大小,大約是物理備份的二分之一到三分之一左右。
  • 內部服務依賴:我們的MySQL資料備份的作用並不僅僅是為了做災難恢復。他也是資料倉庫的非實時分析的基礎資料來源。任何一個實驗性的調研,都是以邏輯備份作為基礎資料來初始化到臨時資料倉庫中的。而如果使用物理備份,顯然要花更多得精力和人力在備份的Parse部分上。
  • 其他因素:例如備份資料損壞的Debug,外部工具的開發成本等等方面,邏輯備份都因為其直接可讀的檔案形式都佔據了一定的優勢。

logic_vs_phy 當然,這個備份策略並不是絕對最優的,或者說對於所有公司和架構都是普遍適用的。例如,也可以使用xtrabackup的Partial Backups來減小物理備份的體積,以達到和邏輯備份幾乎相似的壓縮率。而對於資料倉庫dump需求,也完全可以通過對物理備份恢復後,再實時匯出。在驗證了備份有效性的同時也滿足的業務需求。當然我們也不是完全不用xtrabackup,在Shard Migration和Instance Migration的時候我們還是會依賴基於物理備份的Rebuild來提升整個遷移速度的。

總而言之:在保證備份可用性的前提下,備份形式會更多的根據公司內部架構和資源來做靈活的調整。

備份儲存地

所有上市公司對於備份的存放地都有來自於審計的要求,當然除此之外我們的設計也還要能經受住每年一次的災難性演練的考驗。目前我們的備份主要有以下兩個存放地。

  • Warm Backup 每個Datacenter中都有一個獨立的HDFS叢集專門負責存放備份資料,存放最近10天的備份檔案(一個邏輯Shard的備份只會儲存在一個HDFS中)
  • Cold Backup 部分Datacenter中有Isilon裝置上,所有超過10天的備份檔案按策略轉移到冷儲存上

99%的備份恢復需求都能從HDFS上得到滿足,這點也比較可以理解。因為大部分使用者的需求都是恢復到最近一週內某一天的某個時間點,或者恢復到某個誤操作以前的狀態。冷備份的存在更多的是用於應對HDFS邏輯故障以及來自於審計壓力的歷史歸檔需要。

備份源的選擇

之前也提到,由於多個Datacenter的存在,一個Replicaset中就會有多個Instance可以作為備份源的選擇。所以,我們在對於從哪個節點進行備份的策略上也進行了一定的優化。首先,我們用類似於一致性hash的方法把ShardName對映到一個bucket中,每個HDFS叢集都會負責多個bucket的儲存。當backup-agent發現當前有一個備份需求時,它會先通過hash決定目標HDFS實體地址,然後通過以下因素決定,應該從哪個MySQL節點,作為備份源進行備份。

  • 網路流量
  • broekn slave
  • 一致性

備份策略

備份策略按照資料特點的不同,我們應用不同的備份策略。對於變更熱點集中,增量資料多的使用者資料,我們採用每隔三天做一次全量備份,期間進行增量備份的策略。對於資料變化量大,或者無法預估change pattern的資料,我們採用每天全量備份的策略。在每一臺MySQL Server上,都會有一個Python實現的Backup agent負責每天備份的排程。它的主要職責就是根據配置中心的配置,具體併發起備份。同時決定的備份併發數量,不同例項上備份的優先順序,備份失敗的重試等等。

全量備份

如同上文已經提到的,我們的全量備份使用mysqldump + qpress + HDFS client的管道方式,按照Shard為單位進行備份。所謂Shard對應於MySQL中得一個邏輯資料庫。Shard和Shard之間可能存在併發。根據伺服器硬體配置的不同,我們也有不同的併發策略。例如Flash card上我們可以支援同時執行2-3個mysqldump進行。此外,為了邏輯備份能夠更快,並且對Server正常服務影響程度最小的方式執行,我們還使用了Logical Read Ahead的策略,並在mysqldump中添加了相應的option。具體實現和效果可以參見Yoshinori的這篇博文

增量備份

增量備份的方法,同樣也是我們比較特殊的一個部分。相較於傳統的基於Binlog的備份不同,我們的增量備份是基於全量資料的。由於全量備份是以Shard為單位存在的,一個MySQL例項上會有多個Shard,而如果我們以Binlog作為增量備份,就意味著各個Shard的增量備份存在於同一組Binlog中得不同位置。這樣也就造成了不同邏輯備份之間的相互依賴,增加了備份的不確定性。假設我們在額外做一個Binlog解析按照Shard來切分的系統的話,那複雜度和不確定很顯然會大大增加。此外,由於前面提到的熱點資料集中,反覆修改多得特點,Binlog中對於同一Object Row或者說同一Primary Key的DML重複度非常高。這樣直接備份Binlog會有大量的儲存空間浪費。所以,我們開發了一套只備份差異資料的特殊增量備份系統,也先後經歷了兩個大版本的演變。

版本一: 純依賴於Hadoop的解決方案,第一版我們把這個問題簡化成了HDFS的問題,或者說對MySQL端透明的方案。由於之前的Binlog是MIX級別的,因此沒有辦法只分析Binlog來合併生成增量備份。每天都往HDFS裡寫入一份全量備份,然後由Hadoop Job來對兩個全備做差異比較並生成差異檔案,並把較新的全量備份檔案刪除。這個方法的弊端也比較明顯:HDFS的讀寫壓力大,且浪費資源。每天要寫入一份只用來作為比較的全量備份(並刪除)。最終上線後發現,受制於HDFS的寫入吞吐,已經硬體頻寬限制,整個增量備份系統無法在一天內完成所有Shard的備份。

版本二: 第二版,我們仍然保持了原有系統的簡單程度(對MySQL來說只有jave客戶端,沒有額外計算),同時又免去了每天都把全量備份寫入HDFS冗餘操作,取而代之的是通過流的方式實時生成差異檔案。全量資料仍然從MySQL端讀取,不同的是到了HDFS後,動態的讀取最近一次的全量備份在記憶體中作比較,並做增量檔案寫入。這個版本也最終成為了我們現在Production上穩定執行一年多的版本。當然,這個方案也是有缺陷的。首先,引入額外的差異比較步驟,已經違背了減少系統複雜度的初衷。同時,每天都從MySQL讀取一次全量資料也是對系統資源和網路資源一種不小的損耗。隨著RBR的大面積應用,當獲取全量Binlog的可靠度越來越高的前提下,我們可以基於Binlog作出一套更好的增量備份系統(詳見下文展望部分)

備份驗證

沒有進行驗證的備份是無效的。業界之前也有很多血的教訓。例如下廚房的資料恢復,如果備份始終有效,就沒有之後更多的故事不是麼?所以在Facebook內部,所有的備份(全量/增量)都有一整套恢復驗證策略和驗證系統來負責備份的有效性。由於篇幅關係,這裡我們只簡單介紹下概況,在後續文章中博主會用單獨一篇博文詳細介紹。 驗證系統的主要執行機制是不間斷的從熱備份儲存(HDFS)上根據metadata獲取恢復優先順序最高的備份,並且恢復到空閒機器上加以驗證。越久沒有做過驗證的備份優先順序越高;驗證失敗次數越多的Schema,優先順序越高。如果對於一個邏輯分片(Shard),有連續超過3個備份驗證失敗,那麼我們的alarm dashboard上就會出現相應的警告。驗證的主要步驟包括:下載,解壓,Load,驗證,Binlog Replay等步驟,任何一個步驟的失敗都會判定為備份無效。由於我們的PIT(point in time recovery)和驗證系統使用的是完全相同的恢復程式碼,也就意味著,只要通過有效驗證的備份就一定能夠成功的恢復到任何一個歷史上的時間點。 除了HDFS上備份的儲存,由於歷史資料歸檔和應對災難性情況的需要,我們也會對冷備份上的備份做驗證。這個驗證相對就比較簡單,由於之前備份在熱儲存上已經被驗證過,所以我們只通過簡單的備份檔案checksum比對即可確定冷備份的完整性。

現有問題和未來展望

由於篇幅關係,這裡就不多贅述在整個備份系統演變過程中所遇到的那些趣事了。有興趣的讀者可以翻出來,在Youtube上看看我們關於MySQL備份系統的一次分享。 隨著RBR在Production的逐步啟用,我們可以大膽展望一種新的備份方式。基於RBR的邏輯增量備份。根據網際網路使用者的行為屬性和2/8原則,我們不難假定活躍使用者可能只佔到20%的總使用者數量。相應的資料庫上每天使用者資料的所有變更中,可能80%的變更都是由20%的重度活躍使用者貢獻的。我們用下圖來舉例子:一個100GB的資料庫,每天的RBR形式的Binlog就只有20GB;而這20G的增量日誌中又有80%的資料是重複使用者的變更,所以實際上只有4G的資料是Replay到最終態所需要使用的有效增量資料。也就意味著對於一個100G的資料庫,我們每天需要備份的raw資料只有4G,再加上文字壓縮,可能最終的物理大小隻有500MB。這無疑又會為公司節省幾百萬美金,當然也是我們接下來的工作重點之一!Weeeee~ RBR backup

Ref: