標籤:
文章內容非常乾貨,非常值得學習。文章將以四部分進行闡述,建議大家耐心看完。
第一部分:Log是什麼?
第二部分:Data Integration
第三部分:日誌和即時資料流處理
第四部分:系統建設
我在六年前的一個令人興奮的時刻加入到LinkedIn公司。從那個時候開始我們就破解單一的、集中式資料庫的限制,並且啟動到特殊的分布式系統套件 的轉換。這是一件令人興奮的事情:我們構建、部署,而且直到今天仍然在啟動並執行分布式圖形資料庫、分布式搜尋後端、Hadoop安裝以及第一代和第二代索引值 資料存放區。
從這一切裡我們體會到的最有益的事情是我們構建的許多東西的核心裡都包含一個簡單的理念:日誌。有時候也稱作預先寫入日誌或者提交日誌或者交易記錄,日誌幾乎在電腦產生的時候就存在,同時它還是許多分布式資料系統和即時應用結構的核心。
不懂得日誌,你就不可能完全懂得資料庫,NoSQL儲存,KVStore for Redis,複製,paxos,Hadoop,版本控制以及幾乎所有的軟體系統;然而大多數軟 件工程師對它們不是很熟悉。我願意改變這種現狀。在這篇部落格文章裡,我將帶你瀏覽你必須瞭解的有關日誌的所有的東西,包括日誌是什麼,如何在Data Integration、實 時處理和系統構建中使用日誌等。
第一部分:日誌是什麼?
日誌是一種簡單的不能再簡單的儲存抽象。它是一個只能增加的,完全按照時間排序的一系列記錄。日誌看起來如下:
我們可以給日誌的末尾添加記錄,並且可以從左至右讀取日誌記錄。每一條記錄都指定了一個唯一的有一定順序的日誌記錄編號。
日誌記錄的排序是由“時間”來確定的,這是因為位於左邊的日誌記錄比位於右邊的要早些。日誌記錄編號可以看作是這條日誌 記錄的“時間戳記”。在一開始就把這種排序說成是按時間排序顯得有點多餘 ,不過 ,與任何一個具體的物理時鐘相比,時間 屬性是非常便於使用的屬性。在我們運行多個分布式系統的時候,這個屬性就顯得非常重要。
對於這篇討論的目標而言,日誌記錄的內容和格式不怎麼重要。另外提醒一下,在完全耗盡儲存空間的情況下,我們不可能 再給日誌添加記錄。稍後我們將會提到這個問題。
日誌並不是完全不同於檔案或者資料表的。檔案是由一系列位元組組成,表是由一系列記錄組成,而日誌實際上只是按照時間順序儲存記錄的 一種資料表或者檔案。
此時,你可能奇怪為什麼要討論這麼簡單的事情呢? 不同環境下的一個只可增加的有一定順序的日誌記錄是怎樣與資料系統關聯起來的呢?答案是日誌有其特定的應用目標:它記錄了什麼時間發生了什麼事情。 而對分布式資料系統許多方面而言, 這才是問題的真正核心。
不過,在我們進行更加深入的討論之前,讓我先澄清有些讓人混淆的概念。每個編程人員都熟悉另一種日誌記錄-應用使用syslog或者log4j可能寫 入到本地檔案裡的沒有結構的錯誤資訊或者追蹤資訊。為了區分開來,我們把這種情形的日誌記錄稱為“應用日誌記錄”。應用日誌記錄是我在這兒所說的日誌的一 種低級的變種。最大的區別是:文本日誌意味著主要用來方便人們閱讀,而我所說明的“日誌”或者“資料日誌”的建立是方便程式訪問。
(實際上,如果你對它進行深入的思考,那麼人們讀取某個機器上的日誌這種理念有些不順應時代潮流。當涉及到許多服務和伺服器的時候,這種方法很快就變 成一個難於管理的方式,而且為了認識多個機器的行為,日誌的目標很快就變成查詢和圖形化這些行為的輸入了-對多個機器的某些行為而言,檔案裡的英文形式的 文本同這兒所描述的這種結構化的日誌相比幾乎就不適合了。)
資料庫日誌
我不知道日誌概念起源於何處-可能它就像二進位搜尋一樣:發明者認為它太簡單而不能當作一項發明。它早在IBM的系統R出現時候就出現了。資料庫裡的 用法是在崩潰的時候用它來同步各種資料結構和索引。為了保證操作的原子性和持久性,在對資料庫維護的所有各種資料結構做更改之前,資料庫把即將修改的資訊 謄寫到日誌裡。日誌記錄了發生了什麼,而且其中的每個表或者索引都是一些資料結構或者索引的曆史映射。由於日誌是即刻永久化的,可以把它當作崩潰發生時用 來恢複其他所有永久性結構的可信賴資料來源。
隨著時間的推移,日誌的用途從實現ACID細節成長為資料庫間複製資料的一種方法。利用日誌的結果就是發生在資料庫上的更改順序與遠端複製資料庫上的更改順序需要保持完全同步。
Oracle,MySQL 和PostgreSQL都包括用於給備用的複製資料庫傳輸日誌的日誌傳輸協議。Oracle還把日誌產品化為一個通用的資料訂閱機制,這樣非Oracle 資料訂閱使用者就可以使用XStreams和GoldenGate訂閱資料了,MySQL和PostgreSQL上的類似的實現則成為許多資料結構的關鍵組 件。
正是由於這樣的起源,機器可識別的日誌的概念大部分都被局限在資料庫內部。日誌用做資料訂閱的機制似乎是偶然出現的,不過要把這種 抽象用於支援所有類型的訊息傳輸、資料流和即時資料處理是不切實際的。
分布式系統日誌
日誌解決了兩個問題:更改動作的排序和資料的分發,這兩個問題在分布式資料系統裡顯得尤為重要。協商出一致的更改動作的順序(或者說保持各個子系統本身的做法,但可以進行存在副作用的資料拷貝)是分布式系統設計的核心問題之一。
以日誌為中心實現分布式系統是受到了一個簡單的經驗常識的啟發,我把這個經驗常識稱為狀態機器複製原理:如果兩個相同的、確定性進程從同一狀態開始,並且以相同的順序獲得相同的輸入,那麼這兩個進程將會產生相同的輸出,並且結束在相同的狀態。
這也許有點難以理解,讓我們更加深入的探討,弄懂它的真正含義。
確定性意味著處理過程是與時間無關的,而且任何其他“外部的“輸入不會影響到處理結果。例如,如果一個程式的輸出會受到線程執行的具體順序影響,或者 受到gettimeofday調用、或者其他一些非重複性事件的影響,那麼這樣的程式一般最有可能被認為是非確定性。
進程狀態是進程儲存在機器上的任何資料,在進程處理結束的時候,這些資料要麼儲存在記憶體裡,要麼儲存在磁碟上。
以相同的順序獲得相同輸入的地方應當引起注意-這就是引入日誌的地方。這兒有一個重要的常識:如果給兩段確定性代碼相同的日誌輸入,那麼它們就會產生相同的輸出。
分散式運算這方面的應用就格外明顯。你可以把用多台機器一起執行同一件事情的問題縮減為實現分布式一致性日誌為這些進程輸入的問題。這兒日誌的目的是把所有非確定性東西排除在輸入資料流之外,來確保每個複製進程能夠同步地處理輸入。
當你理解了這個以後,狀態機器複製原理就不再複雜或者說不再深奧了:這或多或少的意味著“確定性處理過程就是確定性”。不管怎樣,我都認為它是分布式系統設計裡較常用的工具之一。
這種方式的一個美妙之處就在於索引日誌的時間戳記就像時鐘狀態的一個副本——你可以用一個單獨的數字描述每一個副本,這就是經過處理的日誌的時間戳記。時間戳記與日誌一一對應著整個副本的狀態。
由於寫進日誌的內容的不同,也就有許多在系統中應用這個原則的不同方式。舉個例子,我們記錄一個服務的請求,或者服務從請求到響應的狀態變化,或者它 執行命令的轉換。理論上來說,我們甚至可以為每一個副本記錄一系列要執行的機器指令或者調用的方法名和參數。只要兩個進程用相同的方式處理這些輸入,這些 進程就會保持副本的一致性。
一千個人眼中有一千種日誌的用法。資料庫工作者通常區分物理日誌和邏輯日誌。物理日誌就是記錄每一行被改變的內容。邏輯日誌記錄的不是改變的行而是那些引起行的內容被改變的SQL語句(insert,update和delete語句)。
分布式系統通常可以寬泛分為兩種方法來處理資料和完成響應。“狀態機器模型”通常引用一個主動-主動的模型——也就是我們為之記錄請求和響應的對象。 對此進行一個細微的更改,稱之為“預備份模型”,就是選出一個副本做為leader,並允許它按照請求到達的時間來進行處理並從處理過程中輸出記錄其狀態 改變的日誌。其他的副本按照leader狀態改變的順序而應用那些改變,這樣他們之間達到同步,並能夠在leader失敗的時候接替leader的工作。
為了理解兩種方式的不同,我們來看一個不太嚴謹的例子。假定有一個演算法服務的副本,保持一個獨立的數字作為它的狀態(初始值為0),並對這個值進行加 法和乘法運算。主動-主動方式應該會輸出所進行的變換,比如“+1”,“*2”等。每一個副本都會應用這些變換,從而得到同樣的解集。主動-被動方式將會 有一個獨立的主體執行這些變換並輸出結果日誌,比如“1”,“3”,“6”等。這個例子也清楚的展示了為什麼說順序是保證各副本間一致性的關鍵:一次加法 和乘法的順序的改變將會導致不同的結果。
分布式日誌可以理解為一致性問題模型的資料結構。因為日誌代表了後續追加值的一系列決策。你需要重新審視Paxos演算法簇,儘管日誌模組是他們最常見 的應用。 在Paxos演算法中,它通常通過使用稱之為多paxos的協議,這種協議將日誌建模為一系列的問題,在日誌中每個問題都有對應的部分。在ZAB, RAFT等其它的協議中,日誌的作用尤為突出,它直接對維護分布式的、一致性的日誌的問題建模。
我懷疑的是,我們就曆史發展的觀點是有偏差的,可能是由於過去的幾十年中,分散式運算的理論遠超過了其實際應用。在現實中,共識的問題是有點太簡單 了。電腦系統很少需要決定單個值,他們幾乎總是處理成序列的請求。這樣的記錄,而不是一個簡單的單值寄存器,自然是更加抽象。
此外,專註於演算法掩蓋了 抽象系統需要的底層的日誌。我懷疑,我們最終會把日誌中更注重作為一個商品化的基石,不論其是否以同樣的方式 實施的,我們經常談論一個雜湊表而不是糾結我們 得到是不是具體某個細節的雜湊表,例如線性或者帶有什麼什麼其它變體雜湊表。日誌將成為一種福士化的介面,為大多數演算法和其實現提升提供最好的保證和最佳 的效能。
變更日誌101: 表與事件的二相性。
讓我們繼續聊資料庫。資料庫中存在著大量變更日誌和表之間的二相性。這些日誌有點類似借貸清單和銀行的流程,資料庫表就是當前的盈餘表。如果你有大量 的變更日誌,你就可以使用這些變更用以建立捕獲目前狀態的表。這張表將記錄每個關鍵點(日誌中一個特別的時間點)的狀態資訊。這就是為什麼日誌是非常基本 的資料結構的意義所在:日誌可用來建立基本表,也可以用來建立各類衍生表。同時意味著可以儲存非關係型的對象。
這個流程也是可逆的:如果你正在對一張表進行更新,你可以記錄這些變更,並把所有更新的日誌發布到表的狀態資訊中。這些變更日誌就是你所需要的支援准 即時的複製。基於此,你就可以清楚的理解表與事件的二相性: 表支援了待用資料而日誌捕獲變更。日誌的魅力就在於它是變更的完整記錄,它不僅僅捕獲了表的最終版本的內容,它還記錄了曾經存在過的其它版本的資訊。日誌 實質上是表曆史狀態的一系列備份。
這可能會引起你對原始碼的版本管理。原始程式碼控制和資料庫之間有密切關係。版本管理解決了一個大家非常熟悉的問題,那就是什麼是分布式資料系統需要解決 的— 時時刻刻在變化著的分布式管理。版本管理系統通常以補丁的發布為基礎,這實際上可能是一個日誌。您可以直接對當前 類似於表中的代碼做出“快照”互動。你會注意到, 與其他分布式狀態化系統類別似,版本控制系統 當你更新時會複製日誌,你希望的只是更新補丁並將它們應用到你的當前快照中。
最近,有些人從Datomic –一家銷售日誌資料庫的公司得到了一些想法。這些想法使他們對如何 在他們的系統應用這些想法有了開闊的認識。 當然這些想法不是只針對這個系統,他們會成為 十多年分布式系統和資料庫文獻的一部分。
這可能似乎有點過於理想化。但是不要悲觀!我們會很快把它實現。
接下來的內容
在這篇文章的其餘部分,我將試圖說明日誌除了可用在分散式運算或者抽象分散式運算模型內部之外,還可用在哪些方面。其中包括:
Data Integration-讓機構的全部儲存和處理系統裡的所有資料很容易地得到訪問。
即時資料處理-計算產生的資料流。
分布式系統設計-實際應用的系統是如何通過使用集中式日誌來簡化設計的。
所有這些用法都是通過把日誌用做單獨服務來實現的。
在上面任何一種用法裡,日誌的用途開始都是使用了日誌所能提供的某個簡易功能:產生永久的、可重現的記錄。令人意外的是,問題的核心是可以讓多少台機器以特定的方式,按照自身的速度重現記錄的能力。
http://www.pmtoo.com/data/2014/0305/5037.html
首席工程師揭秘:LinkedIn大資料後台是如何運作的?(一)