新聞中心
CAP 定理指出數(shù)據(jù)庫不能同時保證一致性、可用性和分區(qū)容錯性。但是我們不能犧牲分區(qū)容錯性,因此必須在可用性和一致性之間做出權(quán)衡。管理這種權(quán)衡是 NoSQL 運(yùn)行的核心焦點(diǎn)。

創(chuàng)新互聯(lián)長期為上千家客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊從業(yè)經(jīng)驗10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為泰山企業(yè)提供專業(yè)的成都網(wǎng)站建設(shè)、網(wǎng)站設(shè)計,泰山網(wǎng)站改版等技術(shù)服務(wù)。擁有十載豐富建站經(jīng)驗和眾多成功案例,為您定制開發(fā)。
一致性意味著在成功寫入之后,以后的讀取將始終考慮該寫入??捎眯砸馕吨梢噪S時讀取和寫入系統(tǒng)。在分區(qū)期間,只能擁有這些屬性之一。
選擇一致性而不是可用性的系統(tǒng)必須處理一些棘手的問題。當(dāng)數(shù)據(jù)庫不可用時怎么做?可以嘗試緩沖寫入以備后用,但是如果丟失了帶有緩沖區(qū)的機(jī)器,就有丟失這些寫入的風(fēng)險。此外,緩沖寫入可能是一種不一致的形式,因為客戶端認(rèn)為寫入已成功但寫入尚未在數(shù)據(jù)庫中。或者,可以在數(shù)據(jù)庫不可用時將錯誤返回給客戶端。但是,如果曾經(jīng)使用過一種告訴“稍后再試”的產(chǎn)品,就會知道這會是多么令人惱火。
另一種選擇是選擇可用性而不是一致性。這些系統(tǒng)所能提供的最好的一致性保證就是“最終一致性”。如果使用最終一致的數(shù)據(jù)庫,那么有時會讀取到與剛剛寫入的結(jié)果不同的結(jié)果。有時多個訪問者同時讀取同一個密鑰會得到不同的結(jié)果。更新可能不會傳遞到一個值的所有副本,因此最終會得到一些副本獲得一些更新而其他副本獲得不同的更新。一旦檢測到值出現(xiàn)差異,就可以修復(fù)該值。這需要使用矢量時鐘追溯歷史并將更新合并在一起,稱為“讀取修復(fù)”。
在應(yīng)用層維護(hù)最終一致性對開發(fā)人員來說負(fù)擔(dān)太重。讀取修復(fù)代碼極易受到開發(fā)人員錯誤的影響;如果犯了錯誤,錯誤的讀取修復(fù)將給數(shù)據(jù)庫帶來不可逆轉(zhuǎn)的損壞。因此犧牲可用性是有問題的,最終一致性太復(fù)雜以至于無法合理地構(gòu)建應(yīng)用程序。然而,這是唯一的兩個選擇, CAP 定理是自然界的事實(shí),那么還有什么替代方案呢?還有另一種方法。你無法避免 CAP 定理,但你可以隔離它的復(fù)雜性并防止它破壞你對系統(tǒng)進(jìn)行推理的能力。CAP 定理引起的復(fù)雜性是我們?nèi)绾螛?gòu)建數(shù)據(jù)系統(tǒng)的基本問題。有兩個問題特別突出:在數(shù)據(jù)庫中使用可變狀態(tài)以及使用增量算法來更新該狀態(tài)。正是這些問題與 CAP 定理之間的相互作用導(dǎo)致了復(fù)雜性。
在這篇文章中將展示一個系統(tǒng)的設(shè)計,該系統(tǒng)通過防止 CAP 定理通常引起的復(fù)雜性來突破它。CAP 定理是關(guān)于數(shù)據(jù)系統(tǒng)對機(jī)器故障的容錯程度的結(jié)果。然而,有一種比機(jī)器容錯更重要的容錯形式:人為容錯。如果軟件開發(fā)有任何確定性,那就是開發(fā)人員并不完美,錯誤將不可避免地影響生產(chǎn)。我們的數(shù)據(jù)系統(tǒng)必須對寫入錯誤數(shù)據(jù)的錯誤程序具有彈性,而下面將要展示的系統(tǒng)具有盡可能多的人為容錯能力。
這篇文章將挑戰(zhàn)對如何構(gòu)建數(shù)據(jù)系統(tǒng)的基本假設(shè)。但是,通過打破我們當(dāng)前的思維方式并重新想象應(yīng)該如何構(gòu)建數(shù)據(jù)系統(tǒng),出現(xiàn)的是一種比想象的更好的、可擴(kuò)展和健壯的架構(gòu)。
什么是數(shù)據(jù)系統(tǒng)
在我們談?wù)撓到y(tǒng)設(shè)計之前,讓我們首先定義我們試圖解決的問題。數(shù)據(jù)系統(tǒng)的目的是什么?什么是數(shù)據(jù)?除非我們可以用清楚地封裝每個數(shù)據(jù)應(yīng)用程序的定義來回答這些問題,否則我們甚至不需要接近 CAP 定理。
數(shù)據(jù)應(yīng)用范圍從存儲和檢索對象、連接、聚合、流處理、連續(xù)計算、機(jī)器學(xué)習(xí)等等。目前尚不清楚是否存在如此簡單的數(shù)據(jù)系統(tǒng)定義——似乎我們對數(shù)據(jù)所做的事情范圍太廣,無法用單一定義來概括。
但是,有這么一個簡單的定義。就是這個:
Query = Function(All Data)
而已。這個等式總結(jié)了數(shù)據(jù)庫和數(shù)據(jù)系統(tǒng)的整個領(lǐng)域。該領(lǐng)域的一切——過去 50 年的 RDBMS、索引、OLAP、OLTP、MapReduce、ETL、分布式文件系統(tǒng)、流處理器、NoSQL 等——都以這種或那種方式總結(jié)為該等式。
數(shù)據(jù)系統(tǒng)回答有關(guān)數(shù)據(jù)集的問題。這些問題稱為“查詢”。這個等式表明查詢只是擁有的所有數(shù)據(jù)的函數(shù)。
這個等式可能看起來過于籠統(tǒng)而無用。它似乎沒有捕捉到數(shù)據(jù)系統(tǒng)設(shè)計的任何復(fù)雜性。但重要的是每個數(shù)據(jù)系統(tǒng)都屬于這個等式。該等式是我們探索數(shù)據(jù)系統(tǒng)的起點(diǎn),該等式最終將導(dǎo)致一種突破 CAP 定理的方法。
這個等式中有兩個概念:“數(shù)據(jù)”和“查詢”。這些是在數(shù)據(jù)庫領(lǐng)域中經(jīng)?;煜牟煌拍?,因此讓我們嚴(yán)格了解這些概念的含義。
數(shù)據(jù)
讓我們從“數(shù)據(jù)”開始。一條數(shù)據(jù)是一個不可分割的單元,你認(rèn)為它是真實(shí)的,除了它存在之外沒有其他原因。它就像數(shù)學(xué)中的公理。
關(guān)于數(shù)據(jù),有兩個重要的屬性需要注意。首先,數(shù)據(jù)本質(zhì)上是基于時間的。一條數(shù)據(jù)是知道在某個時刻是真實(shí)的事實(shí)。例如,假設(shè)張梓涵在她的社交網(wǎng)絡(luò)資料中輸入她住在北京。從該輸入中獲取的數(shù)據(jù)是,截至她將該信息輸入她的個人資料的特定時刻,她住在北京。假設(shè)張梓涵稍后將她的個人資料位置更新為上海。然后你知道她在那段時間住在上海。她現(xiàn)在住在上海的事實(shí)并沒有改變她曾經(jīng)住在北京的事實(shí)。這兩個數(shù)據(jù)都是真實(shí)的。
數(shù)據(jù)的第二個屬性緊隨第一個屬性:數(shù)據(jù)本質(zhì)上是不可變的。由于它與時間點(diǎn)的聯(lián)系,一條數(shù)據(jù)的真實(shí)性永遠(yuǎn)不會改變。人們無法回到過去來改變數(shù)據(jù)的真實(shí)性。這意味著只能對數(shù)據(jù)執(zhí)行兩個主要操作:讀取現(xiàn)有數(shù)據(jù)和添加更多數(shù)據(jù)。CRUD變成了 CR。我省略了“更新”操作。這是因為更新對不可變數(shù)據(jù)沒有意義。例如,“更新”張梓涵的位置實(shí)際上意味著正在添加一條新數(shù)據(jù),表明她最近住在一個新位置。我也省略了“刪除”操作。同樣,大多數(shù)刪除情況更好地表示為創(chuàng)建新數(shù)據(jù)。例如,如果張三停止在微博上關(guān)注李四,這不會改變他曾經(jīng)關(guān)注過她的事實(shí)。因此,與其刪除表示他關(guān)注她的數(shù)據(jù),不如添加一條新的數(shù)據(jù)記錄,說明他在某個時刻取消了對她的關(guān)注。
在某些情況下,確實(shí)希望永久刪除數(shù)據(jù),例如要求在一定時間后清除數(shù)據(jù)的法規(guī)。將要展示的數(shù)據(jù)系統(tǒng)設(shè)計很容易支持這些情況,因此為了簡單起見,我們可以忽略這些情況。
這種數(shù)據(jù)定義幾乎肯定與習(xí)慣的不同,特別是如果來自以更新為常態(tài)的關(guān)系數(shù)據(jù)庫世界。有兩個原因。首先,這個數(shù)據(jù)定義非常通用:很難想出一種數(shù)據(jù)不符合這個定義。其次,數(shù)據(jù)的不變性是我們在設(shè)計一個戰(zhàn)勝 CAP 定理的人類容錯數(shù)據(jù)系統(tǒng)時要利用的關(guān)鍵屬性。
查詢
等式中的第二個概念是“查詢”。查詢是一組數(shù)據(jù)的推導(dǎo)。從這個意義上說,查詢就像數(shù)學(xué)中的定理。例如,“張梓涵目前的位置是什么?” 是一個查詢??梢酝ㄟ^返回有關(guān)張梓涵 位置的最新數(shù)據(jù)記錄來計算此查詢。查詢是完整數(shù)據(jù)集的函數(shù),因此它們可以做任何事情:聚合、將不同類型的數(shù)據(jù)連接在一起等等。因此,可能會查詢服務(wù)的女性用戶數(shù)量,或者可能會查詢推文數(shù)據(jù)集,了解過去幾個小時的熱門話題。
我們已將查詢定義為完整數(shù)據(jù)集上的函數(shù)。當(dāng)然,許多查詢不需要運(yùn)行完整的數(shù)據(jù)集——它們只需要數(shù)據(jù)集的一個子集。但重要的是我們的定義封裝了所有可能的查詢,如果我們要突破 CAP 定理,我們必須能夠?qū)θ魏尾樵冏龅竭@一點(diǎn)。
突破 CAP 定理
計算查詢的最簡單方法是在完整數(shù)據(jù)集上逐字運(yùn)行函數(shù)。如果可以在延遲限制內(nèi)執(zhí)行此操作,那么就完成了。沒有別的東西可以建造了。
當(dāng)然,期望一個函數(shù)在一個完整的數(shù)據(jù)集上快速完成是不可行的。許多查詢,例如為網(wǎng)站提供服務(wù)的查詢,需要毫秒級的響應(yīng)時間。但是,讓我們假設(shè)可以快速計算這些函數(shù),讓我們看看這樣的系統(tǒng)如何與 CAP 定理交互。正如即將看到的,像這樣的系統(tǒng)不僅突破了 CAP 定理,而且還消滅了它。
CAP 定理仍然適用,因此需要在一致性和可用性之間做出選擇。關(guān)鍵之處在于,一旦決定了要做出的權(quán)衡,就完成了。通過使用不可變數(shù)據(jù)和從頭開始計算查詢,避免了 CAP 定理通常導(dǎo)致的復(fù)雜性。
如果選擇一致性而不是可用性,那么與以前相比不會有太大變化。有時將無法讀取或?qū)懭霐?shù)據(jù),因為犧牲了可用性。但對于需要嚴(yán)格一致性的情況,這是一種選擇。
當(dāng)選擇可用性而不是一致性時,事情會變得更加有趣。在這種情況下,系統(tǒng)是最終一致的,沒有任何最終一致性的復(fù)雜性。由于系統(tǒng)具有高可用性,可以隨時編寫新數(shù)據(jù)和計算查詢。在失敗的情況下,查詢將返回不包含以前寫入的數(shù)據(jù)的結(jié)果。最終,這些數(shù)據(jù)將是一致的,并且查詢會將這些數(shù)據(jù)合并到它們的計算中。
關(guān)鍵是數(shù)據(jù)是不可變的。不可變數(shù)據(jù)意味著沒有更新這樣的東西,因此一條數(shù)據(jù)的不同副本不可能變得不一致。這意味著沒有不同的值、矢量時鐘或讀取修復(fù)。從查詢的角度來看,一條數(shù)據(jù)要么存在,要么不存在。該數(shù)據(jù)上只有數(shù)據(jù)和功能。無需執(zhí)行任何操作來強(qiáng)制執(zhí)行最終一致性,并且最終一致性不會妨礙對系統(tǒng)進(jìn)行推理。
之前導(dǎo)致復(fù)雜的是增量更新和CAP定理的交互。增量更新和 CAP 定理真的不能很好地結(jié)合在一起;可變值需要在最終一致的系統(tǒng)中進(jìn)行讀取修復(fù)。通過拒絕增量更新、接受不可變數(shù)據(jù)以及每次都從頭開始計算查詢,可以避免這種復(fù)雜性。CAP 定理已被突破。
當(dāng)然,我們剛剛經(jīng)歷的是一個思想實(shí)驗。雖然我們希望每次都能從頭開始計算查詢,但這是不可行的。然而,我們已經(jīng)了解了真實(shí)解決方案的一些關(guān)鍵屬性:
1.該系統(tǒng)使存儲和擴(kuò)展不可變、不斷增長的數(shù)據(jù)集變得容易
2.主要的寫操作是添加新的不可變數(shù)據(jù)事實(shí)
3.系統(tǒng)通過從原始數(shù)據(jù)重新計算查詢來避免 CAP 定理的復(fù)雜性
4.系統(tǒng)使用增量算法將查詢延遲降低到可接受的水平
讓我們開始探索這樣一個系統(tǒng)是什么樣的。請注意,從這里開始的一切都是優(yōu)化。數(shù)據(jù)庫、索引、ETL、批處理計算、流處理——這些都是優(yōu)化查詢功能并將延遲降低到可接受水平的技術(shù)。這是一個簡單而深刻的認(rèn)識。數(shù)據(jù)庫通常被認(rèn)為是數(shù)據(jù)管理的核心,但實(shí)際上它們是更大范圍的一部分。
批量計算
弄清楚如何在任意數(shù)據(jù)集上快速運(yùn)行任意函數(shù)是一個令人生畏的問題。所以讓我們稍微放松一下這個問題。讓我們假設(shè)查詢過時幾個小時是可以的。以這種方式放松問題會導(dǎo)致構(gòu)建數(shù)據(jù)系統(tǒng)的簡單、優(yōu)雅和通用的解決方案。之后,我們將擴(kuò)展解決方案,使問題不再寬松。
由于查詢是所有數(shù)據(jù)的函數(shù),因此使查詢快速運(yùn)行的最簡單方法是預(yù)先計算它們。每當(dāng)有新數(shù)據(jù)時,只需重新計算所有內(nèi)容。這是可行的,因為我們放寬了問題,允許查詢過時幾個小時。這是此工作流程的示例:
要構(gòu)建它,需要一個系統(tǒng):
1.可以輕松存儲龐大且不斷增長的數(shù)據(jù)集
2.可以以可擴(kuò)展的方式計算該數(shù)據(jù)集上的函數(shù)
這樣的系統(tǒng)是存在的。它成熟,經(jīng)過數(shù)百個組織的實(shí)戰(zhàn)測試,并且擁有龐大的工具生態(tài)系統(tǒng)。它叫做Hadoop。Hadoop并不完美,但它是進(jìn)行批處理的最佳工具。
很多人會說 Hadoop 只適用于“非結(jié)構(gòu)化”數(shù)據(jù)。這是完全錯誤的。Hadoop 非常適合結(jié)構(gòu)化數(shù)據(jù)。使用Thrift或Protocol Buffers等工具,可以使用豐富的、可演化的模式來存儲數(shù)據(jù)。
Hadoop 由兩部分組成:分布式文件系統(tǒng) (HDFS) 和批處理框架 (MapReduce)。HDFS 擅長以可擴(kuò)展的方式跨文件存儲大量數(shù)據(jù)。MapReduce 擅長以可擴(kuò)展的方式對該數(shù)據(jù)運(yùn)行計算。這些系統(tǒng)完全符合我們的需求。
我們會將數(shù)據(jù)存儲在 HDFS 上的平面文件中。文件將包含一系列數(shù)據(jù)記錄。要添加新數(shù)據(jù),只需將包含新數(shù)據(jù)記錄的新文件附加到包含所有數(shù)據(jù)的文件夾即可。在 HDFS 上存儲這樣的數(shù)據(jù)解決了“存儲一個龐大且不斷增長的數(shù)據(jù)集”的需求。
對該數(shù)據(jù)進(jìn)行預(yù)計算查詢同樣簡單明了。MapReduce 是一種具有足夠表現(xiàn)力的范例,幾乎任何功能都可以作為一系列 MapReduce 作業(yè)來實(shí)現(xiàn)。Cascalog、Cascading和Pig等工具使實(shí)現(xiàn)這些功能變得更加容易。
最后,需要為預(yù)計算的結(jié)果編制索引,以便應(yīng)用程序可以快速訪問結(jié)果。有一類數(shù)據(jù)庫非常擅長于此。ElephantDB和Voldemort read-only專注于從 Hadoop 中導(dǎo)出鍵/值數(shù)據(jù)以進(jìn)行快速查詢。這些數(shù)據(jù)庫支持批量寫入和隨機(jī)讀取,不支持隨機(jī)寫入。隨機(jī)寫入導(dǎo)致數(shù)據(jù)庫的大部分復(fù)雜性,因此由于不支持隨機(jī)寫入,這些數(shù)據(jù)庫非常簡單。例如,ElephantDB 只有幾千行代碼。這種簡單性導(dǎo)致這些數(shù)據(jù)庫非常健壯。
讓我們看一個批處理系統(tǒng)如何組合在一起的例子。假設(shè)正在構(gòu)建一個跟蹤頁面瀏覽量的 Web 分析應(yīng)用程序,并且希望能夠查詢?nèi)魏螘r間段內(nèi)的頁面瀏覽量,精確到一小時。
實(shí)現(xiàn)這個很容易。每個數(shù)據(jù)記錄都包含一個頁面視圖。這些數(shù)據(jù)記錄存儲在 HDFS 上的文件中。按小時匯總每個 URL 的頁面瀏覽量的功能是作為一系列 MapReduce 作業(yè)實(shí)現(xiàn)的。該函數(shù)發(fā)出鍵/值對,其中每個鍵都是一[URL, hour]對,每個值都是頁面瀏覽量的計數(shù)。這些鍵/值對被導(dǎo)出到 ElephantDB 數(shù)據(jù)庫中,以便應(yīng)用程序可以快速獲取任何[URL, hour]對的值。當(dāng)應(yīng)用程序想知道某個時間范圍內(nèi)的頁面瀏覽量時,它會向 ElephantDB 查詢該時間范圍內(nèi)每小時的頁面瀏覽量,并將它們相加得到最終結(jié)果。
批處理可以計算任意數(shù)據(jù)上的任意函數(shù),缺點(diǎn)是查詢會過時幾個小時。這種系統(tǒng)的“任意性”意味著它可以應(yīng)用于任何問題。更重要的是,它簡單、易于理解并且完全可擴(kuò)展。只需要從數(shù)據(jù)和功能的角度考慮,Hadoop 負(fù)責(zé)并行化。
批處理系統(tǒng)、CAP 和人為容錯
那么批處理系統(tǒng)如何與 CAP 保持一致,它是否滿足我們的人類容錯目標(biāo)?
讓我們從 CAP 開始。批處理系統(tǒng)以最極端的方式實(shí)現(xiàn)最終一致性:寫入總是需要幾個小時才能合并到查詢中。但這是一種易于推理的最終一致性形式,因為只需考慮數(shù)據(jù)和數(shù)據(jù)上的函數(shù)。無需考慮讀取修復(fù)、并發(fā)或其他復(fù)雜問題。
接下來,我們來看看批處理系統(tǒng)的人為容錯能力。批處理系統(tǒng)的人為容錯能力是你能得到的最好的。在這樣的系統(tǒng)中,人類只會犯兩個錯誤:部署有缺陷的查詢實(shí)現(xiàn)或?qū)懭脲e誤數(shù)據(jù)。
如果你部署了一個有問題的查詢實(shí)現(xiàn),你要做的就是修復(fù)這個問題,部署修復(fù)后的版本,然后從主數(shù)據(jù)集中重新計算所有內(nèi)容。這是可行的,因為查詢是純函數(shù)。
同樣,寫入壞數(shù)據(jù)有一條清晰的恢復(fù)路徑:刪除壞數(shù)據(jù)并再次預(yù)計算查詢。由于數(shù)據(jù)是不可變的并且主數(shù)據(jù)集是僅附加的,因此寫入錯誤數(shù)據(jù)不會覆蓋或以其他方式破壞良好數(shù)據(jù)。這與幾乎所有傳統(tǒng)數(shù)據(jù)庫形成鮮明對比,在傳統(tǒng)數(shù)據(jù)庫中,如果更新密鑰,就會丟失舊值。
請注意,MVCC和類似 HBase 的行版本控制并沒有接近這種水平的人為容錯。MVCC 和 HBase 行版本控制不會永遠(yuǎn)保留數(shù)據(jù):一旦數(shù)據(jù)庫壓縮行,舊值就消失了。只有不可變的數(shù)據(jù)集才能保證在寫入錯誤數(shù)據(jù)時有恢復(fù)路徑。
實(shí)時層
批處理解決方案幾乎解決了實(shí)時計算任意數(shù)據(jù)的任意函數(shù)的完整問題。任何早于幾個小時的數(shù)據(jù)都已合并到批處理視圖中,因此剩下要做的就是補(bǔ)償最后幾個小時的數(shù)據(jù)。弄清楚如何對幾個小時的數(shù)據(jù)進(jìn)行實(shí)時查詢比對完整數(shù)據(jù)集進(jìn)行實(shí)時查詢要容易得多。這是一個重要的見解。
為了補(bǔ)償那幾個小時的數(shù)據(jù),需要一個與批處理系統(tǒng)并行運(yùn)行的實(shí)時系統(tǒng)。實(shí)時系統(tǒng)針對最近幾個小時的數(shù)據(jù)預(yù)先計算每個查詢函數(shù)。要解決查詢功能,查詢批處理視圖和實(shí)時視圖并將結(jié)果合并在一起以獲得最終答案。
實(shí)時層是使用讀/寫數(shù)據(jù)庫(如 Riak 或 Cassandra)的地方,實(shí)時層依賴于增量算法來更新這些數(shù)據(jù)庫中的狀態(tài)。
用于實(shí)時計算的 Hadoop 模擬是Storm。Storm 是為了以一種可擴(kuò)展且健壯的方式進(jìn)行大量實(shí)時數(shù)據(jù)處理。Storm 對數(shù)據(jù)流進(jìn)行無限計算,并為數(shù)據(jù)處理提供強(qiáng)有力的保證。
讓我們通過返回查詢某個時間范圍內(nèi) URL 的頁面瀏覽量的運(yùn)行示例來查看實(shí)時層的示例。
批處理系統(tǒng)與以前相同:基于 Hadoop 和 ElephantDB 的批處理工作流預(yù)先計算除最近幾個小時數(shù)據(jù)之外的所有內(nèi)容的查詢。剩下的就是構(gòu)建實(shí)時系統(tǒng)來補(bǔ)償最后幾個小時的數(shù)據(jù)。
我們會將過去幾個小時的統(tǒng)計數(shù)據(jù)匯總到 Cassandra 中,我們將使用 Storm 處理頁面瀏覽流并將更新并行化到數(shù)據(jù)庫中。[URL, hour]在 Cassandra 中,每次頁面瀏覽都會導(dǎo)致一個密鑰計數(shù)器遞增。這就是它的全部——Storm 使這些事情變得非常簡單。
批處理層 + 實(shí)時層、CAP 定理和人類容錯
在某些方面,我們似乎又回到了起點(diǎn)。實(shí)現(xiàn)實(shí)時查詢需要我們使用 NoSQL 數(shù)據(jù)庫和增量算法。這意味著我們回到了不同值、矢量時鐘和讀取修復(fù)的復(fù)雜世界。
但是有一個關(guān)鍵的區(qū)別。由于實(shí)時層僅補(bǔ)償最后幾個小時的數(shù)據(jù),實(shí)時層計算的所有內(nèi)容最終都會被批處理層覆蓋。因此,如果在實(shí)時層中犯了錯誤或出了什么問題,批處理層會糾正它。所有這些復(fù)雜性都是短暫的。
這并不意味著不應(yīng)該關(guān)心實(shí)時層中的讀取修復(fù)或最終一致性。仍然希望實(shí)時層盡可能保持一致。但是,當(dāng)犯錯時,不會永久損壞數(shù)據(jù)。這減輕了巨大的復(fù)雜性負(fù)擔(dān)。
在批處理層,你只需要考慮數(shù)據(jù)和數(shù)據(jù)上的函數(shù)。批處理層的推理非常簡單。另一方面,在實(shí)時層,必須使用增量算法和極其復(fù)雜的 NoSQL 數(shù)據(jù)庫。將所有這些復(fù)雜性隔離到實(shí)時層中,對于構(gòu)建健壯、可靠的系統(tǒng)有很大的不同。
此外,實(shí)時層不會影響系統(tǒng)的人為容錯能力。批處理層中的 append-only 不可變數(shù)據(jù)集仍然是系統(tǒng)的核心,因此任何錯誤都可以像以前一樣從中恢復(fù)。
讓我們看一個關(guān)于在實(shí)時層中隔離復(fù)雜性的案例。有一個與這里描述的系統(tǒng)非常相似的系統(tǒng):用于批處理層的 Hadoop 和 ElephantDB,以及用于實(shí)時層的 Storm 和 Cassandra。由于監(jiān)控不力,有一天發(fā)現(xiàn) Cassandra 空間不足并且每次請求都超時。這導(dǎo)致 Storm 拓?fù)涫?,?shù)據(jù)流在隊列中備份。相同的消息不斷被重播并不斷失敗。
如果沒有批處理層,將不得不擴(kuò)展和恢復(fù) Cassandra。這很重要。更糟糕的是,由于多次重播相同的消息,許多數(shù)據(jù)庫可能不準(zhǔn)確。
幸運(yùn)的是,所有這些復(fù)雜性都隔離在實(shí)時層中。將備份的隊列刷新到批處理層并創(chuàng)建了一個新的 Cassandra 集群。批處理層像發(fā)條一樣運(yùn)行,幾個小時內(nèi)一切恢復(fù)正常。沒有數(shù)據(jù)丟失,查詢也沒有不準(zhǔn)確之處。
垃圾收集
我們描述的一切都建立在一個不變的、不斷增長的數(shù)據(jù)集的基礎(chǔ)上。那么,如果的數(shù)據(jù)集太大以至于無法一直存儲所有數(shù)據(jù),即使使用水平可擴(kuò)展存儲,會怎么做?這個用例是否破壞了所描述的一切?你應(yīng)該回去使用可變數(shù)據(jù)庫嗎?
不。很容易用“垃圾收集”擴(kuò)展基本模型來處理這個用例。垃圾收集只是一個函數(shù),它接受主數(shù)據(jù)集并返回主數(shù)據(jù)集的過濾版本。垃圾收集擺脫了低價值的數(shù)據(jù)。可以使用任何想要的策略來進(jìn)行垃圾回收。可以通過僅保留實(shí)體的最后一個值來模擬可變性,或者可以保留每個實(shí)體的歷史記錄。例如,如果要處理位置數(shù)據(jù),可能希望每年為每個人保留一個位置以及當(dāng)前位置。可變性實(shí)際上只是一種不靈活的垃圾收集形式,它與 CAP 定理的交互也很差。
垃圾收集是作為批處理任務(wù)實(shí)現(xiàn)的。這是偶爾運(yùn)行的東西,也許每月一次。由于垃圾收集作為離線批處理任務(wù)運(yùn)行,因此它不會影響系統(tǒng)與 CAP 定理的交互方式。
小結(jié)
使可伸縮數(shù)據(jù)系統(tǒng)變得困難的不是 CAP 定理。正是對增量算法和可變狀態(tài)的依賴導(dǎo)致了我們系統(tǒng)的復(fù)雜性。隨著分布式數(shù)據(jù)庫的興起,這種復(fù)雜性才開始減弱。但這種復(fù)雜性一直存在。
批處理/實(shí)時架構(gòu)還有許多其他功能。現(xiàn)在值得總結(jié)其中的一些:
- 算法靈活性:一些算法難以增量計算。例如,如果唯一值集變大,計算唯一值可能會很困難。批處理/實(shí)時拆分使可以靈活地在批處理層上使用精確算法,在實(shí)時層上使用近似算法。批處理層不斷覆蓋實(shí)時層,因此近似值得到糾正,系統(tǒng)表現(xiàn)出“最終準(zhǔn)確性”的特性。
- 模式遷移很容易:由于批處理計算是系統(tǒng)的核心,因此很容易在完整的數(shù)據(jù)集上運(yùn)行函數(shù)。這使得更改數(shù)據(jù)或視圖的模式變得容易。
- 輕松的臨時分析:批處理層的任意性意味著可以對數(shù)據(jù)運(yùn)行任何喜歡的查詢。由于所有數(shù)據(jù)都可以在一個位置訪問,因此簡單方便。
- 自審計:通過將數(shù)據(jù)視為不可變的,可以獲得自審計數(shù)據(jù)集。數(shù)據(jù)集記錄了它自己的歷史。這對于人類容錯非常重要,它對于進(jìn)行分析也非常有用。
批處理/實(shí)時架構(gòu)具有很高的通用性,可以應(yīng)用于任何數(shù)據(jù)系統(tǒng)。要提高我們解決大數(shù)據(jù)問題的集體能力,還有很多工作要做。以下是一些關(guān)鍵的改進(jìn)領(lǐng)域:
- 批量可寫、隨機(jī)讀取數(shù)據(jù)庫的擴(kuò)展數(shù)據(jù)模型:并非每個應(yīng)用程序都受鍵/值數(shù)據(jù)模型支持。這就是為什么我的團(tuán)隊正在投資擴(kuò)展 ElephantDB 以支持搜索、文檔數(shù)據(jù)庫、范圍查詢等。
- 更好的批處理原語:Hadoop 不是批處理計算的終極目標(biāo)。對于某些類型的計算,它可能效率低下。Spark是一個重要的項目,在擴(kuò)展 MapReduce 范例方面做了有趣的工作。
- 改進(jìn)的讀/寫 NoSQL 數(shù)據(jù)庫:有更多具有不同數(shù)據(jù)模型的數(shù)據(jù)庫的空間,這些項目通常會從更成熟的過程中受益。
- 高級抽象:未來工作中最有趣的領(lǐng)域之一是映射到批處理組件和實(shí)時處理組件的高級抽象。沒有理由不讓聲明性語言的簡潔性和批處理/實(shí)時架構(gòu)的健壯性結(jié)合起來。
很多人都想要一個可擴(kuò)展的關(guān)系數(shù)據(jù)庫。大數(shù)據(jù)和 NoSQL 運(yùn)動似乎使數(shù)據(jù)管理比 RDBMS 更復(fù)雜,但這只是因為我們試圖像對待 RDBMS 數(shù)據(jù)一樣對待“大數(shù)據(jù)”:通過合并數(shù)據(jù)和視圖并依賴關(guān)于增量算法。大數(shù)據(jù)的規(guī)模讓能夠以完全不同的方式構(gòu)建系統(tǒng)。通過將數(shù)據(jù)存儲為一組不斷擴(kuò)展的不可變事實(shí)并將重新計算構(gòu)建到核心中,大數(shù)據(jù)系統(tǒng)實(shí)際上比關(guān)系系統(tǒng)更容易推理。
以上便是Lambda 架構(gòu)的想法,架構(gòu)如下圖所示:
它的工作方式是捕獲不可變的記錄序列并將其并行輸入到批處理系統(tǒng)和流處理系統(tǒng)中。實(shí)現(xiàn)轉(zhuǎn)換邏輯兩次,一次在批處理系統(tǒng)中,一次在流處理系統(tǒng)中。在查詢時將兩個系統(tǒng)的結(jié)果拼接在一起以產(chǎn)生完整的結(jié)果。
名稱欄目:談?wù)剰腃AP定理到Lambda架構(gòu)的演化
本文鏈接:http://www.dlmjj.cn/article/cdcgcid.html


咨詢
建站咨詢
