我在六年前的一個(gè)令人興奮的時(shí)刻加入到LinkedIn公司。從那個(gè)時(shí)候開始我們就破解單一的、集中式數(shù)據(jù)庫(kù)的限制,并且啟動(dòng)到特殊的分布式系統(tǒng)套件的轉(zhuǎn)換。這是一件令人興奮的事情:我們構(gòu)建、部署,而且直到今天仍然在運(yùn)行的分布式圖形數(shù)據(jù)庫(kù)、分布式搜索后端、Hadoop安裝以及第一代和第二代鍵值數(shù)據(jù)存儲(chǔ)。
從這一切里我們體會(huì)到的最有益的事情是我們構(gòu)建的許多東西的核心里都包含一個(gè)簡(jiǎn)單的理念:日志。有時(shí)候也稱作預(yù)先寫入日志或者提交日志或者事務(wù)日志,日志幾乎在計(jì)算機(jī)產(chǎn)生的時(shí)候就存在,同時(shí)它還是許多分布式數(shù)據(jù)系統(tǒng)和實(shí)時(shí)應(yīng)用結(jié)構(gòu)的核心。
不懂得日志,你就不可能完全懂得數(shù)據(jù)庫(kù),NoSQL存儲(chǔ),鍵值存儲(chǔ),復(fù)制,paxos,Hadoop,版本控制以及幾乎所有的軟件系統(tǒng);然而大多數(shù)軟件工程師對(duì)它們不是很熟悉。我愿意改變這種現(xiàn)狀。在這篇博客文章里,我將帶你瀏覽你必須了解的有關(guān)日志的所有的東西,包括日志是什么,如何在數(shù)據(jù)集成、實(shí)時(shí)處理和系統(tǒng)構(gòu)建中使用日志等。
第一部分:日志是什么?
日志是一種簡(jiǎn)單的不能再簡(jiǎn)單的存儲(chǔ)抽象。它是一個(gè)只能增加的,完全按照時(shí)間排序的一系列記錄。日志看起來如下:
我們可以給日志的末尾添加記錄,并且可以從左到右讀取日志記錄。每一條記錄都指定了一個(gè)唯一的有一定順序的日志記錄編號(hào)。
日志記錄的排序是由“時(shí)間”來確定的,這是因?yàn)槲挥谧筮叺娜罩居涗洷任挥谟疫叺囊缧?。日志記錄編?hào)可以看作是這條日志 記錄的“時(shí)間戳”。在一開始就把這種排序說成是按時(shí)間排序顯得有點(diǎn)多余 ,不過 ,與任何一個(gè)具體的物理時(shí)鐘相比,時(shí)間 屬性是非常便于使用的屬性。在我們運(yùn)行多個(gè)分布式系統(tǒng)的時(shí)候,這個(gè)屬性就顯得非常重要。
對(duì)于這篇討論的目標(biāo)而言,日志記錄的內(nèi)容和格式不怎么重要。另外提醒一下,在完全耗盡存儲(chǔ)空間的情況下,我們不可能 再給日志添加記錄。稍后我們將會(huì)提到這個(gè)問題。
日志并不是完全不同于文件或者數(shù)據(jù)表的。文件是由一系列字節(jié)組成,表是由一系列記錄組成,而日志實(shí)際上只是按照時(shí)間順序存儲(chǔ)記錄的 一種數(shù)據(jù)表或者文件。
此時(shí),你可能奇怪為什么要討論這么簡(jiǎn)單的事情呢? 不同環(huán)境下的一個(gè)只可增加的有一定順序的日志記錄是怎樣與數(shù)據(jù)系統(tǒng)關(guān)聯(lián)起來的呢?答案是日志有其特定的應(yīng)用目標(biāo):它記錄了什么時(shí)間發(fā)生了什么事情。 而對(duì)分布式數(shù)據(jù)系統(tǒng)許多方面而言, 這才是問題的真正核心。
不過,在我們進(jìn)行更加深入的討論之前,讓我先澄清有些讓人混淆的概念。每個(gè)編程人員都熟悉另一種日志記錄-應(yīng)用使用syslog或者log4j可能寫入到本地文件里的沒有結(jié)構(gòu)的錯(cuò)誤信息或者追蹤信息。為了區(qū)分開來,我們把這種情形的日志記錄稱為“應(yīng)用日志記錄”。應(yīng)用日志記錄是我在這兒所說的日志的一種低級(jí)的變種。最大的區(qū)別是:文本日志意味著主要用來方便人們閱讀,而我所說明的“日志”或者“數(shù)據(jù)日志”的建立是方便程序訪問。
(實(shí)際上,如果你對(duì)它進(jìn)行深入的思考,那么人們讀取某個(gè)機(jī)器上的日志這種理念有些不順應(yīng)時(shí)代潮流。當(dāng)涉及到許多服務(wù)和服務(wù)器的時(shí)候,這種方法很快就變成一個(gè)難于管理的方式,而且為了認(rèn)識(shí)多個(gè)機(jī)器的行為,日志的目標(biāo)很快就變成查詢和圖形化這些行為的輸入了-對(duì)多個(gè)機(jī)器的某些行為而言,文件里的英文形式的文本同這兒所描述的這種結(jié)構(gòu)化的日志相比幾乎就不適合了。)
數(shù)據(jù)庫(kù)日志
我不知道日志概念起源于何處-可能它就像二進(jìn)制搜索一樣:發(fā)明者認(rèn)為它太簡(jiǎn)單而不能當(dāng)作一項(xiàng)發(fā)明。它早在IBM的系統(tǒng)R出現(xiàn)時(shí)候就出現(xiàn)了。數(shù)據(jù)庫(kù)里的用法是在崩潰的時(shí)候用它來同步各種數(shù)據(jù)結(jié)構(gòu)和索引。為了保證操作的原子性和持久性,在對(duì)數(shù)據(jù)庫(kù)維護(hù)的所有各種數(shù)據(jù)結(jié)構(gòu)做更改之前,數(shù)據(jù)庫(kù)把即將修改的信息謄寫到日志里。日志記錄了發(fā)生了什么,而且其中的每個(gè)表或者索引都是一些數(shù)據(jù)結(jié)構(gòu)或者索引的歷史映射。由于日志是即刻永久化的,可以把它當(dāng)作崩潰發(fā)生時(shí)用來恢復(fù)其他所有永久性結(jié)構(gòu)的可信賴數(shù)據(jù)源。
隨著時(shí)間的推移,日志的用途從實(shí)現(xiàn)ACID細(xì)節(jié)成長(zhǎng)為數(shù)據(jù)庫(kù)間復(fù)制數(shù)據(jù)的一種方法。利用日志的結(jié)果就是發(fā)生在數(shù)據(jù)庫(kù)上的更改順序與遠(yuǎn)端復(fù)制數(shù)據(jù)庫(kù)上的更改順序需要保持完全同步。