從最近的mysql故障談海量數據庫的備份系統設計

前言

最近爐石傳說,gitlab數據庫故障在業界傳得沸沸揚揚,造成了無法挽回的數據丟失。對於越是大規模的數據庫系統, 如何設計一個可靠的備份系統越是至關重要。本文主要以UCloud雲數據庫產品UDB的備份系統爲例,闡述下在海量數據庫情況下,備份系統該如何設計,如何確保備份的安全性,如何避免數據庫從刪庫到跑路的窘境。

大型備份系統設計

大型備份系統設計考慮因素

如果一個DBA只需要維護一套數據庫,那麼備份和恢復無疑是較爲簡單的,通常只需要知道怎麼使用備份工具進行備份和還原就搞定了。而在大公司中,數據庫實例數量往往都是成百上千個,公有云服務商甚至需要維護着十萬級別的實例數量,簡單粗糙的備份系統就顯得有些low了,設計一個完善的備份系統尤其關鍵。一個大體量的備份系統需要考慮好這幾個方面:

l  如何根據業務類型選擇備份方式,邏輯備份or物理備份?

l  如何靈活地設置備份策略,比如備份週期選擇,是否在從庫備份,備份上傳到何處

l  如何確認備份是否成功,哪一步驟出了問題

l  如何確認成功的備份實際可有效還原

l  需要恢復時,如何做到一鍵恢復到指定時間點

備份系統設計架構

下面以UCloud UDB爲例,講述備份系統的一般設計架構,來解決上述問題和需求。

UDB備份系統架構設計如下圖所示:


其中Access模塊是業務接入模塊。它處理所有來自API或控制檯的備份相關請求,並將請求轉發到對應的實際物理機去執行備份或者恢復操作;備份機集羣實際存放備份文件,它可能是獨立的物理機集羣,也可能是NFS等其他存儲媒介,甚至是大規模分佈式存儲。在DB物理機上進行的備份完成後,備份系統會通過複雜的負載均衡算法把備份上傳到合適的備份節點上。以保證對應的備份相對均勻地分佈在備份機集羣上。

備份元數據

大型備份系統的核心之一,是”備份元數據”的結構設計。備份系統通過與“備份元數據”所在的業務數據庫交互,來決定備份的各種配置。所謂“備份元數據”,即每個數據庫實例的備份信息,包括該實例的信息,備份的設置策略,備份結果的詳細信息等。通過這個數據庫備份系統將備份元數據和常用的與備份相關的流程串通起來。

通常來說,爲了能夠存儲上述的“備份元數據”,一個海量的備份系統大致需要這樣做表設計:一張表A存放實例的備份配置信息,一張表B存放所有實例的詳細備份記錄。表A和表B通過該數據庫實例的唯一ID從業務上關聯起來。一般這兩張表所要保存的一些信息如下圖所示。


結合備份系統表設計和備份系統架構設計圖,大多數跟備份相關的業務流程就可以更加自動化可配置化。A表使得每一個DB的實例的備份都可以配置,並且也可以通過備份系統的後臺模塊智能分析一批UDB實例的備份策略並記錄。而B表的存在,使得每一個備份的情況都能夠進行精確跟蹤。備份系統後臺可以定期分析B表的記錄,進行後續的處理,比如給用戶告警。

幾個常見的備份恢復流程,都可以通過整套後臺系統和核心元數據的緊密配合來完成:

定時備份和手工備份:Access模塊接收到請求後,通過讀取表A的備份策略,將請求轉發到備份DB所在的物理機去執行,備份完成後通過負載均衡算法上傳遠端的NFS或是備份機集羣

備份失敗檢測:Access模塊讀取表B的備份詳細信息和備份失敗原因,將告警發出,並且經過分析之後,可以動態修改A表該RDS的備份配置。保證RDS的備份成功率

下載備份:Access模塊接受到請求後讀取表B的信息,生成一個可下載的url

基於時間點的恢復:Access模塊接收到請求後,通過讀取表A的記錄獲取該實例的配置信息,生成一個相同配置的可用資源,再將請求轉發到這個可用資源(即恢復DB所在的物理機),在該物理機上新建出實例。接着通過讀取表B的記錄獲取備份信息,讀取表A的信息解析所需時間段的binlog,將備份和binlog導入新實例即完成恢復

通過備份新建一個RDS實例:步驟同上,略去了獲取和導入binlog

通過備份新建一個備庫實例:步驟同上,略去了獲取和導入binlog,改爲指定複製源

備份安全性保障

常規安全性策略

業界有句話:沒有校驗的備份等於沒有備份。我對這句話也是理解深刻,曾經碰到過多次典型的情況比如備份時沒有記錄相應的binlog和pos點導致pointin time恢復時不好找準確的pos點,大大增加了恢復難度;再比如mysqldump邏輯備份時沒有考慮到部分表採用utf8mb4字符集,導致恢復後的數據庫亂碼情況等。以UDB爲例,大型備份系統主要從以下幾個方面確保備份安全性

◎備份失敗監控,一旦備份失敗就會發送告警信息

◎定期抽取歷史備份記錄進行恢復測試

◎備份上傳前後的MD5校驗

◎備份過程中的全局讀鎖檢測,卡住時間太長則發生告警信息

◎備份週期選擇上確保兩次間隔的binlog未過期

◎備份數據冗餘,本地存一份最新的備份,異地存多天的歷史備份

◎備份機集羣空間檢測和負載均衡,確保空間富餘

◎備份重傳和重試

其中,備份的有效性測試方法大概是這樣的:啓幾個對應版本的數據庫並行測試,通過備份詳細記錄表獲取備份後將其傳送到這幾個實例進行恢復測試。由於實例數量較大,不可能每天都做恢復測試,通過讀取上一次校驗時間和校驗結果計算測試優先級。越久沒有做過驗證的備份優先級越高,最近校驗結果爲失敗的次數越多的實例,優先級也越高。

備份過程的全局讀鎖檢測,是因爲備份過程中爲了記錄當前的pos點信息,都會執行一個flush tables with read lock的操作,但是如果當時有長SQL未執行完就會導致全局鎖等待,從而阻塞後續的所有寫請求。爲了使備份不影響業務,在備份開始後定期會檢測全局鎖等待,檢測到以後kill長連接或者kill當前備份線程。

這些備份的常規檢測都會在備份系統後臺定期全自動執行,保證了備份的成功率。

除了上述的考慮,有些特殊情況下光有備份還不夠。假設一個單實例UDB宕機,由於硬件故障物理機無法啓動,物理機恢復時間茫茫無知。這種情況下由於無法獲取最實時的binlog,僅僅通過歷史備份只能恢復到備份時間點,而無法恢復到故障前的時間點。所以僅從安全性角度考慮,必要的備庫都是不可忽略的存在。UDB出於客戶配置靈活,經濟成本的考慮,既支持只創建單實例RDS,也可以創建高可用RDS和跨機房的master-slave RDS,對於重要的業務,一般都建議至少配置有備庫。

智能宕機恢復方法選擇

數據庫宕機有時也會造成數據損壞導致無法正常啓動的情況,以MySQL innodb爲例,一般這時需要做一次force recovery,但是這時的業務恢復時間評估也顯得尤爲重要。UDB可以智能選擇在這種情況下采用何種恢復方式,即:

◎基於重新初始化DB+備份+binlog的恢復

◎force recovery啓動+重新mysqldump+mv損壞數據+重新導入

主要基於以下幾點考慮:

◎原數據量大小評估,數據量越大,重新mysqldump的時間會越長,但同樣的歷史備份傳輸+解壓時間也會越長,需要找到一個平衡點

◎備份時間點到故障時間點的寫入量評估,寫入量越大,使用歷史備份+binlog花的時間也會越長

◎恢復過程中適當提到當前RDS的IOPS上限

總結

有效的備份和恢復策略對於數據庫安全的重要性不言而喻,而海量數據庫的備份系統設計和實現卻不是那麼簡單的一件事,需要考慮的細節還有很多。希望本文對於有意研發海量DB備份系統的童鞋有一些幫助。沒有意向自研的童鞋,不妨考慮將數據庫遷移上雲,讓強大的雲數據庫爲您的數據保駕護航

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章