您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“如何理解LinkedIn以日志為中心的大數(shù)據(jù)管理方式”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“如何理解LinkedIn以日志為中心的大數(shù)據(jù)管理方式”吧!
以下是原文:
我在六年前的一個(gè)令人興奮的時(shí)刻加入到LinkedIn公司。從那個(gè)時(shí)候開(kāi)始我們就破解單一的、集中式數(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í)候也稱(chēng)作預(yù)先寫(xiě)入日志或者提交日志或者事務(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í)間排序的一系列記錄。日志看起來(lái)如下:
我們可以給日志的末尾添加記錄,并且可以從左到右讀取日志記錄。每一條記錄都指定了一個(gè)唯一的有一定順序的日志記錄編號(hào)。
日志記錄的排序是由“時(shí)間”來(lái)確定的,這是因?yàn)槲挥谧筮叺娜罩居涗洷任挥谟疫叺囊缧?。日志記錄編?hào)可以看作是這條日志 記錄的“時(shí)間戳”。在一開(kāi)始就把這種排序說(shuō)成是按時(shí)間排序顯得有點(diǎn)多余 ,不過(guò) ,與任何一個(gè)具體的物理時(shí)鐘相比,時(shí)間 屬性是非常便于使用的屬性。在我們運(yùn)行多個(gè)分布式系統(tǒng)的時(shí)候,這個(gè)屬性就顯得非常重要。
對(duì)于這篇討論的目標(biāo)而言,日志記錄的內(nèi)容和格式不怎么重要。另外提醒一下,在完全耗盡存儲(chǔ)空間的情況下,我們不可能 再給日志添加記錄。稍后我們將會(huì)提到這個(gè)問(wèn)題。
日志并不是完全不同于文件或者數(shù)據(jù)表的。文件是由一系列字節(jié)組成,表是由一系列記錄組成,而日志實(shí)際上只是按照時(shí)間順序存儲(chǔ)記錄的 一種數(shù)據(jù)表或者文件。
此時(shí),你可能奇怪為什么要討論這么簡(jiǎn)單的事情呢? 不同環(huán)境下的一個(gè)只可增加的有一定順序的日志記錄是怎樣與數(shù)據(jù)系統(tǒng)關(guān)聯(lián)起來(lái)的呢?答案是日志有其特定的應(yīng)用目標(biāo):它記錄了什么時(shí)間發(fā)生了什么事情。 而對(duì)分布式數(shù)據(jù)系統(tǒng)許多方面而言, 這才是問(wèn)題的真正核心。
不過(guò),在我們進(jìn)行更加深入的討論之前,讓我先澄清有些讓人混淆的概念。每個(gè)編程人員都熟悉另一種日志記錄-應(yīng)用使用syslog或者log4j可能寫(xiě)入到本地文件里的沒(méi)有結(jié)構(gòu)的錯(cuò)誤信息或者追蹤信息。為了區(qū)分開(kāi)來(lái),我們把這種情形的日志記錄稱(chēng)為“應(yīng)用日志記錄”。應(yīng)用日志記錄是我在這兒所說(shuō)的日志的一種低級(jí)的變種。最大的區(qū)別是:文本日志意味著主要用來(lái)方便人們閱讀,而我所說(shuō)明的“日志”或者“數(shù)據(jù)日志”的建立是方便程序訪問(wèn)。
(實(shí)際上,如果你對(duì)它進(jìn)行深入的思考,那么人們讀取某個(gè)機(jī)器上的日志這種理念有些不順應(yīng)時(shí)代潮流。當(dāng)涉及到許多服務(wù)和服務(wù)器的時(shí)候,這種方法很快就變成一個(gè)難于管理的方式,而且為了認(rèn)識(shí)多個(gè)機(jī)器的行為,日志的目標(biāo)很快就變成查詢(xún)和圖形化這些行為的輸入了-對(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í)候用它來(lái)同步各種數(shù)據(jù)結(jié)構(gòu)和索引。為了保證操作的原子性和持久性,在對(duì)數(shù)據(jù)庫(kù)維護(hù)的所有各種數(shù)據(jù)結(jié)構(gòu)做更改之前,數(shù)據(jù)庫(kù)把即將修改的信息謄寫(xiě)到日志里。日志記錄了發(fā)生了什么,而且其中的每個(gè)表或者索引都是一些數(shù)據(jù)結(jié)構(gòu)或者索引的歷史映射。由于日志是即刻永久化的,可以把它當(dāng)作崩潰發(fā)生時(shí)用來(lái)恢復(fù)其他所有永久性結(jié)構(gòu)的可信賴(lài)數(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ù)上的更改順序需要保持完全同步。
Oracle,MySQL 和PostgreSQL都包括用于給備用的復(fù)制數(shù)據(jù)庫(kù)傳輸日志的日志傳輸協(xié)議。Oracle還把日志產(chǎn)品化為一個(gè)通用的數(shù)據(jù)訂閱機(jī)制,這樣非Oracle數(shù)據(jù)訂閱用戶(hù)就可以使用XStreams和GoldenGate訂閱數(shù)據(jù)了,MySQL和PostgreSQL上的類(lèi)似的實(shí)現(xiàn)則成為許多數(shù)據(jù)結(jié)構(gòu)的關(guān)鍵組件。
正是由于這樣的起源,機(jī)器可識(shí)別的日志的概念大部分都被局限在數(shù)據(jù)庫(kù)內(nèi)部。日志用做數(shù)據(jù)訂閱的機(jī)制似乎是偶然出現(xiàn)的,不過(guò)要把這種 抽象用于支持所有類(lèi)型的消息傳輸、數(shù)據(jù)流和實(shí)時(shí)數(shù)據(jù)處理是不切實(shí)際的。
分布式系統(tǒng)日志
日志解決了兩個(gè)問(wèn)題:更改動(dòng)作的排序和數(shù)據(jù)的分發(fā),這兩個(gè)問(wèn)題在分布式數(shù)據(jù)系統(tǒng)里顯得尤為重要。協(xié)商出一致的更改動(dòng)作的順序(或者說(shuō)保持各個(gè)子系統(tǒng)本身的做法,但可以進(jìn)行存在副作用的數(shù)據(jù)拷貝)是分布式系統(tǒng)設(shè)計(jì)的核心問(wèn)題之一。
以日志為中心實(shí)現(xiàn)分布式系統(tǒng)是受到了一個(gè)簡(jiǎn)單的經(jīng)驗(yàn)常識(shí)的啟發(fā),我把這個(gè)經(jīng)驗(yàn)常識(shí)稱(chēng)為狀態(tài)機(jī)復(fù)制原理:如果兩個(gè)相同的、確定性的進(jìn)程從同一狀態(tài)開(kāi)始,并且以相同的順序獲得相同的輸入,那么這兩個(gè)進(jìn)程將會(huì)生成相同的輸出,并且結(jié)束在相同的狀態(tài)。
這也許有點(diǎn)難以理解,讓我們更加深入的探討,弄懂它的真正含義。
確定性意味著處理過(guò)程是與時(shí)間無(wú)關(guān)的,而且任何其他“外部的“輸入不會(huì)影響到處理結(jié)果。例如,如果一個(gè)程序的輸出會(huì)受到線(xiàn)程執(zhí)行的具體順序影響,或者受到gettimeofday調(diào)用、或者其他一些非重復(fù)性事件的影響,那么這樣的程序一般最有可能被認(rèn)為是非確定性的。
進(jìn)程狀態(tài)是進(jìn)程保存在機(jī)器上的任何數(shù)據(jù),在進(jìn)程處理結(jié)束的時(shí)候,這些數(shù)據(jù)要么保存在內(nèi)存里,要么保存在磁盤(pán)上。
以相同的順序獲得相同輸入的地方應(yīng)當(dāng)引起注意-這就是引入日志的地方。這兒有一個(gè)重要的常識(shí):如果給兩段確定性代碼相同的日志輸入,那么它們就會(huì)生成相同的輸出。
分布式計(jì)算這方面的應(yīng)用就格外明顯。你可以把用多臺(tái)機(jī)器一起執(zhí)行同一件事情的問(wèn)題縮減為實(shí)現(xiàn)分布式一致性日志為這些進(jìn)程輸入的問(wèn)題。這兒日志的目的是把所有非確定性的東西排除在輸入流之外,來(lái)確保每個(gè)復(fù)制進(jìn)程能夠同步地處理輸入。
當(dāng)你理解了這個(gè)以后,狀態(tài)機(jī)復(fù)制原理就不再?gòu)?fù)雜或者說(shuō)不再深?yuàn)W了:這或多或少的意味著“確定性的處理過(guò)程就是確定性的”。不管怎樣,我都認(rèn)為它是分布式系統(tǒng)設(shè)計(jì)里較常用的工具之一。
這種方式的一個(gè)美妙之處就在于索引日志的時(shí)間戳就像時(shí)鐘狀態(tài)的一個(gè)副本——你可以用一個(gè)單獨(dú)的數(shù)字描述每一個(gè)副本,這就是經(jīng)過(guò)處理的日志的時(shí)間戳。時(shí)間戳與日志一一對(duì)應(yīng)著整個(gè)副本的狀態(tài)。
由于寫(xiě)進(jìn)日志的內(nèi)容的不同,也就有許多在系統(tǒng)中應(yīng)用這個(gè)原則的不同方式。舉個(gè)例子,我們記錄一個(gè)服務(wù)的請(qǐng)求,或者服務(wù)從請(qǐng)求到響應(yīng)的狀態(tài)變化,或者它執(zhí)行命令的轉(zhuǎn)換。理論上來(lái)說(shuō),我們甚至可以為每一個(gè)副本記錄一系列要執(zhí)行的機(jī)器指令或者調(diào)用的方法名和參數(shù)。只要兩個(gè)進(jìn)程用相同的方式處理這些輸入,這些進(jìn)程就會(huì)保持副本的一致性。
一千個(gè)人眼中有一千種日志的用法。數(shù)據(jù)庫(kù)工作者通常區(qū)分物理日志和邏輯日志。物理日志就是記錄每一行被改變的內(nèi)容。邏輯日志記錄的不是改變的行而是那些引起行的內(nèi)容被改變的SQL語(yǔ)句(insert,update和delete語(yǔ)句)。
分布式系統(tǒng)通常可以寬泛分為兩種方法來(lái)處理數(shù)據(jù)和完成響應(yīng)?!盃顟B(tài)機(jī)器模型”通常引用一個(gè)主動(dòng)-主動(dòng)的模型——也就是我們?yōu)橹涗浾?qǐng)求和響應(yīng)的對(duì)象。對(duì)此進(jìn)行一個(gè)細(xì)微的更改,稱(chēng)之為“預(yù)備份模型”,就是選出一個(gè)副本做為leader,并允許它按照請(qǐng)求到達(dá)的時(shí)間來(lái)進(jìn)行處理并從處理過(guò)程中輸出記錄其狀態(tài)改變的日志。其他的副本按照l(shuí)eader狀態(tài)改變的順序而應(yīng)用那些改變,這樣他們之間達(dá)到同步,并能夠在leader失敗的時(shí)候接替leader的工作。
為了理解兩種方式的不同,我們來(lái)看一個(gè)不太嚴(yán)謹(jǐn)?shù)睦?。假定有一個(gè)算法服務(wù)的副本,保持一個(gè)獨(dú)立的數(shù)字作為它的狀態(tài)(初始值為0),并對(duì)這個(gè)值進(jìn)行加法和乘法運(yùn)算。主動(dòng)-主動(dòng)方式應(yīng)該會(huì)輸出所進(jìn)行的變換,比如“+1”,“*2”等。每一個(gè)副本都會(huì)應(yīng)用這些變換,從而得到同樣的解集。主動(dòng)-被動(dòng)方式將會(huì)有一個(gè)獨(dú)立的主體執(zhí)行這些變換并輸出結(jié)果日志,比如“1”,“3”,“6”等。這個(gè)例子也清楚的展示了為什么說(shuō)順序是保證各副本間一致性的關(guān)鍵:一次加法和乘法的順序的改變將會(huì)導(dǎo)致不同的結(jié)果。
分布式日志可以理解為一致性問(wèn)題模型的數(shù)據(jù)結(jié)構(gòu)。因?yàn)槿罩敬砹撕罄m(xù)追加值的一系列決策。你需要重新審視Paxos算法簇,盡管日志模塊是他們最常見(jiàn)的應(yīng)用。 在Paxos算法中,它通常通過(guò)使用稱(chēng)之為多paxos的協(xié)議,這種協(xié)議將日志建模為一系列的問(wèn)題,在日志中每個(gè)問(wèn)題都有對(duì)應(yīng)的部分。在ZAB, RAFT等其它的協(xié)議中,日志的作用尤為突出,它直接對(duì)維護(hù)分布式的、一致性的日志的問(wèn)題建模。
我懷疑的是,我們就歷史發(fā)展的觀點(diǎn)是有偏差的,可能是由于過(guò)去的幾十年中,分布式計(jì)算的理論遠(yuǎn)超過(guò)了其實(shí)際應(yīng)用。在現(xiàn)實(shí)中,共識(shí)的問(wèn)題是有點(diǎn)太簡(jiǎn)單了。計(jì)算機(jī)系統(tǒng)很少需要決定單個(gè)值,他們幾乎總是處理成序列的請(qǐng)求。這樣的記錄,而不是一個(gè)簡(jiǎn)單的單值寄存器,自然是更加抽象。
此外,專(zhuān)注于算法掩蓋了 抽象系統(tǒng)需要的底層的日志。我懷疑,我們最終會(huì)把日志中更注重作為一個(gè)商品化的基石,不論其是否以同樣的方式 實(shí)施的,我們經(jīng)常談?wù)撘粋€(gè)哈希表而不是糾結(jié)我們 得到是不是具體某個(gè)細(xì)節(jié)的哈希表,例如線(xiàn)性或者帶有什么什么其它變體哈希表。日志將成為一種大眾化的接口,為大多數(shù)算法和其實(shí)現(xiàn)提升提供最好的保證和最佳的性能。
變更日志101: 表與事件的二相性。
讓我們繼續(xù)聊數(shù)據(jù)庫(kù)。數(shù)據(jù)庫(kù)中存在著大量變更日志和表之間的二相性。這些日志有點(diǎn)類(lèi)似借貸清單和銀行的流程,數(shù)據(jù)庫(kù)表就是當(dāng)前的盈余表。如果你有大量的變更日志,你就可以使用這些變更用以創(chuàng)建捕獲當(dāng)前狀態(tài)的表。這張表將記錄每個(gè)關(guān)鍵點(diǎn)(日志中一個(gè)特別的時(shí)間點(diǎn))的狀態(tài)信息。這就是為什么日志是非?;镜臄?shù)據(jù)結(jié)構(gòu)的意義所在:日志可用來(lái)創(chuàng)建基本表,也可以用來(lái)創(chuàng)建各類(lèi)衍生表。同時(shí)意味著可以存儲(chǔ)非關(guān)系型的對(duì)象。
這個(gè)流程也是可逆的:如果你正在對(duì)一張表進(jìn)行更新,你可以記錄這些變更,并把所有更新的日志發(fā)布到表的狀態(tài)信息中。這些變更日志就是你所需要的支持準(zhǔn)實(shí)時(shí)的克隆?;诖?,你就可以清楚的理解表與事件的二相性: 表支持了靜態(tài)數(shù)據(jù)而日志捕獲變更。日志的魅力就在于它是變更的完整記錄,它不僅僅捕獲了表的最終版本的內(nèi)容,它還記錄了曾經(jīng)存在過(guò)的其它版本的信息。日志實(shí)質(zhì)上是表歷史狀態(tài)的一系列備份。
這可能會(huì)引起你對(duì)源代碼的版本管理。源代碼管理和數(shù)據(jù)庫(kù)之間有密切關(guān)系。版本管理解決了一個(gè)大家非常熟悉的問(wèn)題,那就是什么是分布式數(shù)據(jù)系統(tǒng)需要解決的— 時(shí)時(shí)刻刻在變化著的分布式管理。版本管理系統(tǒng)通常以補(bǔ)丁的發(fā)布為基礎(chǔ),這實(shí)際上可能是一個(gè)日志。您可以直接對(duì)當(dāng)前 類(lèi)似于表中的代碼做出“快照”互動(dòng)。你會(huì)注意到, 與其他分布式狀態(tài)化系統(tǒng)類(lèi)似,版本控制系統(tǒng) 當(dāng)你更新時(shí)會(huì)復(fù)制日志,你希望的只是更新補(bǔ)丁并將它們應(yīng)用到你的當(dāng)前快照中。
最近,有些人從Datomic –一家銷(xiāo)售日志數(shù)據(jù)庫(kù)的公司得到了一些想法。這些想法使他們對(duì)如何 在他們的系統(tǒng)應(yīng)用這些想法有了開(kāi)闊的認(rèn)識(shí)。 當(dāng)然這些想法不是只針對(duì)這個(gè)系統(tǒng),他們會(huì)成為 十多年分布式系統(tǒng)和數(shù)據(jù)庫(kù)文獻(xiàn)的一部分。
這可能似乎有點(diǎn)過(guò)于理想化。但是不要悲觀!我們會(huì)很快把它實(shí)現(xiàn)。
請(qǐng)讓我首先解釋 一下“數(shù)據(jù)集成”是什么意思,還有為什么我覺(jué)得它很重要,之后我們?cè)賮?lái)看看它和日志有什么關(guān)系。
數(shù)據(jù)集成就是將數(shù)據(jù)組織起來(lái),使得在與其有關(guān)的服務(wù)和系統(tǒng)中可以訪問(wèn)它們。“數(shù)據(jù)集成”(data integration)這個(gè)短語(yǔ)應(yīng)該不止這么簡(jiǎn)單,但是我找不到一個(gè)更好的解釋。而更常見(jiàn)的術(shù)語(yǔ) ETL 通常只是覆蓋了數(shù)據(jù)集成的一個(gè)有限子集(譯注:ETL,Extraction-Transformation-Loading的縮寫(xiě),即數(shù)據(jù)提取、轉(zhuǎn)換和加載)——相對(duì)于關(guān)系型數(shù)據(jù)倉(cāng)庫(kù)。但我描述的東西很大程度上可以理解為,將ETL推廣至實(shí)時(shí)系統(tǒng)和處理流程。
你一定不會(huì)聽(tīng)到數(shù)據(jù)集成就興趣盎然屏住呼吸,并且天花亂墜的想到關(guān)于大數(shù)據(jù)的概念,不過(guò),我相信世俗的問(wèn)題“讓數(shù)據(jù)可被訪問(wèn)” 是一個(gè)組織應(yīng)該關(guān)注的有價(jià)值的事情。
對(duì)數(shù)據(jù)的高效使用遵循一種 馬斯洛的需要層次理論 。金字塔的基礎(chǔ)部分包括捕獲所有相關(guān)數(shù)據(jù),能夠?qū)⑺鼈內(nèi)糠诺竭m當(dāng)?shù)奶幚憝h(huán)境(那個(gè)環(huán)境應(yīng)該是一個(gè)奇妙的實(shí)時(shí)查詢(xún)系統(tǒng),或者僅僅是文本文件和python腳本)。這些數(shù)據(jù)需要以統(tǒng)一的方式建模,這樣就可以方便讀取和數(shù)據(jù)處理。如果這種以統(tǒng)一的方式捕獲數(shù)據(jù)的基本需求得到滿(mǎn)足,那么就可以在基礎(chǔ)設(shè)施上以若干種方法處理這些數(shù)據(jù)——映射化簡(jiǎn)(MapReduce),實(shí)時(shí)查詢(xún)系統(tǒng),等等。
很明顯,有一點(diǎn)值得注意:如果沒(méi)有可靠的、完整的數(shù)據(jù)流,Hadoop集群除了象昂貴的且難于安裝的空間取暖器哪樣外不會(huì)做更多事情了。一旦數(shù)據(jù)和處理可用,人們就會(huì)關(guān)心良好數(shù)據(jù)模型和一致地易于理解的語(yǔ)法哪些更細(xì)致的問(wèn)題。最后,人們才會(huì)關(guān)注更加高級(jí)的處理-更好的可視化、報(bào)表以及處理和預(yù)測(cè)算法。
以我的經(jīng)驗(yàn),大多數(shù)機(jī)構(gòu)在數(shù)據(jù)金字塔的底部存在巨大的漏洞-它們?nèi)狈煽康摹⑼暾臄?shù)據(jù)流-而是打算直接跳到高級(jí)數(shù)據(jù)模型技術(shù)上。這樣做完全是反著來(lái)做的。因此,問(wèn)題是我們?nèi)绾螛?gòu)建通過(guò)機(jī)構(gòu)內(nèi)所有數(shù)據(jù)系統(tǒng)的可靠的數(shù)據(jù)流。
數(shù)據(jù)集成:兩個(gè)并發(fā)癥
兩種趨勢(shì)使數(shù)據(jù)集成變得更困難。
事件數(shù)據(jù)管道
第一個(gè)趨勢(shì)是增長(zhǎng)的事件數(shù)據(jù)(event data)。事件數(shù)據(jù)記錄的是發(fā)生的事情,而不是存在的東西。在web系統(tǒng)中,這就意味著用戶(hù)活動(dòng)日志,還有為了可靠的操作以及監(jiān)控?cái)?shù)據(jù)中心的機(jī)器的目的,所需要記錄的機(jī)器級(jí)別的事件和統(tǒng)計(jì)數(shù)字。人們傾向稱(chēng)它們?yōu)椤叭罩緮?shù)據(jù)”,因?yàn)樗鼈兘?jīng)常被寫(xiě)到應(yīng)用的日志中,但是這混淆了形式與功能。這種數(shù)據(jù)位于現(xiàn)代web的中心:歸根結(jié)底,Google的資產(chǎn)是由這樣一些建立在點(diǎn)擊和映像基礎(chǔ)之上的相關(guān)管道所生成的——那也就是事件。
這些東西并不是僅限于網(wǎng)絡(luò)公司,只是網(wǎng)絡(luò)公司已經(jīng)完全數(shù)字化,所以它們更容易用設(shè)備記錄。財(cái)務(wù)數(shù)據(jù)一直是面向事件的。RFID(無(wú)線(xiàn)射頻識(shí)別)將這種跟蹤能力賦予物理對(duì)象。我認(rèn)為這種趨勢(shì)仍將繼續(xù),伴隨著這個(gè)過(guò)程的是傳統(tǒng)商務(wù)活動(dòng)的數(shù)字化。
這種類(lèi)型的事件數(shù)據(jù)記錄下發(fā)生的事情,而且往往比傳統(tǒng)數(shù)據(jù)庫(kù)應(yīng)用要大好幾個(gè)數(shù)量級(jí)。這對(duì)于處理提出了重大挑戰(zhàn)。
專(zhuān)門(mén)的數(shù)據(jù)系統(tǒng)的爆發(fā)
第二個(gè)趨勢(shì)來(lái)自于專(zhuān)門(mén)的數(shù)據(jù)系統(tǒng)的爆發(fā),通常這些數(shù)據(jù)系統(tǒng)在最近的五年中開(kāi)始變得流行,并且可以免費(fèi)獲得。專(zhuān)門(mén)的數(shù)據(jù)系統(tǒng)是為OLAP, 搜索, 簡(jiǎn)單 在線(xiàn) 存儲(chǔ), 批處理, 圖像分析, 等 等 而存在的。
更多的不同類(lèi)型數(shù)據(jù)的組合,以及將這些數(shù)據(jù)存放到更多的系統(tǒng)中的愿望,導(dǎo)致了一個(gè)巨大的數(shù)據(jù)集成問(wèn)題。
日志結(jié)構(gòu)數(shù)據(jù)流
為了處理系統(tǒng)之間的數(shù)據(jù)流,日志是最自然的數(shù)據(jù)結(jié)構(gòu)。其中的秘訣很簡(jiǎn)單:
將所有組織的數(shù)據(jù)提取出來(lái),并將它們放到一個(gè)中心日志,以便實(shí)時(shí)查閱。
每個(gè)邏輯數(shù)據(jù)源都可以建模為它自己的日志。一個(gè)數(shù)據(jù)源可以是一個(gè)應(yīng)用程序的事件日志(如點(diǎn)擊量或者頁(yè)面瀏覽量),或者是一個(gè)接受修改的數(shù)據(jù)庫(kù)表。每個(gè)訂閱消息的系統(tǒng)都盡可能快的從日志讀取信息,將每條新的記錄保存到自己的存儲(chǔ),并且提升其在日志中的地位。訂閱方可以是任意一種數(shù)據(jù)系統(tǒng) —— 一個(gè)緩存,Hadoop,另一個(gè)網(wǎng)站中的另一個(gè)數(shù)據(jù)庫(kù),一個(gè)搜索系統(tǒng),等等。
例如,日志針對(duì)每個(gè)更改給出了邏輯時(shí)鐘的概念,這樣所有的訂閱方都可以被測(cè)量。推導(dǎo)不同的訂閱系統(tǒng)的狀態(tài)也因此變得相對(duì)簡(jiǎn)單的多,因?yàn)槊總€(gè)系統(tǒng)都有一個(gè)讀取動(dòng)作的“時(shí)間點(diǎn)”。
為了讓這個(gè)顯得更具體,我們考慮一個(gè)簡(jiǎn)單的案例,有一個(gè)數(shù)據(jù)庫(kù)和一組緩存服務(wù)器集群。日志提供了一種同步更新所有這些系統(tǒng),并推導(dǎo)出每一個(gè)系統(tǒng)的接觸時(shí)間點(diǎn)的方法。我們假設(shè)寫(xiě)了一條日志X,然后需要從緩存做一次讀取。如果我們想保證看到的不是陳舊的數(shù)據(jù),我們只需保證沒(méi)有從任何尚未復(fù)制X的緩存中讀取即可。
日志也起到緩存的作用,使數(shù)據(jù)生產(chǎn)與數(shù)據(jù)消費(fèi)相同步。由于許多原因這個(gè)功能很重要,特別是在多個(gè)訂閱方消費(fèi)數(shù)據(jù)的速度各不相同的時(shí)候。這意味著一個(gè)訂閱數(shù)據(jù)系統(tǒng)可以宕機(jī),或者下線(xiàn)維護(hù),之后重新上線(xiàn)以后再趕上來(lái):訂閱方按照自己控制的節(jié)拍來(lái)消費(fèi)數(shù)據(jù)。批處理系統(tǒng),如Hadoop或者是一個(gè)數(shù)據(jù)倉(cāng)庫(kù),或許只是每小時(shí)或者每天消費(fèi)一次數(shù)據(jù),而實(shí)時(shí)查詢(xún)系統(tǒng)可能需要及時(shí)到秒。由于無(wú)論是原始數(shù)據(jù)源還是日志,都沒(méi)有各種目標(biāo)數(shù)據(jù)系統(tǒng)的相關(guān)知識(shí),因此消費(fèi)方系統(tǒng)可以被添加和刪除,而無(wú)需傳輸管道的變化。
特別重要的是:目標(biāo)系統(tǒng)只知道日志,不知道數(shù)據(jù)源系統(tǒng)的任何細(xì)節(jié)。消費(fèi)方系統(tǒng)自身無(wú)需考慮數(shù)據(jù)到底是來(lái)自于一個(gè)RDBMS(關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng)Relational Database Management System),一種新型的鍵值存儲(chǔ),或者它不是由任何形式的實(shí)時(shí)查詢(xún)系統(tǒng)所生成的。這似乎是一個(gè)小問(wèn)題,但實(shí)際上是至關(guān)重要的。
這里我使用術(shù)語(yǔ)“日志”取代了“消息系統(tǒng)”或者“發(fā)布-訂閱”,因?yàn)樗谡Z(yǔ)義上更明確,并且對(duì)支持?jǐn)?shù)據(jù)復(fù)制的實(shí)際實(shí)現(xiàn)這樣的需求,有著更接近的描述。我發(fā)現(xiàn)“發(fā)布訂閱”并不比間接尋址的消息具有更多的含義——如果你比較任何兩個(gè)發(fā)布-訂閱的消息傳遞系統(tǒng)的話(huà),你會(huì)發(fā)現(xiàn)他們承諾的是完全不同的東西,而且大多數(shù)模型在這一領(lǐng)域都不是有用的。你可以認(rèn)為日志是一種消息系統(tǒng),它具有持久性保證和強(qiáng)大的訂閱語(yǔ)義。在分布式系統(tǒng)中,這個(gè)通信模型有時(shí)有個(gè)(有些可怕的)名字叫做原子廣播。
值得強(qiáng)調(diào)的是,日志仍然只是基礎(chǔ)設(shè)施。這并不是管理數(shù)據(jù)流這個(gè)故事的結(jié)束:故事的其余部分圍繞著元數(shù)據(jù),模式,兼容性,以及處理數(shù)據(jù)結(jié)構(gòu)的所有細(xì)節(jié)及其演化。除非有一種可靠的,一般的方法來(lái)處理數(shù)據(jù)流運(yùn)作,語(yǔ)義在其中總是次要的細(xì)節(jié)。
在 LinkedIn(SNS社交網(wǎng)站)
在LinkedIn從集中式關(guān)系數(shù)據(jù)庫(kù)向分布式系統(tǒng)集合轉(zhuǎn)化的過(guò)程中,我看到這個(gè)數(shù)據(jù)集成問(wèn)題迅速演變。
現(xiàn)在主要的數(shù)據(jù)系統(tǒng)包括:
搜索
社交圖譜
Voldemort (鍵值存儲(chǔ))(譯注:一種分布式數(shù)據(jù)庫(kù))
Espresso (文檔存儲(chǔ))
推舉引擎
OLAP查詢(xún)引擎(譯注:OLAP聯(lián)機(jī)分析技術(shù))
Hadoop
Terradata
Ingraphs (監(jiān)控圖表和指標(biāo)服務(wù))
這些都是專(zhuān)門(mén)的分布式系統(tǒng),在其專(zhuān)業(yè)領(lǐng)域提供先進(jìn)的功能。
這種使用日志作為數(shù)據(jù)流的思想,甚至在我到這里之前就已經(jīng)與LinkedIn相伴了。我們開(kāi)發(fā)的一個(gè)最早的基礎(chǔ)設(shè)施之一,是一種稱(chēng)為databus 的服務(wù),它在我們?cè)缙诘腛racle表上提供了一種日志緩存抽象,可伸縮訂閱數(shù)據(jù)庫(kù)修改,這樣我們就可以很好支持我們的社交網(wǎng)絡(luò)和搜索索引。
我會(huì)給出一些歷史并交代一下上下文。我首次參與到這些大約是在2008年左右,在我們轉(zhuǎn)移鍵值存儲(chǔ)之后。我的下一個(gè)項(xiàng)目是讓一個(gè)工作中的Hadoop配置演進(jìn),并給其增加一些我們的推薦流程。由于缺乏這方面的經(jīng)驗(yàn),我們自然而然的安排了數(shù)周計(jì)劃在數(shù)據(jù)的導(dǎo)入導(dǎo)出方面,剩下的時(shí)間則用來(lái)實(shí)現(xiàn)奇妙的預(yù)測(cè)算法。這樣我們就開(kāi)始了長(zhǎng)途跋涉。
我們本來(lái)計(jì)劃是僅僅將數(shù)據(jù)從現(xiàn)存的Oracle數(shù)據(jù)倉(cāng)庫(kù)中剖離。但是我們首先發(fā)現(xiàn)將數(shù)據(jù)從Oracle中迅速取出是一種黑暗藝術(shù)。更糟的是,數(shù)據(jù)倉(cāng)庫(kù)的處理過(guò)程與我們?yōu)镠adoop而計(jì)劃的批處理生產(chǎn)過(guò)程不適合——其大部分處理都是不可逆轉(zhuǎn)的,并且與即將生成的報(bào)告具體相關(guān)。最終我們采取的辦法是,避免使用數(shù)據(jù)倉(cāng)庫(kù),直接訪問(wèn)源數(shù)據(jù)庫(kù)和日志文件。最后,我們?yōu)榱思虞d數(shù)據(jù)到鍵值存儲(chǔ) 并生成結(jié)果,實(shí)現(xiàn)了另外一種管道。
這種普通的數(shù)據(jù)復(fù)制最終成為原始開(kāi)發(fā)項(xiàng)目的主要內(nèi)容之一。糟糕的是,在任何時(shí)間任意管道都有一個(gè)問(wèn)題,Hadoop系統(tǒng)很大程度上是無(wú)用的——在錯(cuò)誤的數(shù)據(jù)基礎(chǔ)上運(yùn)行奇特的算法,只會(huì)產(chǎn)生更多的錯(cuò)誤數(shù)據(jù)。
雖然我們已經(jīng)以一種通用的方式創(chuàng)建事物,但是每個(gè)數(shù)據(jù)源都需要自定義配置安裝。這也被證明是巨量錯(cuò)誤與失敗的根源。我們?cè)贖adoop上實(shí)現(xiàn)的網(wǎng)站功能已經(jīng)開(kāi)始流行起來(lái),同時(shí)我們發(fā)現(xiàn)我們有一長(zhǎng)串感興趣的工程師。每個(gè)用戶(hù)都有他們想要集成的一系列系統(tǒng),他們想要的一系列新數(shù)據(jù)源。
有些東西在我面前開(kāi)始漸漸清晰起來(lái)。
首先,我們已建成的通道雖然有一些雜亂,但實(shí)質(zhì)上它們是很有價(jià)值的。在采用諸如Hadoop的新的處理系統(tǒng)生成可用數(shù)據(jù)的過(guò)程,它開(kāi)啟了大量的可能性。 基于這些數(shù)據(jù)過(guò)去很難實(shí)現(xiàn)的計(jì)算,如今變?yōu)榭赡堋?許多新的產(chǎn)品和分析技術(shù)都來(lái)源于把分片的數(shù)據(jù)放在一起,這些數(shù)據(jù)過(guò)被鎖定在特定的系統(tǒng)中。
第二, 眾所周知,可靠的數(shù)據(jù)加載需要數(shù)據(jù)通道的深度支持。如果我們可以捕獲所有我們需要的結(jié)構(gòu),我就就可以使得Hadoop數(shù)據(jù)全自動(dòng)的加載,這樣就不需要額外的操作來(lái)增加新的數(shù)據(jù)源或者處理模式變更–數(shù)據(jù)就會(huì)自動(dòng)的出現(xiàn)在HDFS,Hive表就會(huì)自動(dòng)的生成對(duì)應(yīng)于新數(shù)據(jù)源的恰當(dāng)?shù)牧小?/p>
第三,我們的數(shù)據(jù)覆蓋率仍然非常低。如果你查看存儲(chǔ)于Hadoop中的可用的Linked 數(shù)據(jù)的全部百分比,它仍然是不完整的。花費(fèi)大量的努力去使得各個(gè)新的數(shù)據(jù)源運(yùn)轉(zhuǎn)起來(lái),使得數(shù)據(jù)覆蓋度完整不是一件容易的事情。
我們正在推行的,為每個(gè)數(shù)據(jù)源和目標(biāo)增建客戶(hù)化數(shù)據(jù)加載,這種方式很顯然是不可行的。我們有大量的數(shù)據(jù)系統(tǒng)和數(shù)據(jù)倉(cāng)庫(kù)。把這些系統(tǒng)和倉(cāng)庫(kù)聯(lián)系起來(lái),就會(huì)導(dǎo)致任意一對(duì)系統(tǒng)會(huì)產(chǎn)生如下所示的客戶(hù)化通道。
需要注意的是:數(shù)據(jù)是雙向流動(dòng)的:例如許多系統(tǒng)諸如數(shù)據(jù)庫(kù)和Hadoop既是數(shù)據(jù)轉(zhuǎn)化的來(lái)源又是數(shù)據(jù)轉(zhuǎn)化的目的地。這就意味著我們我們不必為每個(gè)系統(tǒng)建立兩個(gè)通道:一個(gè)用于數(shù)據(jù)輸入,一個(gè)用于數(shù)據(jù)輸出。
這顯然需要一大群人,而且也不具有可操作性。隨著我們接近完全連接,最終我們將有差不多O(N2)條管道。
替代的,我們需要像這樣通用的東西:
我們需要盡可能的將每個(gè)消費(fèi)者與數(shù)據(jù)源隔離。理想情形下,它們應(yīng)該只與一個(gè)單獨(dú)的數(shù)據(jù)倉(cāng)庫(kù)集成,并由此讓他們能訪問(wèn)到所有東西。
這個(gè)思想是增加一個(gè)新的數(shù)據(jù)系統(tǒng)——或者它是一個(gè)數(shù)據(jù)源或者它是一個(gè)數(shù)據(jù)目的地——讓集成工作只需連接到一個(gè)單獨(dú)的管道,而無(wú)需連接到每個(gè)數(shù)據(jù)消費(fèi)方。
這種經(jīng)歷使得我關(guān)注創(chuàng)建Kafka來(lái)關(guān)聯(lián)我們?cè)谙⑾到y(tǒng)所見(jiàn)的與數(shù)據(jù)庫(kù)和分布式系統(tǒng)內(nèi)核所發(fā)布的日志。我們希望一些實(shí)體作為中心的通道,首先用于所有的活動(dòng)數(shù)據(jù),逐步的擴(kuò)展到其他用途,例如Hadoop外的數(shù)據(jù)實(shí)施,數(shù)據(jù)監(jiān)控等。
在相當(dāng)長(zhǎng)的時(shí)間內(nèi),Kafka是獨(dú)一無(wú)二的底層產(chǎn)品,它既不是數(shù)據(jù)庫(kù),也不是日志文件收集系統(tǒng),更不是傳統(tǒng)的消息系統(tǒng)。但是最近Amazon提供了非常類(lèi)似Kafka的服務(wù),稱(chēng)之為Kinesis.相似度包括了分片處理的方式,數(shù)據(jù)的保持,甚至包括在Kafka API中,有點(diǎn)特別的高端和低端消費(fèi)者分類(lèi)。我很開(kāi)心看到這些,這表明了你已經(jīng)創(chuàng)建了很好的底層協(xié)議,AWS已經(jīng)把它作為服務(wù)提供。他們對(duì)此的期待與我所描述的吻合:通道聯(lián)通了所有的分布式系統(tǒng),諸如DynamoDB, RedShift, S3等,它同時(shí)作為使用EC2進(jìn)行分布式流處理的基礎(chǔ)。
與ETL和數(shù)據(jù)倉(cāng)庫(kù)的關(guān)系
我們?cè)賮?lái)聊聊數(shù)據(jù)倉(cāng)庫(kù)。數(shù)據(jù)倉(cāng)庫(kù)是清洗和歸一數(shù)據(jù)結(jié)構(gòu)用于支撐數(shù)據(jù)分析的倉(cāng)庫(kù)。這是一個(gè)偉大的理念。對(duì)不熟悉數(shù)據(jù)倉(cāng)庫(kù)概念的人來(lái)說(shuō),數(shù)據(jù)倉(cāng)庫(kù)方法論包括了:周期性的從數(shù)據(jù)源抽取數(shù)據(jù),把它們轉(zhuǎn)化為可理解的形式,然后把它導(dǎo)入中心數(shù)據(jù)倉(cāng)庫(kù)。對(duì)于數(shù)據(jù)集中分析和處理,擁有高度集中的位置存放全部數(shù)據(jù)的原始副本是非常寶貴的資產(chǎn)。在高層級(jí)上,也許你抽取和加載數(shù)據(jù)的順序略微調(diào)整,這個(gè)方法論不會(huì)有太多變化,無(wú)論你使用傳統(tǒng)的數(shù)據(jù)倉(cāng)庫(kù)Oracle還是Teradata或者Hadoop。
數(shù)據(jù)倉(cāng)庫(kù)是極其重要的資產(chǎn),它包含了原始的和規(guī)整的數(shù)據(jù),但是實(shí)現(xiàn)此目標(biāo)的機(jī)制有點(diǎn)過(guò)時(shí)了。
對(duì)以數(shù)據(jù)為中心的組織關(guān)鍵問(wèn)題是把原始的歸一數(shù)據(jù)聯(lián)結(jié)到數(shù)據(jù)倉(cāng)庫(kù)。數(shù)據(jù)倉(cāng)庫(kù)是批處理的基礎(chǔ)查詢(xún):它們適用于各類(lèi)報(bào)表和臨時(shí)性分析,特別是當(dāng)查詢(xún)包含了簡(jiǎn)單的計(jì)數(shù)、聚合和過(guò)濾。但是如果一個(gè)批處理系統(tǒng)僅僅包含了原始的完整的數(shù)據(jù)的數(shù)據(jù)倉(cāng)庫(kù),這就意味著這些數(shù)據(jù)對(duì)于實(shí)時(shí)數(shù)據(jù)處理、搜索索引和系統(tǒng)監(jiān)控等實(shí)時(shí)的查詢(xún)是不可用的。
依我之見(jiàn),ETL包括兩件事:首先,它是抽取和數(shù)據(jù)清洗過(guò)程–特別是釋放被鎖在組織的各類(lèi)系統(tǒng)中的數(shù)據(jù),移除系統(tǒng)專(zhuān)有的無(wú)用物。第二,依照數(shù)據(jù)倉(cāng)庫(kù)的查詢(xún)重構(gòu)數(shù)據(jù)。例如使其符合關(guān)系數(shù)據(jù)庫(kù)類(lèi)型系統(tǒng),強(qiáng)制使用星號(hào)、雪花型模式,或者分解為高性能的柱狀格式等。合并這兩者是有困難的。這些規(guī)整的數(shù)據(jù)集應(yīng)當(dāng)可以在實(shí)時(shí)或低時(shí)延處理中可用,也可以在其它實(shí)施存儲(chǔ)系統(tǒng)索引。
在我看來(lái),正是因?yàn)檫@個(gè)原因有了額外好處:使得數(shù)據(jù)倉(cāng)庫(kù)ETL更具了組織級(jí)的規(guī)模。數(shù)據(jù)倉(cāng)庫(kù)的精典問(wèn)題是數(shù)據(jù)倉(cāng)庫(kù)負(fù)責(zé)收集和清洗組織中各個(gè)組所生成的全部數(shù)據(jù)。各組織的動(dòng)機(jī)是不同的,數(shù)據(jù)的生產(chǎn)者并不知曉在數(shù)據(jù)倉(cāng)庫(kù)中數(shù)據(jù)的使用情況,最終產(chǎn)生的數(shù)據(jù)很難抽取,或者需要花費(fèi)規(guī)?;霓D(zhuǎn)化才可以轉(zhuǎn)化為可用的形式。當(dāng)然, 中心團(tuán)隊(duì)不可能恰到好處的掌握規(guī)模,使得這規(guī)模剛好與組織中其它團(tuán)隊(duì)相匹配,因此數(shù)據(jù)的覆蓋率常常差別很大,數(shù)據(jù)流是脆弱的同時(shí)變更是緩慢的。
較好的方法是有一個(gè)中心通道,日志和用于增加數(shù)據(jù)的定義良好的API。與通道集成的且提供良好的結(jié)構(gòu)化的數(shù)據(jù)文件的職責(zé)依賴(lài)于數(shù)據(jù)的生產(chǎn)者所生成的數(shù)據(jù)文件。這意味著在設(shè)計(jì)和實(shí)施其它系統(tǒng)時(shí)應(yīng)當(dāng)考慮數(shù)據(jù)的輸出以及輸出的數(shù)據(jù)如何轉(zhuǎn)化為結(jié)構(gòu)良好的形式并傳遞給中心通道。增加新的存儲(chǔ)系統(tǒng)倒是不必因?yàn)閿?shù)據(jù)倉(cāng)庫(kù)團(tuán)隊(duì)有一個(gè)中心結(jié)點(diǎn)需要集成而關(guān)注數(shù)據(jù)倉(cāng)庫(kù)團(tuán)隊(duì)。數(shù)據(jù)倉(cāng)庫(kù)團(tuán)隊(duì)僅需處理簡(jiǎn)單的問(wèn)題,例如從中心日志中加載結(jié)構(gòu)化的數(shù)據(jù),向其它周邊系統(tǒng)實(shí)施個(gè)性化的數(shù)據(jù)轉(zhuǎn)化等。
如圖所示:當(dāng)考慮在傳統(tǒng)的數(shù)據(jù)倉(cāng)庫(kù)之外增加額外的數(shù)據(jù)系統(tǒng)時(shí),組織結(jié)構(gòu)的可擴(kuò)展性顯得尤為重要。例如,可以考慮為組織的完整的數(shù)據(jù)集提供搜索功能?;蛘咛峁┒?jí)的數(shù)據(jù)流監(jiān)控實(shí)時(shí)數(shù)據(jù)趨勢(shì)和告警。無(wú)論是這兩者中的哪一個(gè),傳統(tǒng)的數(shù)據(jù)倉(cāng)庫(kù)架構(gòu)甚至于Hadoop聚簇都不再適用。更糟的是,ETL的流程通道的目的就是支持?jǐn)?shù)據(jù)加載,然而ETL似乎無(wú)法輸出到其它的各個(gè)系統(tǒng),也無(wú)法通過(guò)引導(dǎo)程序,使得這些外圍的系統(tǒng)的各個(gè)架構(gòu)成為適用于數(shù)據(jù)倉(cāng)庫(kù)的重要資產(chǎn)。這就不難解釋為什么組織很難輕松的使用它的全部數(shù)據(jù)。反之,如果組織已建立起了一套標(biāo)準(zhǔn)的、結(jié)構(gòu)良好的數(shù)據(jù),那么任何新的系統(tǒng)要使用這些數(shù)據(jù)僅僅需要與通道進(jìn)行簡(jiǎn)單的集成就可以實(shí)現(xiàn)。
這種架構(gòu)引出了數(shù)據(jù)清理和轉(zhuǎn)化在哪個(gè)階段進(jìn)行的不同觀點(diǎn):
由數(shù)據(jù)的生產(chǎn)者在把數(shù)據(jù)增加到公司全局日志之前。
在日志的實(shí)時(shí)轉(zhuǎn)化階段進(jìn)行,這將會(huì)產(chǎn)生一個(gè)新的轉(zhuǎn)化日志。
在向目標(biāo)系統(tǒng)加載數(shù)據(jù)時(shí),做為加載過(guò)程的一部分進(jìn)行。
理想的模形是:由數(shù)據(jù)的生產(chǎn)者在把數(shù)據(jù)發(fā)布到日志之前對(duì)數(shù)據(jù)進(jìn)行清理。這樣可以確保數(shù)據(jù)的權(quán)威性,不需要維護(hù)其它的遺留物例如為數(shù)據(jù)產(chǎn)生的特殊處理代碼或者維護(hù)這些數(shù)據(jù)的其它的存儲(chǔ)系統(tǒng)。這些細(xì)節(jié)應(yīng)當(dāng)由產(chǎn)生數(shù)據(jù)的團(tuán)隊(duì)來(lái)處理,因?yàn)樗麄冏盍私馑麄冏约旱臄?shù)據(jù)。這個(gè)階段所使用的任何邏輯都應(yīng)該是無(wú)損的和可逆的。
任何可以實(shí)時(shí)完成的增值轉(zhuǎn)化類(lèi)型都應(yīng)當(dāng)基于原始日志進(jìn)行后期處理。這一過(guò)程包括了事件數(shù)據(jù)的會(huì)話(huà)流程,或者增加大眾感興趣的衍生字段。原始的日志仍然是可用的,但是這種實(shí)時(shí)處理產(chǎn)生的衍生日志包含了參數(shù)數(shù)據(jù)。
最終,只有針對(duì)目標(biāo)系統(tǒng)的聚合需要做了加載流程的一部分。它包括了把數(shù)據(jù)轉(zhuǎn)化成特定的星型或者雪花狀模式,從而用于數(shù)據(jù)倉(cāng)庫(kù)的分析和報(bào)表。因?yàn)樵谶@個(gè)階段,大部分自然的映射到傳統(tǒng)的ETL流程中,而現(xiàn)在它是在一個(gè)更加干凈和規(guī)整的數(shù)據(jù)流集在進(jìn)行的,它將會(huì)更加的簡(jiǎn)單。
日志文件和事件
我們?cè)賮?lái)聊聊這種架構(gòu)的優(yōu)勢(shì):它支持解耦和事件驅(qū)動(dòng)的系統(tǒng)。
在網(wǎng)絡(luò)行業(yè)取得活動(dòng)數(shù)據(jù)的典型方法是把它記為文本形式的日志,這些文本文件是可分解進(jìn)入數(shù)據(jù)倉(cāng)庫(kù)或者Hadoop,用于聚合和查詢(xún)處理的。由此產(chǎn)生的問(wèn)題與所有批處理的ETL的問(wèn)題是相同的:它耦合了數(shù)據(jù)流進(jìn)入數(shù)據(jù)倉(cāng)庫(kù)系統(tǒng)的能力和流程的調(diào)度。
在LinkedIn中,我們已經(jīng)以中心日志的方式構(gòu)建了事件數(shù)據(jù)處理。我們正在使用Kafka做為中心的、多訂閱者事件日志。我們已經(jīng)定義了數(shù)百種事件類(lèi)型,每種類(lèi)型都會(huì)捕獲用于特定類(lèi)型動(dòng)作的獨(dú)特的屬性。這將會(huì)覆蓋包括頁(yè)面視圖、表達(dá)式、搜索以及服務(wù)調(diào)用、應(yīng)用異常等方方面面。
為了進(jìn)一步理解這一優(yōu)勢(shì):設(shè)想一個(gè)簡(jiǎn)單的事務(wù)–在日志頁(yè)面顯示已發(fā)布的日志。這個(gè)日志頁(yè)面應(yīng)當(dāng)只包括顯示日志所需要的邏輯。然而,在相當(dāng)多的動(dòng)態(tài)站點(diǎn)中,日志頁(yè)面常常變的添加了很多與顯示日志無(wú)關(guān)的邏輯。例如,我們將對(duì)如下的系統(tǒng)進(jìn)行集成:
需要把數(shù)據(jù)傳送到Hadoop和數(shù)據(jù)倉(cāng)庫(kù)中用于離線(xiàn)數(shù)據(jù)處理。
需要對(duì)視圖進(jìn)行統(tǒng)計(jì),確保視圖訂閱者不會(huì)攻擊一些內(nèi)容片段。
需要聚合這些視圖,視圖將用于作業(yè)發(fā)布者的分析頁(yè)面顯示。
需要記錄視圖以確保我們?yōu)樽鳂I(yè)推薦的使用者提供了恰當(dāng)?shù)挠∠蟾采w,我們不想一次次的重復(fù)同樣的事情。
推薦系統(tǒng)需要記錄日志用于正確的跟蹤作業(yè)的普及度。
等等。
不久,簡(jiǎn)單的作業(yè)顯示變得相當(dāng)?shù)膹?fù)雜。我們?cè)黾恿俗鳂I(yè)顯示的其它終端–移動(dòng)終端應(yīng)用等–這些邏輯必須繼續(xù)存在,復(fù)雜度不斷的增加。更糟的是我們需要與之做接口交互的系統(tǒng)現(xiàn)在是錯(cuò)綜復(fù)雜的–在為顯示日作業(yè)而工作的工程師們需要知曉多個(gè)其它系統(tǒng)和它們的特征,才可以確保它們被正確的集成了。這僅僅是問(wèn)題的簡(jiǎn)單版本,真實(shí)的的應(yīng)用系統(tǒng)只會(huì)更加的復(fù)雜。
“事件驅(qū)動(dòng)”的模式提供了一種簡(jiǎn)化這類(lèi)問(wèn)題的機(jī)制。作業(yè)顯示頁(yè)面現(xiàn)在只顯示作業(yè)并記錄與正在顯示的作業(yè),作業(yè)訂閱者相關(guān)的其它屬性,和其它與作業(yè)顯示相關(guān)的其它有價(jià)值的屬性。每個(gè)與此相關(guān)的其它系統(tǒng)諸如推薦系統(tǒng)、安全系統(tǒng)、作業(yè)推送分析系統(tǒng)和數(shù)據(jù)倉(cāng)庫(kù),所有這些只是訂閱種子文件,并進(jìn)行它們的操作。顯示代碼并不需要關(guān)注其它的系統(tǒng),也不需要因?yàn)樵黾恿藬?shù)據(jù)的消費(fèi)者而相應(yīng)的進(jìn)行變更。
構(gòu)建可伸縮的日志
當(dāng)然,把發(fā)布者與訂閱者分離不再是什么新鮮事了。但是如果你想要確保提交日志的行為就像多個(gè)訂閱者實(shí)時(shí)的分類(lèi)日志那樣記錄網(wǎng)站發(fā)生的每件事時(shí),可擴(kuò)展性就會(huì)成為你所面臨的首要挑戰(zhàn)。如果我們不能創(chuàng)建快速、高性?xún)r(jià)比和可擴(kuò)展性靈活的日志以滿(mǎn)足實(shí)際的可擴(kuò)展需求,把日志做為統(tǒng)一的集成機(jī)制不再是美好的想像,
人們普遍認(rèn)為分布式日志是緩慢的、重量經(jīng)的概念(并且通常會(huì)把它僅僅與“原數(shù)據(jù)”類(lèi)型的使用聯(lián)系起來(lái),對(duì)于這類(lèi)使用Zookeeper可以適用)。但是深入實(shí)現(xiàn)并重點(diǎn)關(guān)注分類(lèi)記錄大規(guī)模的數(shù)據(jù)流,這種需求是不切實(shí)際的。在LinkedIn, 我們現(xiàn)在每天通過(guò)Kafka運(yùn)行著超過(guò)600億個(gè)不同的消息寫(xiě)入點(diǎn)(如果統(tǒng)計(jì)鏡相與數(shù)據(jù)中心之間的寫(xiě)入,那么這個(gè)數(shù)字會(huì)是數(shù)千億。)
我們?cè)贙afk中使用了一些小技巧來(lái)支持這種可擴(kuò)展性:
日志分片
通過(guò)批處理讀出和寫(xiě)入優(yōu)化吞吐力
規(guī)避無(wú)用的數(shù)據(jù)復(fù)制。
為了確保水平可擴(kuò)展性,我們把日志進(jìn)行切片:
每個(gè)切片都是一篇有序的日志,但是各片之間沒(méi)有全局的次序(這個(gè)有別于你可能包含在消息中的掛鐘時(shí)間)。把消息分配到特定的日志片段這是由寫(xiě)入者控制的,大部分使用者會(huì)通過(guò)用戶(hù)ID等鍵值來(lái)進(jìn)行分片。分片可以把日志追加到不存在協(xié)作的片段之間,也可以使系統(tǒng)的吞吐量與Kafka聚簇大小成線(xiàn)性比例關(guān)系。
每個(gè)分片都是通過(guò)可配置數(shù)量的復(fù)制品復(fù)制的,每個(gè)復(fù)制品都有分片的一份完全一致的拷貝。無(wú)論何時(shí),它們中的任一個(gè)都可以做為主分片,如果主分片出錯(cuò)了,任何一個(gè)復(fù)制品都可以接管并做為主分片。
缺少跨分片的全局順序是這個(gè)機(jī)制的局限性,但是我們不認(rèn)為它是最主要的。事實(shí)上,與日志的交互主要來(lái)源于成百上千個(gè)不同的流程,以致于對(duì)于它們的行為排一個(gè)總體的順序是沒(méi)什么意義的。相反,我們可以確保的是我們提供的每個(gè)分片都是按順序保留的。Kafka保證了追加到由單一發(fā)送者送出的特定分片會(huì)按照發(fā)送的順序依次處理。
日志,就像文件系統(tǒng)一樣,是容易優(yōu)化成線(xiàn)性可讀可寫(xiě)的樣式的。日志可以把小的讀入和寫(xiě)出組合成大的、高吞吐量的操作。Kafka一直至立于實(shí)現(xiàn)這一優(yōu)化目標(biāo)。批處理可以發(fā)生在由客戶(hù)端向服務(wù)器端發(fā)送數(shù)據(jù)、寫(xiě)入磁盤(pán);在服務(wù)器各端之間復(fù)制;數(shù)據(jù)傳遞給消費(fèi)者和確認(rèn)提交數(shù)據(jù)等諸多環(huán)節(jié)。
最終,Kafka使用簡(jiǎn)單的二進(jìn)制形式維護(hù)內(nèi)存日志,磁盤(pán)日志和網(wǎng)絡(luò)數(shù)據(jù)傳送。這使得我們可以使用包括“0數(shù)據(jù)復(fù)制傳送”在內(nèi)的大量的優(yōu)化機(jī)制。
這些優(yōu)化的積累效應(yīng)是你常常進(jìn)行的寫(xiě)出和讀入數(shù)據(jù)的操作可以在磁盤(pán)和網(wǎng)絡(luò)上得到支持,甚至于維護(hù)內(nèi)存以外的大量數(shù)據(jù)集。
到此為止,我只是描述從端到端數(shù)據(jù)復(fù)制的理想機(jī)制。但是在存儲(chǔ)系統(tǒng)中搬運(yùn)字節(jié)不是所要講述內(nèi)容的全部。最終我們發(fā)現(xiàn)日志是流的另一種說(shuō)法,日志是流處理的核心。
但是,等等,什么是流處理呢?
如果你是90年代晚期或者21世紀(jì)初數(shù)據(jù)庫(kù)文化或者數(shù)據(jù)基礎(chǔ)架構(gòu)產(chǎn)品的愛(ài)好者,那么你就可能會(huì)把流處理與建創(chuàng)SQL引擎或者創(chuàng)建“箱子和箭頭”接口用于事件驅(qū)動(dòng)的處理等聯(lián)系起來(lái)。
如果你關(guān)注開(kāi)源數(shù)據(jù)庫(kù)系統(tǒng)的大量出現(xiàn),你就可能把流處理和一些開(kāi)源數(shù)據(jù)庫(kù)系統(tǒng)關(guān)聯(lián)起來(lái),這些系統(tǒng)包括了:Storm,Akka,S4和Samza.但是大部分人會(huì)把這些系統(tǒng)作為異步消息處理系統(tǒng),這些系統(tǒng)與支持群集的遠(yuǎn)程過(guò)程調(diào)用層的應(yīng)用沒(méi)什么差別(而事實(shí)上在開(kāi)源數(shù)據(jù)庫(kù)系統(tǒng)領(lǐng)域某些方面確實(shí)如此)。
這些視圖都有一些局限性。流處理與SQL是無(wú)關(guān)的。它也局限于實(shí)時(shí)流處理。不存在內(nèi)在的原因限制你不能處理昨天的或者一個(gè)月之前的流數(shù)據(jù),且使用多種不同的語(yǔ)言表達(dá)計(jì)算。
我把流處理視為更廣泛的概念:持續(xù)數(shù)據(jù)流處理的基礎(chǔ)架構(gòu)。我認(rèn)為計(jì)算模型可以像MapReduce或者分布式處理架構(gòu)一樣普遍,但是有能力處理低時(shí)延的結(jié)果。
處理模型的實(shí)時(shí)驅(qū)動(dòng)是數(shù)據(jù)收集方法。成批收集的數(shù)據(jù)是分批處理的。數(shù)據(jù)是不斷收集的,它也是按順序不斷處理的。
美國(guó)的統(tǒng)計(jì)調(diào)查就是成批收集數(shù)據(jù)的良好典范。統(tǒng)計(jì)調(diào)查周期性的開(kāi)展,通過(guò)挨門(mén)挨戶(hù)的走訪,使用蠻力發(fā)現(xiàn)和統(tǒng)計(jì)美國(guó)的公民信息。1790年統(tǒng)計(jì)調(diào)查剛剛開(kāi)始時(shí)這種方式是奏效的。那時(shí)的數(shù)據(jù)收集是批處理的,它包括了騎著馬悠閑的行進(jìn),把信息寫(xiě)在紙上,然后把成批的記錄傳送到人們統(tǒng)計(jì)數(shù)據(jù)的中心站點(diǎn)?,F(xiàn)在,在描述這個(gè)統(tǒng)計(jì)過(guò)程時(shí),人們立即會(huì)想到為什么我們不保留出生和死亡的記錄,這樣就可以產(chǎn)生人口統(tǒng)計(jì)信息這些信息或是持續(xù)的或者是其它維度的。
這是一個(gè)極端的例子,但是大量的數(shù)據(jù)傳送處理仍然依賴(lài)于周期性的轉(zhuǎn)儲(chǔ),批量轉(zhuǎn)化和集成。處理大容量轉(zhuǎn)儲(chǔ)的唯一方法就是批量的處理。但是隨著這些批處理被持續(xù)的供給所取代,人們自然而然的開(kāi)始不間斷的處理以平滑的處理所需資源并且消除延遲。
例如LinkedIn幾乎沒(méi)有批量數(shù)據(jù)收集。大部分的數(shù)據(jù)或者是活動(dòng)數(shù)據(jù)或者是數(shù)據(jù)庫(kù)變更,這兩者都是不間斷發(fā)生的。事實(shí)上,你可以想到的任何商業(yè),正如:Jack Bauer告訴我們的,低層的機(jī)制都是實(shí)時(shí)發(fā)生的不間斷的流程事件。數(shù)據(jù)是成批收集的,它總是會(huì)依賴(lài)于一些人為的步驟,或者缺少數(shù)字化或者是一些自動(dòng)化的非數(shù)字化流程處理的遺留信息。當(dāng)傳送和處理這些數(shù)據(jù)的機(jī)制是郵件或者人工的處理時(shí),這一過(guò)程是非常緩慢的。首輪自動(dòng)化總是保持著最初的處理形式,它常常會(huì)持續(xù)相當(dāng)長(zhǎng)的時(shí)間。
每天運(yùn)行的批量處理作業(yè)常常是模擬了一種一天的窗口大小的不間斷計(jì)算。當(dāng)然,低層的數(shù)據(jù)也經(jīng)常變化。在LinkedIn,這些是司空見(jiàn)貫的,并且使得它們?cè)贖adoop運(yùn)轉(zhuǎn)的機(jī)制是有技巧的,所以我們實(shí)施了一整套管理增量的Hadoop工作流的架構(gòu)。
由此看來(lái),對(duì)于流處理可以有不同的觀點(diǎn)。流處理包括了在底層數(shù)據(jù)處理的時(shí)間概念,它不需要數(shù)據(jù)的靜態(tài)快照,它可以產(chǎn)生用戶(hù)可控頻率的輸出,而不用等待數(shù)據(jù)集的全部到達(dá)。從這個(gè)角度上講,流處理就是廣義上的批處理,隨著實(shí)時(shí)數(shù)據(jù)的流行,會(huì)兒更加普遍。
這就是為什么從傳統(tǒng)的視角看來(lái)流處理是利基應(yīng)用。我個(gè)人認(rèn)為最大的原因是缺少實(shí)時(shí)數(shù)據(jù)收集使得不間斷的處理成為了學(xué)術(shù)性的概念。
我想缺少實(shí)時(shí)數(shù)據(jù)收集就像是商用流處理系統(tǒng)注定的命運(yùn)。他們的客戶(hù)仍然需要處理面向文件的、每日批量處理ETL和數(shù)據(jù)集成。公司建設(shè)流處理系統(tǒng)關(guān)注的是提供附著在實(shí)時(shí)數(shù)據(jù)流的處理引擎,但是最終當(dāng)時(shí)極少數(shù)人真正使用了實(shí)時(shí)數(shù)據(jù)流。事實(shí)上,在我在LinkedIn工作的初期,有一家公司試圖把一個(gè)非常棒的流處理系統(tǒng)銷(xiāo)售給我們,但是因?yàn)楫?dāng)時(shí)我們的全部數(shù)據(jù)都按小時(shí)收集在的文件里,當(dāng)時(shí)我們提出的最好的應(yīng)用就是在每小時(shí)的最后把這些文件輸入到流處理系統(tǒng)中。他們注意到這是一個(gè)普遍性的問(wèn)題。這些異常證明了如下規(guī)則:流處理系統(tǒng)要滿(mǎn)足的重要商業(yè)目標(biāo)之一是:財(cái)務(wù), 它是實(shí)時(shí)數(shù)據(jù)流已具備的基準(zhǔn),并且流處理已經(jīng)成為了瓶頸。
甚至于在一個(gè)健康的批處理系統(tǒng)中,流處理作為一種基礎(chǔ)架構(gòu)的實(shí)際應(yīng)用能力是相當(dāng)廣泛的。它跨越了實(shí)時(shí)數(shù)據(jù)請(qǐng)求-應(yīng)答服務(wù)和離線(xiàn)批量處理之間的鴻溝?,F(xiàn)在的互聯(lián)網(wǎng)公司,大約25%的代碼可以劃分到這個(gè)類(lèi)型中。
最終這些日志解決了流處理中絕大部分關(guān)鍵的技術(shù)問(wèn)題。在我看來(lái),它所解決的最大的問(wèn)題是它使得多訂閱者可以獲得實(shí)時(shí)數(shù)據(jù)。對(duì)這些技術(shù)細(xì)節(jié)感興趣的朋友,我們可以用開(kāi)源的Samza,它是基于這些理念建設(shè)的一個(gè)流處理系統(tǒng)。這些應(yīng)用的更多技術(shù)細(xì)節(jié)我們?cè)诖宋臋n中有詳細(xì)的描述。
數(shù)據(jù)流圖
流處理最有趣的角度是它與流處理系統(tǒng)內(nèi)部無(wú)關(guān),但是與之密切相關(guān)的是如何擴(kuò)展了我們談到的早期數(shù)據(jù)集成的數(shù)據(jù)獲取的理念。我們主要討論了基礎(chǔ)數(shù)據(jù)的獲取或日志–事件和各類(lèi)系統(tǒng)執(zhí)行中產(chǎn)生的數(shù)據(jù)等。但是流處理允許我們包括了計(jì)算其它數(shù)據(jù)的數(shù)據(jù)。這些衍生的數(shù)據(jù)在消費(fèi)者看來(lái)與他們計(jì)算的原始數(shù)據(jù)沒(méi)什么差別。這些衍生的數(shù)據(jù)可以按任意的復(fù)雜度進(jìn)行壓縮。
讓我們?cè)偕钊胍徊?。我們的目?biāo)是:流處理作業(yè)可以讀取任意的日志并把日志寫(xiě)入到日志或者其它的系統(tǒng)中。他們用于輸入輸出的日志把這些處理關(guān)聯(lián)到一組處理過(guò)程中。事實(shí)上,使用這種樣式的集中日志,你可以把組織全部的數(shù)據(jù)抓取、轉(zhuǎn)化和工作流看成是一系列的日志和寫(xiě)入它們的處理過(guò)程。
流處理器根本不需要理想的框架:它可能是讀寫(xiě)日志的任何處理器或者處理器集合,但是額外的基礎(chǔ)設(shè)施和輔助可以提供幫助管理處理代碼。
日志集成的目標(biāo)是雙重的:
首先,它確保每個(gè)數(shù)據(jù)集都有多個(gè)訂閱者和有序的。讓我們回顧一下?tīng)顟B(tài)復(fù)制原則來(lái)記住順序的重要性。為了使這個(gè)更加具體,設(shè)想一下從數(shù)據(jù)庫(kù)中更新數(shù)據(jù)流–如果在處理過(guò)程中我們把對(duì)同一記錄的兩次更新重新排序,可能會(huì)產(chǎn)生錯(cuò)誤的輸出。 TCP之類(lèi)的鏈接僅僅局限于單一的點(diǎn)對(duì)點(diǎn)鏈接,這一順序的持久性要優(yōu)于TCP之類(lèi)的鏈接,它可以在流程處理失敗和重連時(shí)仍然存在。
第二,日志提供了流程的緩沖。這是非?;A(chǔ)的。如果處理流程是非同步的,那么上行生成流數(shù)據(jù)的作業(yè)比下行消費(fèi)流數(shù)據(jù)的作業(yè)運(yùn)行的更快。這將會(huì)導(dǎo)致處理流程阻塞,或者緩沖數(shù)據(jù),或者丟棄數(shù)據(jù)。丟棄數(shù)據(jù)并不是可行的方法,阻塞將會(huì)導(dǎo)致整個(gè)流程圖立即停止。 日志實(shí)際上是一個(gè)非常大的緩沖,它允許流程重啟或者停止但不會(huì)影響流程圖其它部分的處理速度。如果要把數(shù)據(jù)流擴(kuò)展到更大規(guī)模的組織,如果處理作業(yè)是由多個(gè)不同的團(tuán)隊(duì)提供的,這種隔離性是極其重的。我們不能容忍一個(gè)錯(cuò)誤的作業(yè)引發(fā)后臺(tái)的壓力,這種壓力會(huì)使得整個(gè)處理流程停止。
Storm和Sama這兩者都是按非同步方式設(shè)計(jì)的,可以使用Kafka或者其它類(lèi)似的系統(tǒng)作為它們的日志。
有狀態(tài)的實(shí)時(shí)流處理
一些實(shí)時(shí)流處理在轉(zhuǎn)化時(shí)是無(wú)狀態(tài)的記錄。在流處理中大部分的應(yīng)用會(huì)是相當(dāng)復(fù)雜的統(tǒng)計(jì)、聚合、不同窗口之間的關(guān)聯(lián)。例如有時(shí)人們想擴(kuò)大包含用戶(hù)操作信息的事件流(一系列的單擊動(dòng)作)–實(shí)際上關(guān)聯(lián)了用戶(hù)的單擊動(dòng)作流與用戶(hù)的賬戶(hù)信息數(shù)據(jù)庫(kù)。不變的是這類(lèi)流程最終會(huì)需要由處理器維護(hù)的一些狀態(tài)信息。例如數(shù)據(jù)統(tǒng)計(jì)時(shí),你需要統(tǒng)計(jì)到目前為止需要維護(hù)的計(jì)數(shù)器。如果處理器本身失敗了,如何正確的維護(hù)這些狀態(tài)信息呢?
最簡(jiǎn)單的替換方案是把這些狀態(tài)信息保存在內(nèi)存中。但是如果流程崩潰,它就會(huì)丟失中間狀態(tài)。如果狀態(tài)是按窗口維護(hù)的,流程就會(huì)回退到日志中窗口開(kāi)始的時(shí)間點(diǎn)上。但是,如果統(tǒng)計(jì)是按小時(shí)進(jìn)行的,那么這種方式就會(huì)變得不可行。
另一個(gè)替換方案是簡(jiǎn)單的存儲(chǔ)所有的狀態(tài)信息到遠(yuǎn)程的存儲(chǔ)系統(tǒng),通過(guò)網(wǎng)絡(luò)與這些存儲(chǔ)關(guān)聯(lián)起來(lái)。這種機(jī)制的問(wèn)題是沒(méi)有本地?cái)?shù)據(jù)和大量的網(wǎng)絡(luò)間通信。
我們?nèi)绾沃С痔幚磉^(guò)程可以像表一樣分區(qū)的數(shù)據(jù)呢?
回顧一下關(guān)于表和日志二相性的討論。這一機(jī)制提供了工具把數(shù)據(jù)流轉(zhuǎn)化為與處理過(guò)程協(xié)同定位的表,同時(shí)也提供了這些表的容錯(cuò)處理的機(jī)制。
流處理器可以把它的狀態(tài)保存在本地的表或索引–bdb,或者leveldb,甚至于類(lèi)似于Lucene 或fastbit一樣不常見(jiàn)的索引。這些內(nèi)容存儲(chǔ)在它的輸入流中(或許是使用任意的轉(zhuǎn)化)。生成的變更日志記錄了本地的索引,它允許存儲(chǔ)事件崩潰、重啟等的狀態(tài)信息。流處理提供了通用的機(jī)制用于在本地輸入流數(shù)據(jù)的隨機(jī)索引中保存共同分片的狀態(tài)。
當(dāng)流程運(yùn)行失敗時(shí),它會(huì)從變更日志中恢復(fù)它的索引。每次備份時(shí),日志把本地狀態(tài)轉(zhuǎn)化成一系列的增量記錄。
這種狀態(tài)管理的方法有一個(gè)優(yōu)勢(shì)是把處理器的狀態(tài)也做為日志進(jìn)行維護(hù)。我們可以把這些日志看成與數(shù)據(jù)庫(kù)表相對(duì)應(yīng)的變更日志。事實(shí)上,這些處理器同時(shí)維護(hù)著像共同分片表一樣的表。因?yàn)檫@些狀態(tài)它本身就是日志,其它的處理器可以訂閱它。如果流程處理的目標(biāo)是更新結(jié)點(diǎn)的最后狀態(tài),這種狀態(tài)又是流程的輸出,那么這種方法就顯得尤為重要。
為了數(shù)據(jù)集成,與來(lái)自數(shù)據(jù)庫(kù)的日志關(guān)聯(lián),日志和數(shù)據(jù)庫(kù)表的二象性就更加清晰了。變更日志可以從數(shù)據(jù)庫(kù)中抽取出來(lái),日志可以由不同的流處理器(流處理器用于關(guān)聯(lián)不同的事件流)按不同的方式進(jìn)行索引。
我們可以列舉在Samza中有狀態(tài)流處理管理的更多細(xì)節(jié)和大量實(shí)用的例子。
日志壓縮
當(dāng)然,我們不能奢望保存全部變更的完整日志。除非想要使用無(wú)限空間,日志不可能完全清除。為了澄清它,我們?cè)賮?lái)聊聊Kafka的實(shí)現(xiàn)。在Kafka中,清理有兩種選擇,這取決于數(shù)據(jù)是否包括關(guān)鍵更新和事件數(shù)據(jù)。對(duì)于事件數(shù)據(jù),Kafka支持僅維護(hù)一個(gè)窗口的數(shù)據(jù)。通常,配置需要一些時(shí)間,窗口可以按時(shí)間或空間定義。雖然對(duì)于關(guān)鍵數(shù)據(jù)而言,完整日志的重要特征是你可以重現(xiàn)源系統(tǒng)的狀態(tài)信息,或者在其它的系統(tǒng)重現(xiàn)。
隨著時(shí)間的推移,保持完整的日志會(huì)使用越來(lái)越多的空間,重現(xiàn)所耗費(fèi)的時(shí)間越來(lái)越長(zhǎng)。因些在Kafka中,我們支持不同類(lèi)型的保留。我們移除了廢棄的記錄(這些記錄的主鍵最近更新過(guò))而不是簡(jiǎn)單的丟棄舊日志。我們?nèi)匀槐WC日志包含了源系統(tǒng)的完整備份,但是現(xiàn)在我們不再重現(xiàn)原系統(tǒng)的全部狀態(tài),而是僅僅重現(xiàn)最近的狀態(tài)。我們把這一特征稱(chēng)為日志壓縮。
我們最后要討論的是在線(xiàn)數(shù)據(jù)系統(tǒng)設(shè)計(jì)中日志的角色。
在分布式數(shù)據(jù)庫(kù)數(shù)據(jù)流中日志的角色和在大型組織機(jī)構(gòu)數(shù)據(jù)完整中日志的角色是相似的。在這兩個(gè)應(yīng)用場(chǎng)景中,日志是對(duì)于數(shù)據(jù)源是可靠的,一致的和可恢復(fù)的。組織如果不是一個(gè)復(fù)雜的分布式數(shù)據(jù)系統(tǒng)呢,它究竟是什么?
如果換個(gè)角度,你可以看到把整個(gè)組織系統(tǒng)和數(shù)據(jù)流看做是單一的分布式數(shù)據(jù)系統(tǒng)。你可以把所有的子查詢(xún)系統(tǒng)(諸如Redis, SOLR,Hive表等)看成是數(shù)據(jù)的特定索引。你可以把Storm或Samza一樣的流處理系統(tǒng)看成是發(fā)展良好的觸發(fā)器和視圖具體化機(jī)制。我已經(jīng)注意到,傳統(tǒng)的數(shù)據(jù)庫(kù)管理人員非常喜歡這樣的視圖,因?yàn)樗罱K解釋了這些不同的數(shù)據(jù)系統(tǒng)到底是做什么用的–它們只是不同的索引類(lèi)型而已。
不可否認(rèn)這類(lèi)數(shù)據(jù)庫(kù)系統(tǒng)現(xiàn)在大量的出現(xiàn),但是事實(shí)上,這種復(fù)雜性一直都存在。即使是在關(guān)系數(shù)據(jù)庫(kù)系統(tǒng)的鼎盛時(shí)期,組織中有大量的關(guān)系數(shù)據(jù)庫(kù)系統(tǒng)。或許自大型機(jī)時(shí)代開(kāi)始,所有的數(shù)據(jù)都存儲(chǔ)在相同的位置,真正的集成是根本不存在的。存在多種外在需求,需要把數(shù)據(jù)分解成多個(gè)系統(tǒng),這些外在需求包括:規(guī)模、地理因素、安全性,性能隔離是最常見(jiàn)的因素。這些需求都可以由一個(gè)優(yōu)質(zhì)的系統(tǒng)實(shí)現(xiàn):例如,組織可以使用單一的Hadoop聚簇,它包括了全部的數(shù)據(jù),可以服務(wù)于大型的和多樣性的客戶(hù)。
因此在向分布式系統(tǒng)變遷的過(guò)程中,已經(jīng)存在一種處理數(shù)據(jù)的簡(jiǎn)便的方法:把大量的不同系統(tǒng)的小的實(shí)例聚合成為大的聚簇。許多的系統(tǒng)還不足以支持這一方法:因?yàn)樗鼈儾粔虬踩蛘咝阅芨綦x性得不到保證,或者規(guī)模不符合要求。不過(guò)這些問(wèn)題都是可以解決的。
依我之見(jiàn),不同系統(tǒng)大量出現(xiàn)的原因是建設(shè)分布式數(shù)據(jù)庫(kù)系統(tǒng)很困難。通過(guò)削減到單一的查詢(xún)或者用例,每個(gè)系統(tǒng)都可以把規(guī)模控制到易于實(shí)現(xiàn)的程度。但是運(yùn)行這些系統(tǒng)產(chǎn)生的復(fù)雜度依然很高。
未來(lái)這類(lèi)問(wèn)題可能的發(fā)展趨勢(shì)有三種:
第一種可能是保持現(xiàn)狀:孤立的系統(tǒng)還會(huì)或長(zhǎng)或短的持續(xù)一段時(shí)間。這是因?yàn)榻ㄔO(shè)分布式系統(tǒng)的困難很難克服,或者因?yàn)楣铝⑾到y(tǒng)的獨(dú)特性和便捷性很難達(dá)到?;谶@些原因,數(shù)據(jù)集成的核心問(wèn)題仍然是如何恰當(dāng)?shù)氖褂脭?shù)據(jù)。因此,集成數(shù)據(jù)的外部日志非常的重要。
第二種可能是重構(gòu):具備通用性的單一的系統(tǒng)逐步融合多個(gè)功能形成超極系統(tǒng)。這個(gè)超級(jí)系統(tǒng)表面看起來(lái)類(lèi)似關(guān)系數(shù)據(jù)庫(kù)系統(tǒng),但是在組織中你使用時(shí)最大的不同是你只需要一個(gè)大的系統(tǒng)而不是無(wú)數(shù)個(gè)小系統(tǒng)。在這個(gè)世界里,除了在系統(tǒng)內(nèi)已解決的這個(gè)問(wèn)題不存在什么真正的數(shù)據(jù)集成問(wèn)題。我想這是因?yàn)榻ㄔO(shè)這樣的系統(tǒng)的實(shí)際困難。
雖然另一種可能的結(jié)果對(duì)于工程師來(lái)說(shuō)是很有吸引力的。新一代數(shù)據(jù)庫(kù)系統(tǒng)的特征之一是它們是完全開(kāi)源的。開(kāi)源提供了第三種可能性 :數(shù)據(jù)基礎(chǔ)架構(gòu)不必打包成服務(wù)集或者面向應(yīng)用的系統(tǒng)接口。在Java棧中,你可以看到在一定程度上,這種狀況已經(jīng)發(fā)生了。
分類(lèi)計(jì)價(jià)嗎?
Zookeeper用于處理多個(gè)系統(tǒng)之間的協(xié)調(diào),或許會(huì)從諸如Helix 或者Curator等高級(jí)別的抽象中得到一些幫助。
Mesos和YARN用于處理流程可視化和資源管理。
Lucene和LevelDB等嵌入式類(lèi)庫(kù)做為索引。
Netty,Jetty和Finagle,rest.li等封裝成高級(jí)別的用于處理遠(yuǎn)程通信。
Avro,Protocol Buffers,Thrift和umpteen zillion等其它類(lèi)庫(kù)用于處理序列化。
Kafka和Bookeeper提供支持日志。
如果你把這些堆放在一起,換個(gè)角度看,它有點(diǎn)像是簡(jiǎn)化版的分布式數(shù)據(jù)庫(kù)系統(tǒng)工程。你可以把這些拼裝在一起,創(chuàng)建大量的可能的系統(tǒng)。顯而易見(jiàn),現(xiàn)在探討的不是最終用戶(hù)所關(guān)心的API或者如何實(shí)現(xiàn),而是在不斷多樣化和模塊化的過(guò)程中如何設(shè)計(jì)實(shí)現(xiàn)單一系統(tǒng)的途徑。因?yàn)殡S著可靠的、靈活的模塊的出現(xiàn),實(shí)施分布式系統(tǒng)的時(shí)間周期由年縮減為周,聚合形成大型整體系統(tǒng)的壓力逐步消失。
日志文件在系統(tǒng)結(jié)構(gòu)中的地位
那些提供外部日志的系統(tǒng)如今已允許個(gè)人電腦拋棄他們自身復(fù)雜的日志系統(tǒng)轉(zhuǎn)而使用共享日志。在我看來(lái),日志可以做到以下事情:
通過(guò)對(duì)節(jié)點(diǎn)的并發(fā)更新的排序處理數(shù)據(jù)的一致性(無(wú)論在及時(shí)還是最終情況下)
提供節(jié)點(diǎn)之間的數(shù)據(jù)復(fù)制
提供”commit“語(yǔ)法(只有當(dāng)寫(xiě)入器確保數(shù)據(jù)不會(huì)丟失時(shí)才會(huì)寫(xiě)入)
位系統(tǒng)提供外部的數(shù)據(jù)訂閱資源
提供存儲(chǔ)失敗的復(fù)制操作和引導(dǎo)新的復(fù)制操作的能力
處理節(jié)點(diǎn)間的數(shù)據(jù)平衡
這實(shí)際上是一個(gè)數(shù)據(jù)分發(fā)系統(tǒng)最重要的部分,剩下的大部分內(nèi)容與終端調(diào)用的API和索引策略相關(guān)。這正是不同系統(tǒng)間的差異所在,例如:一個(gè)全文本查詢(xún)語(yǔ)句需要查詢(xún)所有的分區(qū),而一個(gè)主鍵查詢(xún)只需要查詢(xún)負(fù)責(zé)鍵數(shù)據(jù)的單個(gè)節(jié)點(diǎn)就可以了。
下面我們來(lái)看下該系統(tǒng)是如何工作的。系統(tǒng)被分為兩個(gè)邏輯區(qū)域:日志和服務(wù)層。日志按順序捕獲狀態(tài)變化,服務(wù)節(jié)點(diǎn)存儲(chǔ)索引提供查詢(xún)服務(wù)需要的所有信息(鍵-值的存儲(chǔ)可能以B-tree或SSTable的方式進(jìn)行,而搜索系統(tǒng)可能存在與之相反的索引)。寫(xiě)入器可以直接訪問(wèn)日志,盡管需要通過(guò)服務(wù)層代理。在寫(xiě)入日志的時(shí)候會(huì)產(chǎn)生邏輯時(shí)間戳(即log中的索引),如果系統(tǒng)是分段式的,那么就會(huì)產(chǎn)生與段數(shù)目相同數(shù)量的日志文件和服務(wù)節(jié)點(diǎn),這里的數(shù)量和機(jī)器數(shù)量可能會(huì)有較大差距。
服務(wù)節(jié)點(diǎn)訂閱日志信息并將寫(xiě)入器按照日志存儲(chǔ)的順序盡快應(yīng)用到它的本地索引上。
客戶(hù)端只要在查詢(xún)語(yǔ)句中提供對(duì)應(yīng)的寫(xiě)入器的時(shí)間戳,它就可以從任何節(jié)點(diǎn)中獲取”讀寫(xiě)“語(yǔ)義。服務(wù)節(jié)點(diǎn)收到該查詢(xún)語(yǔ)句后會(huì)將其中的時(shí)間戳與自身的索引比較,如果必要,服務(wù)節(jié)點(diǎn)會(huì)延遲請(qǐng)求直到對(duì)應(yīng)時(shí)間的索引建立完畢,以免提供舊數(shù)據(jù)。
服務(wù)節(jié)點(diǎn)或許根本無(wú)需知道”控制“或”投標(biāo)選擇(leader election)“的概念,對(duì)很多簡(jiǎn)單的操作,服務(wù)節(jié)點(diǎn)可以愛(ài)完全脫離領(lǐng)導(dǎo)的情況下提供服務(wù),日志即是信息的來(lái)源。
分發(fā)系統(tǒng)所需要做的其中一個(gè)比較復(fù)雜的工作,就是修復(fù)失敗節(jié)點(diǎn)并移除幾點(diǎn)之間的隔離。保留修復(fù)的數(shù)據(jù)并結(jié)合上各區(qū)域內(nèi)的數(shù)據(jù)快照是一種較為典型的做法,它與保留完整的數(shù)據(jù)備份并從垃圾箱內(nèi)回收日志的做法幾乎等價(jià)。這就使得服務(wù)層簡(jiǎn)單了很多,日志系統(tǒng)也更有針對(duì)性。
有了這個(gè)日志系統(tǒng),你可以訂閱到API,這個(gè)API提供了把ETL提供給其它系統(tǒng)的數(shù)據(jù)內(nèi)容。事實(shí)上,許多系統(tǒng)都可以共享相同的日志同時(shí)提供不同的索引,如下所示:
這樣一個(gè)以日志為中心的系統(tǒng)是如何做到既數(shù)據(jù)流的提供者又同時(shí)加載其它系統(tǒng)的數(shù)據(jù)的呢?因?yàn)榱魈幚砥骷瓤梢韵M(fèi)多個(gè)輸入的數(shù)據(jù)流,隨后又可以通過(guò)其它系統(tǒng)對(duì)數(shù)據(jù)做索引為它們提供服務(wù)。
這個(gè)系統(tǒng)的視圖可以清晰的分解到日志和查詢(xún)API,因?yàn)樗试S你從系統(tǒng)的可用性和一致性角度分解查詢(xún)的特征。這可以幫助我們對(duì)系統(tǒng)進(jìn)行分解,并理解那些并沒(méi)按這種方式設(shè)計(jì)實(shí)施的系統(tǒng)。
雖然Kafka和Bookeeper都是一致性日志,但這不是必須的,也沒(méi)什么意義。你可以輕松的把Dynamo之類(lèi)的數(shù)據(jù)構(gòu)分解為一致性的AP日志和鍵值對(duì)服務(wù)層。這樣的日志使用起來(lái)靈活,因?yàn)樗貍髁伺f消息,像Dynamo一樣,這樣的處理取決于消息的訂閱者。
在很多人看來(lái),在日志中另外保存一份數(shù)據(jù)的完整復(fù)本是一種浪費(fèi)。事實(shí)上,雖然有很多因素使得這件事并不困難。首先,日志可以是一種有效的存儲(chǔ)機(jī)制。我們?cè)贙afka生產(chǎn)環(huán)境的服務(wù)器上存儲(chǔ)了5 TB的數(shù)據(jù)。同時(shí)有許多的服務(wù)系統(tǒng)需要更多的內(nèi)存來(lái)提供有效的數(shù)據(jù)服務(wù),例如文本搜索,它通常是在內(nèi)存中的。服務(wù)系統(tǒng)同樣也需樣硬盤(pán)的優(yōu)化。例如,我們的實(shí)時(shí)數(shù)據(jù)系統(tǒng)或者在內(nèi)存外提供服務(wù)或者使用固態(tài)硬盤(pán)。相反,日志系統(tǒng)只需要線(xiàn)性的讀寫(xiě),因此,它很樂(lè)于使用TB量級(jí)的硬盤(pán)。最終,如上圖所示,由多個(gè)系統(tǒng)提供的數(shù)據(jù),日志的成本分?jǐn)偟蕉鄠€(gè)索引上,這種聚合使得外部日志的成本降到了最低點(diǎn)。
LinkedIn就是使用了這種方式實(shí)現(xiàn)它的多個(gè)實(shí)時(shí)查詢(xún)系統(tǒng)的。這些系統(tǒng)提供了一個(gè)數(shù)據(jù)庫(kù)(使用數(shù)據(jù)總線(xiàn)做為日志摘要,或者從Kafka去掉專(zhuān)用的日志),這些系統(tǒng)在頂層數(shù)據(jù)流上還提供了特殊的分片、索引和查詢(xún)功能。這也是我們實(shí)施搜索、社交網(wǎng)絡(luò)和OLAP查詢(xún)系統(tǒng)的方式。事實(shí)上這種方式是相當(dāng)普遍的:為多個(gè)用于實(shí)時(shí)服務(wù)的服務(wù)系統(tǒng)提供單一的數(shù)據(jù)(這些來(lái)自Hadoop的數(shù)據(jù)或是實(shí)時(shí)的或是衍生的)。這種方式已被證實(shí)是相當(dāng)簡(jiǎn)潔的。這些系統(tǒng)根本不需要外部可寫(xiě)入的API,Kafka和數(shù)據(jù)庫(kù)被用做系統(tǒng)的記錄和變更流,通過(guò)日志你可以查詢(xún)系統(tǒng)。持有特定分片的結(jié)點(diǎn)在本地完成寫(xiě)操作。這些結(jié)點(diǎn)盲目的把日志提供的數(shù)據(jù)轉(zhuǎn)錄到它們自己的存儲(chǔ)空間中。通過(guò)回放上行流日志可以恢復(fù)轉(zhuǎn)錄失敗的結(jié)點(diǎn)。
這些系統(tǒng)的程度則取決于日志的多樣性。一個(gè)完全可靠的系統(tǒng)可以用日志來(lái)對(duì)數(shù)據(jù)分片、存儲(chǔ)結(jié)點(diǎn)、均衡負(fù)載,以及用于數(shù)據(jù)一致性和數(shù)據(jù)復(fù)制等多方面。在這一過(guò)程中,服務(wù)層實(shí)際上只不過(guò)是一種緩存機(jī)制,這種緩存機(jī)制允許直接寫(xiě)入日志的流處理。
到此,相信大家對(duì)“如何理解LinkedIn以日志為中心的大數(shù)據(jù)管理方式”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢(xún),關(guān)注我們,繼續(xù)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。