The Log

在LinkedIn分布式化中過程中,我學(xué)到最有用的東西,是我們構(gòu)建的很多系統(tǒng),在背后都有一個非常簡單的思想,日志。有時日志也叫做WAL(Write Ahead Logs)或者提交日志或者事務(wù)日志。日志其實已經(jīng)存在很久了,幾乎和計算機存在的時間一樣長,很多分布式數(shù)據(jù)系統(tǒng)和實時應(yīng)用架構(gòu)的核心就是日志。

如果你不了解日志,你就肯定不能徹底理解數(shù)據(jù)庫,NoSQL存儲,kv存儲,復(fù)制,paxos協(xié)議,hadoop,版本控制,甚至其他任何軟件系統(tǒng)。即使這樣,現(xiàn)在中大多數(shù)軟件工程師對日志并不熟悉。我希望改變這種現(xiàn)狀,在這篇文章中,我會帶著你了解有關(guān)日志的一切,包括日志是什么,怎樣使用日志做數(shù)據(jù)集成,實時數(shù)據(jù)處理和系統(tǒng)架構(gòu)。

第一部分,日志是什么?

日志可能是最簡單的存儲抽象。日志是一種只能在尾部添加,完全順序的,按照時間排序的一組記錄。日志長得像這樣:

Log

記錄被添加到日志尾部,并從左到右讀取。日志中的每一條記錄都包含一個唯一的日志序列號。

日志記錄的順序定義了一個時間的概念,因為在我們的定義中,右邊的記錄要比左邊的記錄“大”。這種情況下,日志序列號就可以被當(dāng)做每條記錄的時間戳。把順序定義為時間的概念一開始看起來有點奇怪,但是這其實是一個很有用的屬性,因為這樣一來系統(tǒng)的時間就不依賴任何物理時鐘了。當(dāng)我們說到分布式系統(tǒng)時,這會是一個非常有用的屬性。

在我們現(xiàn)在的討論當(dāng)中,日志的內(nèi)容和格式并不重要,同時,我們也不能一直追加日志,因為存儲空間遲早會耗盡。

所以,日志和文件或者數(shù)據(jù)庫表并沒有本質(zhì)的不同。文件是一個字節(jié)數(shù)組,數(shù)據(jù)庫表是一個記錄數(shù)組,日志其實就像一張數(shù)據(jù)庫表或者一個文件,只是日志里的記錄按照時間順序排序過。

說到現(xiàn)在,你可能奇怪,為什么要說這么簡單的東西?一個只能在尾部追加的記錄序列到底和數(shù)據(jù)系統(tǒng)有什么關(guān)系?答案是,日志記錄了發(fā)生的事情以及發(fā)生的時間。在很大程度上來說,這其實就是分布式系統(tǒng)要處理的核心問題。

在進一步闡釋之前,我要先解釋清楚一個疑惑。每個程序員都對另一種日志特別熟悉 - 非結(jié)構(gòu)化的錯誤日志或者應(yīng)用程序的trace信息。我把這些日志稱為“應(yīng)用日志”。應(yīng)用日志其實我們這里討論的日志的一種降級形式。他們最大的區(qū)別是,應(yīng)用日志是用肉眼去讀并理解的,而數(shù)據(jù)日志是用程序來處理的。

數(shù)據(jù)庫中的日志

我其實并不知道日志這個概念是誰發(fā)明的,也有可能是這個概念像二分查找一樣,太簡單,連發(fā)明者都沒有意識到他發(fā)明了一個東西。日志最早在IBM的System R中出現(xiàn)。在數(shù)據(jù)庫中,日志是作用是在崩潰情況下也能保持不同種類的數(shù)據(jù)結(jié)構(gòu)及索引的同步。為了實現(xiàn)原子性和持久性,在把修改真正應(yīng)用到數(shù)據(jù)之前,數(shù)據(jù)庫使用日志來保存對數(shù)據(jù)的修改。日志是真正發(fā)生的事情的記錄,數(shù)據(jù)庫表和索引只是把發(fā)生過的事情映射到某種有用的數(shù)據(jù)結(jié)構(gòu)之中。由于日志是立即持久化的,在系統(tǒng)崩潰的時候會用日志來恢復(fù)其他的持久性數(shù)據(jù)結(jié)構(gòu)。

隨著時間推移,日志的使用已經(jīng)從最初的數(shù)據(jù)庫ACID性質(zhì)實現(xiàn),發(fā)展到數(shù)據(jù)庫之間復(fù)制數(shù)據(jù)的方法。事實證明,這一連串對數(shù)據(jù)修改的記錄,恰恰就是和遠程數(shù)據(jù)庫保持同步的關(guān)鍵。Oracle,MySQL和PostgreSQL都包含日志傳輸協(xié)議,用來在從數(shù)據(jù)庫上復(fù)制數(shù)據(jù)。Oracle已經(jīng)把他們的Xstreams和GoldenGate產(chǎn)品化,MySQL和PostgreSQL也有相似的關(guān)鍵技術(shù)。

正因為如此,機器可讀的日志概念,僅僅被限制在數(shù)據(jù)庫的范疇之內(nèi)。使用日志作為數(shù)據(jù)訂閱的機制好像只是因為意外而產(chǎn)生的。但是這種抽象對于支持消息,數(shù)據(jù)流動和實時數(shù)據(jù)處理來說非常完美。

在分布式系統(tǒng)中的日志

日志解決的兩個問題是,數(shù)據(jù)變化順序和數(shù)據(jù)分布,在分布式環(huán)境中顯得更加重要。在數(shù)據(jù)的更新上達成一致是分布式系統(tǒng)設(shè)計時需要考慮的核心問題。

以日志為核心的分布式系統(tǒng),是從一個簡單的觀察結(jié)果而來,這里我們把它叫做狀態(tài)機復(fù)制原則:

如果兩個相同的確定性系統(tǒng),從一個相同的狀態(tài)開始,且以相同的順序獲得相同的輸入,兩個系統(tǒng)會產(chǎn)生相同的輸出,并且以相同的狀態(tài)結(jié)束運行。

這個描述可能聽起來有點不清楚,我來解釋一下。

確定性系統(tǒng)的意思是,數(shù)據(jù)的處理并不依賴時間, 也不會因為其他未知輸入影響輸出。舉例來說,如果一個程序的輸出會被線程執(zhí)行的順序影響,或者被gettimeofday這個函數(shù)調(diào)用影響,或者被某些不可重復(fù)發(fā)生的事情影響,這個程序就不具有確定性。

程序的狀態(tài)就是程序運行結(jié)束后機器上存儲的數(shù)據(jù),不管是在內(nèi)存里還是在磁盤上。

程序以相同順序獲得相同輸入這點可能會給我們一個暗示,這里和日志有關(guān)。這其實是一個非常直覺可以理解的概念,如果給兩個確定性程序相同的輸入日志,這兩個程序會產(chǎn)生相同的輸出。

把日志的概念應(yīng)用到分布式系統(tǒng)上的方式就很明顯了。在分布式環(huán)境下的所有機器做同一件事的問題,可以簡化為,實現(xiàn)一個分布式一致性日志系統(tǒng),把日志作為這些程序的輸入就好了。日志在這里的作用是,排除一切非確定性的輸入,確保所有副本同步處理輸入。

這個方式的美妙之處在于,以前作為索引的日志時間戳,現(xiàn)在也可作為副本的狀態(tài)時鐘。你可以用最大處理日志序列號這個數(shù)字來描述一個副本。這個時間戳和日志結(jié)合起來,描述了副本的整個狀態(tài)。

有非常多的方式可以把這個原理應(yīng)用到依賴日志輸入的系統(tǒng)。理論上,我們甚至可以用日志記錄每一條副本需要執(zhí)行的指令或者副本需要執(zhí)行的方法名和參數(shù)。只要兩個程序用相同的方式處理這些輸入,這兩個程序的數(shù)據(jù)會始終保持一致。

不領(lǐng)域的人會用不同方式來描述日志。比如數(shù)據(jù)庫工作者會區(qū)分物理日志和邏輯日志。物理日志是記錄了每一行記錄改變的內(nèi)容。邏輯日志記錄了改變數(shù)據(jù)的SQL,比如insert/update/delete。

書本上通常會描述兩種數(shù)據(jù)處理和復(fù)制的方式。狀態(tài)機模型,通常指的是為每一個請求記錄日志,并且每一個副本逐一處理每一條請求。另一個模型主-備模型稍微有點不同,在這個模型下,系統(tǒng)會選舉一個副本作為leader,leader會執(zhí)行請求并記錄數(shù)據(jù)修改內(nèi)容,其他備份會把數(shù)據(jù)修改通過日志同步到本地。

Two Models

為了理解這兩種方法的區(qū)別,我們來看一個玩具問題。假設(shè)有一個“算法服務(wù)”,它維護了一個數(shù)字作為它的狀態(tài),并且初始化為零,后續(xù)這個服務(wù)對這個數(shù)字進行加法和乘法計算。主-主的模型可能會記錄數(shù)字的變化,比如“+1”或者“+2”。每個副本會經(jīng)歷相同順序的數(shù)字變化。主-備模型會有一個主服務(wù)來執(zhí)行計算,并且日志記錄結(jié)果,比如“1”,“3”,“6”。這個簡單的例子也說明為什么順序?qū)τ跀?shù)據(jù)的一致性至關(guān)重要,因為對加法和乘法的重排序會產(chǎn)生不同的計算結(jié)果。


Paxos

分布式日志也可以被當(dāng)做一致性協(xié)議的數(shù)據(jù)模型。畢竟,日志就是為數(shù)據(jù)下一個變化的值做的決定。你可以看一個paxos算法中的日志是什么樣子的,及時paxos算法也被用來創(chuàng)建日志。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容