分布式系统原理 之5 日志技术
分布式系統原理
日志技術
日志技術是宕機恢復的主要技術之一[3]。日志技術最初使用在數據庫系統中。嚴格來說日志技術不是一種分布式系統的技術,但在分布式系統的實踐中,卻廣泛使用了日志技術做宕機恢復,甚至如 BigTable 等系統將日志保存到一個分布式系統中進一步增強了系統容錯能力。
本章首先簡單介紹數據庫系統中的日志技術,進而抽象簡化問題模型,在簡化模型的基礎上介紹兩種實用的日志技術 Redo Log 與 No Redo/No undo Log。
1. 數據庫系統日志技術簡述
在數據庫系統中實現宕機恢復,其難點在于數據庫操作需要滿足 ACID,尤其在支持事務(transaction)的數據庫系統中宕機往往發生在某些事務只執行了部分操作的時候。此時宕機恢復的主要目標就是數據庫系統恢復到一個穩定可靠狀態,消除未完成的事務對數據庫狀態的影響。
數據庫的日志主要分為 Undo Log、Redo Log、Redo/Undo Log 與 No Redo/No Undo Log。這四類日志的區別在更新日志文件和數據文件的時間點要求不同,從而造成性能和效率也不相同。本文不就數據庫中的這四類日志技術做深入討論,相關信息可以參考有關數據庫系統方面的資料。
2. Redo Log 與 Check point
2.1 問題模型
首先簡化原數據庫系統中的問題模型為一個較為簡單的模型:假設需要設計一個高速的單機查詢系統,將數據全部存放在內存中以實現高速的數據查詢,每次更新操作更新一小部分數據(例如key-value 中的某一個 key)。現在問題為利用日志技術實現該內存查詢系統的宕機恢復。與數據庫的事務不同的是,這個問題模型中的每個成功的更新操作都會生效。這也等效為數據庫的每個事務只有一個更新操作,且每次更新操作都可以也必須立即提交(Auto commit)。
2.2 Redo Log
Redo Log 是一種非常簡單實用的日志技術。在上節的問題模型中,只需按如下流程更新既可以實用 Redo Log。
流程 2.5.1:Redo Log 更新流程 1. 將更新操作的結果(例如 Set K1=1,則記錄 K1=1)以追加寫(append)的方式寫入磁盤的日志文件 2. 按更新操作修改內存中的數據 3. 返回更新成功上述更新流程中第 2 步沒有考慮修改內存數據需要多線程互斥等問題,但對于說明 Redo Log的原理沒有影響。
從Redo Log的流程可以看出,Redo寫入日志的是更新操作完成后的結果(雖然本文不討論UndoLog,這點是與 Undo Log的區別之一),且由于是順序追加寫日志文件,在磁盤等對順序寫有力的存儲設備上效率較高。
用 Redo Log 進行宕機恢復非常簡單,只需要“回放”日志即可。
流程 2.5.2:Redo Log 的宕機恢復 1. 從頭讀取日志文件中的每次更新操作的結果,用這些結果修改內存中的數據。從 Redo Log 的宕機恢復流程也可以看出,只有寫入日志文件的更新結果才能在宕機后恢復。這也是為什么在 Redo Log 流程中需要先更新日志文件再更新內存中的數據的原因。假如先更新內存中的數據,那么用戶立刻就能讀到更新后的數據,一旦在完成內存修改與寫入日志之間發生宕機,那么最后一次更新操作無法恢復,但之前用戶可能已經讀取到了更新后的數據,從而引起不一致的問題。
2.3 Check point
宕機恢復流量的缺點是需要回放所有 redo 日志,效率較低,假如需要恢復的操作非常多,那么這個宕機恢復過程將非常漫長。解決這一問題的方法即引入 check point 技術。在簡化的模型下,checkpoint 技術的過程即將內存中的數據以某種易于重新加載的數據組織方式完整的 dump 到磁盤,從而減少宕機恢復時需要回放的日志數據。
流程 2.5.3:check point 1. 向日志文件中記錄“Begin Check Point” 2. 將內存中的數據以某種易于重新加載的數據組織方式 dump 到磁盤上 3. 向日志文件中記錄“End Check Point”在 check point 流程中,數據可以繼續按照流程 2.5.1 被更新,這段過程中新更新的數據可以 dump到磁盤也可以不 dump 到磁盤,具體取決于實現。例如,check point 開始時 k1=v1,check point 過程中某次更新為 k1 = v2,那么 dump 到磁盤上的 k1 的值可以是 v1 也可以是 v2。
流程 2.5.4:基于 check point 的宕機恢復流程 1. 將 dump 到磁盤的數據加載到內存。 2. 從后向前掃描日志文件,尋找最后一個“End Check Point”日志。 3. 從最后一個“End Check Point”日志向前找到最近的一個“Begin Check Point”日志,并回放該日志之后的所有更新操作日志。3. No Undo/No Redo log
本節介紹另一種特殊的日志技術“No Undo/No Redo log”,這種技術也稱之為“0/1 目錄”(0/1directory)。
本節介紹這種技術并不再使用上節的問題場景,而假設另一種問題場景:若數據維護在磁盤中,某批更新由若干個更新操作組成,這些更新操作需要原子生效,即要么同時生效,要么都不生效。
0/1 目錄技術中有兩個目錄結構,稱為目錄 0(Directory 0)和目錄 1(Directory 1)。另有一個結構稱為主記錄(Master record)記錄當前正在使用的目錄稱為活動目錄。主記錄中要么記錄使用目錄 0,要么記錄使用目錄 1。目錄 0 或目錄 1 中記錄了各個數據的在日志文件中的位置。
0/1 目錄的數據更新過程始終在非活動目錄上進行,只是在數據生效前,將主記錄中的 0、1 值反轉,從而切換主記錄。
流程 2.5.5:0/1 目錄數據更新流程 1. 將活動目錄完整拷貝到非活動目錄。 2. 對于每個更新操作,新建一個日志項紀錄操作后的值,并在非活動目錄中將相應數據的位置 修改為新建的日志項的位置。 3. 原子性修改主記錄:反轉主記錄中的值,使得非活動目錄生效。0/1 目錄的更新流程非常簡單,通過 0、1 目錄的主記錄切換使得一批修改的生效是原子的。
0/1 目錄將批量事務操作的原子性通過目錄手段歸結到主記錄的原子切換。由于多條記錄的原子修改一般較難實現而單條記錄的原子修改往往可以實現,從而降低了問題實現的難度。在工程中0/1 目錄的思想運用非常廣泛,其形式也不局限在上述流程中,可以是內存中的兩個數據結構來回切換,也可以是磁盤上的兩個文件目錄來回生效切換。
4. 工程投影
日志技術的使用非常廣泛,在 zookeeper 系統中,為了實現高效的數據訪問,數據完全保存在內存中,但更新操作的日志不斷持久化到磁盤,另一方面,為了實現較快速度的宕機恢復,zookeeper周期性的將內存數據以 checkpoint 的方式 dump 到磁盤。
MySQL 的主從庫設計也是基于日志。從庫只需通過回放主庫的日志,就可以實現與主庫的同步。由于從庫同步的速度與主庫更新的速度沒有強約束,這種方式只能實現最終一致性。
Mola與 Armor系統支持多種不同的存儲引擎,對于接受到的更新操作,這兩個系統將操作日志(redo log)保存到磁盤,引擎可以通過回放日志實現副本數據的同步。在 mola中,由于不需要強一致性,日志與數據分離,且日志也保存多個副本,當日志副本更新滿足 quorum 要求后就返回用戶更新成功。引擎通過回放日志的方式實現數據更新,由于回放速度不一致,mola 提供最終一致性保證。同時,由于返回用戶更新成功時只保證日志更新成功,此時讀取引擎數據未必可以讀到最新更新的數據。Armor*中更新了這一設計,日志與數據不分離,更新日志的同時也更新引擎數據,從而可以立刻讀取到成功更新的數據。
參考:《分布式系統原理介紹》 - 劉杰
總結
以上是生活随笔為你收集整理的分布式系统原理 之5 日志技术的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 分布式系统原理 之4 Quorum 机制
 - 下一篇: 分布式系统原理 之6 两阶段提交协议