“打敗”CAP定理
分享 2011.12.08 瀏覽次數(shù):7447次
“打敗”CAP定理
標(biāo)簽:網(wǎng)站建設(shè) 網(wǎng)站制作 杭州網(wǎng)站制作 CAP定理
CAP定理是數(shù)據(jù)系統(tǒng)設(shè)計(jì)的基本理論,目前幾乎所有的數(shù)據(jù)系統(tǒng)的設(shè)計(jì)都遵循了這個(gè)定理。但CAP定理給目前的數(shù)據(jù)系統(tǒng)帶來(lái)了許多復(fù)雜的、不可控的問(wèn)題,使得數(shù)據(jù)系統(tǒng)的設(shè)計(jì)越來(lái)越復(fù)雜。Twitter首席工程師、Storm的作者Nathan Marz在本文中通過(guò)避開(kāi)CAP定理帶來(lái)的諸多復(fù)雜問(wèn)題,展示了一個(gè)不同于以往的數(shù)據(jù)系統(tǒng)設(shè)計(jì)方案,給我們的數(shù)據(jù)系統(tǒng)設(shè)計(jì)帶來(lái)了全新的思路。
CAP定理指出,一個(gè)數(shù)據(jù)庫(kù)不可能同時(shí)滿(mǎn)足一致性(Consistency)、可用性(Availability)和分區(qū)容錯(cuò)性(Partition-Tolerance)。
一致性(Consistency)是指執(zhí)行了一次成功的寫(xiě)操作之后,未來(lái)的讀操作一定可以讀到這個(gè)寫(xiě)入的值。可用性(Availability)是指系統(tǒng)總是可讀可寫(xiě)的。Yammer的Coda Hale和Cloudera的Henry Robinson都闡述過(guò),分區(qū)容錯(cuò)性是不能犧牲的,因此只能在一致性和可用性上做取舍,如何處理這種取舍正是目前NoSQL數(shù)據(jù)庫(kù)的核心焦點(diǎn)。
選擇一致性而不是可用性的系統(tǒng)將面臨一些尷尬的問(wèn)題,當(dāng)系統(tǒng)不可用時(shí)怎么辦?你可以對(duì)寫(xiě)操作進(jìn)行緩沖處理,但如果存儲(chǔ)緩沖數(shù)據(jù)的機(jī)器出現(xiàn)故障,客戶(hù)端將丟失寫(xiě)入的值。同樣地,緩沖寫(xiě)也可以被認(rèn)為是一種非一致性的操作,因?yàn)榭蛻?hù)端認(rèn)為成功的寫(xiě)入實(shí)際上并沒(méi)有寫(xiě)入到實(shí)際的數(shù)據(jù)庫(kù)中。當(dāng)然,系統(tǒng)可以在機(jī)器不可用時(shí)向客戶(hù)端返回錯(cuò)誤,但可以想象,一個(gè)經(jīng)常告訴客戶(hù)端“請(qǐng)重試”的產(chǎn)品是多么令人討厭。
另一個(gè)方案是選擇可用性放棄一致性。這種情況下最好的一致性保障是“最終一致性”(Eventually Consistency)。當(dāng)使用最終一致性的系統(tǒng)時(shí),客戶(hù)端有時(shí)會(huì)讀到與剛剛寫(xiě)入數(shù)據(jù)不同的數(shù)據(jù)。有時(shí)候,同一時(shí)間同一個(gè)key的多個(gè)請(qǐng)求有可能返回不同的結(jié)果。數(shù)據(jù)更新并不能及時(shí)在所有的復(fù)制節(jié)點(diǎn)上生效,所以不同的復(fù)制節(jié)點(diǎn)上可能讀取到的是不同的值。當(dāng)你檢測(cè)到數(shù)據(jù)不一致性時(shí),你需要進(jìn)行修復(fù)(Repair)操作,這就需要使用矢量時(shí)鐘(vector clock)記錄數(shù)據(jù)的版本歷史并合并不同的數(shù)據(jù)更新(這稱(chēng)為讀取修復(fù),read repair)。
我相信在應(yīng)用層維護(hù)最終一致性對(duì)開(kāi)發(fā)人員負(fù)擔(dān)太重,開(kāi)發(fā)人員極易弄錯(cuò)讀取修復(fù)的代碼,而一旦開(kāi)發(fā)人員犯錯(cuò),有問(wèn)題的讀取修復(fù)將對(duì)數(shù)據(jù)庫(kù)系統(tǒng)造成不可逆的損壞。
所以犧牲可用性時(shí)問(wèn)題會(huì)很多,犧牲一致性時(shí)構(gòu)建和維護(hù)系統(tǒng)的復(fù)雜度又很高,但這里又只有兩個(gè)選擇,不管怎樣做都會(huì)不完美。CAP定理是改不了的,那么還有什么其他可能的選擇嗎?
實(shí)際上,還有一個(gè)辦法:你并不能避開(kāi)CAP定理,但可以把復(fù)雜的問(wèn)題獨(dú)立出來(lái),免得你喪失對(duì)整個(gè)系統(tǒng)的掌控能力。CAP定理帶來(lái)的復(fù)雜性,其實(shí)是我們?nèi)绾螛?gòu)建數(shù)據(jù)系統(tǒng)這一根本問(wèn)題的體現(xiàn)。其中有兩點(diǎn)特別重要:數(shù)據(jù)庫(kù)中可變狀態(tài)和更新?tīng)顟B(tài)的增量算法。復(fù)雜性正是這兩點(diǎn)和CAP定理之間的相互作用導(dǎo)致的。
本文將通過(guò)一個(gè)數(shù)據(jù)庫(kù)系統(tǒng)的設(shè)計(jì),來(lái)說(shuō)明如何解決CAP定理通常會(huì)造成的復(fù)雜性問(wèn)題。但我要做的不僅僅如此,CAP定理是一個(gè)針對(duì)機(jī)器發(fā)生錯(cuò)誤時(shí)系統(tǒng)容錯(cuò)性的一個(gè)定理,而這里有比機(jī)器容錯(cuò)性更加重要的容錯(cuò)性——人為操作容錯(cuò)性。在軟件開(kāi)發(fā)中一個(gè)確定的事實(shí)是,開(kāi)發(fā)人員都并非完人,產(chǎn)品中難免有一些Bug,我們的系統(tǒng)必須對(duì)有Bug的程序?qū)懭氲腻e(cuò)誤數(shù)據(jù)有足夠的適應(yīng)能力,我要展示的系統(tǒng)將是這樣一個(gè)可以容忍人為錯(cuò)誤的系統(tǒng)。
本文將挑戰(zhàn)你對(duì)數(shù)據(jù)系統(tǒng)如何構(gòu)建這一問(wèn)題的假設(shè),通過(guò)顛覆傳統(tǒng)數(shù)據(jù)系統(tǒng)構(gòu)建方法,我會(huì)讓大家看到一個(gè)前所未見(jiàn)的優(yōu)雅、擴(kuò)展性強(qiáng)、健壯的數(shù)據(jù)系統(tǒng)。
什么是數(shù)據(jù)系統(tǒng)?
在開(kāi)始介紹系統(tǒng)設(shè)計(jì)之前,讓我們先來(lái)看看我們要解決的問(wèn)題:數(shù)據(jù)系統(tǒng)的目的在于什么? 什么是數(shù)據(jù)? 在我們考慮CAP定理之前,我們必須給出一個(gè)可以適用于所有數(shù)據(jù)應(yīng)用程序的定義來(lái)回答上述問(wèn)題。
數(shù)據(jù)應(yīng)用程序種類(lèi)很多,包括存入和提取數(shù)據(jù)對(duì)象、連接、聚合、流處理、機(jī)器學(xué)習(xí)等。似乎并不存在一個(gè)對(duì)數(shù)據(jù)系統(tǒng)的明確定義,數(shù)據(jù)處理的多樣性使得我們很難用一個(gè)定義來(lái)描述。
事實(shí)卻并非如此,下面這個(gè)簡(jiǎn)單的定義:
Query = Function(All Data)
概括了數(shù)據(jù)庫(kù)和數(shù)據(jù)系統(tǒng)的所有領(lǐng)域。每一個(gè)領(lǐng)域——有50年歷史的RDBMS、索引、OLAP、OLTP、MapReduce、EFL、分布式文件系統(tǒng)、流處理器、NoSQL等——都可以被概括進(jìn)這個(gè)方程。
所謂數(shù)據(jù)系統(tǒng)就是要回答數(shù)據(jù)集問(wèn)題的系統(tǒng),這些問(wèn)題我們稱(chēng)之為“查詢(xún)”。上面的方程表明,查詢(xún)就是數(shù)據(jù)上的一個(gè)函數(shù)。
上述方程對(duì)于實(shí)際使用來(lái)說(shuō)太過(guò)于籠統(tǒng),幾乎對(duì)復(fù)雜的數(shù)據(jù)系統(tǒng)設(shè)計(jì)不起什么作用。但如果所有的數(shù)據(jù)系統(tǒng)都遵循這個(gè)方程又會(huì)怎樣呢?這個(gè)方程是探索我們數(shù)據(jù)系統(tǒng)的第一步,而它最終將引導(dǎo)我們找到“打敗”CAP定理的方法。
這個(gè)方程里面有兩個(gè)關(guān)鍵概念:數(shù)據(jù)、查詢(xún)。這兩個(gè)完全不同的概念經(jīng)常被混為一談,所以下面來(lái)看看這兩個(gè)概念究竟是什么意思。
數(shù)據(jù)
我們先從“數(shù)據(jù)”開(kāi)始。所謂數(shù)據(jù)就是一個(gè)不可分割的單位,它肯定存在,就跟數(shù)學(xué)里面的公理一樣。
關(guān)于“數(shù)據(jù)”有兩個(gè)關(guān)鍵的性質(zhì)。首先,數(shù)據(jù)是跟時(shí)間相關(guān)的,一個(gè)真實(shí)的數(shù)據(jù)一定是在某個(gè)時(shí)間點(diǎn)存在于那兒。比如,假如Sally在她的社交網(wǎng)絡(luò)個(gè)人資料中寫(xiě)她住在芝加哥,你拿到的這個(gè)數(shù)據(jù)肯定是她某個(gè)時(shí)間在芝加哥填寫(xiě)的。假如某天Sally把她資料里面居住地點(diǎn)更新為亞特蘭大,那么她肯定在這個(gè)時(shí)候是住在亞特蘭大的,但她住在亞特蘭大的事實(shí)無(wú)法改變她曾經(jīng)住在芝加哥這個(gè)事實(shí)——這兩個(gè)數(shù)據(jù)都是真實(shí)的。
其次,數(shù)據(jù)無(wú)法改變。由于數(shù)據(jù)跟某個(gè)時(shí)間點(diǎn)相關(guān),所以數(shù)據(jù)的真實(shí)性是無(wú)法改變的。沒(méi)有人可以回到那個(gè)時(shí)間去改變數(shù)據(jù)的真實(shí)性,這說(shuō)明了對(duì)數(shù)據(jù)操作只有兩種:讀取已存在的數(shù)據(jù)和添加更多的新數(shù)據(jù)。那么CRUD就變成了CR【譯者注:CRUD是指Create Read Update Delete,即數(shù)據(jù)的創(chuàng)建、讀取、更新和刪除】。
我去掉了“更新”操作,因?yàn)楦聦?duì)于不可改變的數(shù)據(jù)沒(méi)有任何作用。例如,更新Sally的位置信息本質(zhì)上就是在她住的地方數(shù)據(jù)中新加一條最近的位置信息而已。
我同樣去掉了“刪除”操作,因?yàn)榻^大部分刪除操作可以更好地表述為新加一條數(shù)據(jù)。比如Bob在Twitter上不再關(guān)注Mary了,這并不能改變他曾經(jīng)關(guān)注過(guò)Mary這個(gè)事實(shí)。所以與其刪除Bob關(guān)注Mary這個(gè)數(shù)據(jù),還不如新加一條Bob在某個(gè)時(shí)間點(diǎn)不再關(guān)注Mary這個(gè)數(shù)據(jù)。
這里只有很少數(shù)的情況需要永久“刪除”數(shù)據(jù),例如規(guī)則要求你每隔一段時(shí)間清掉數(shù)據(jù),這個(gè)情況在我將要展示的系統(tǒng)中有很好的解決方案,所以為了簡(jiǎn)潔,我們暫不考慮這些情況。
查詢(xún)
查詢(xún)是一個(gè)針對(duì)數(shù)據(jù)集的推導(dǎo),就像是一個(gè)數(shù)學(xué)里面的定理。例如,你可以通過(guò)計(jì)算“Sally現(xiàn)在的位置在哪里”這個(gè)查詢(xún)來(lái)得到Sally最新的位置數(shù)據(jù)。查詢(xún)是整個(gè)數(shù)據(jù)集合上的函數(shù),可以做一切事情:聚合、連接不同類(lèi)型的數(shù)據(jù)等。因此,你可以查詢(xún)系統(tǒng)中女性用戶(hù)的數(shù)量,可以查詢(xún)最近幾小時(shí)熱門(mén)的 Twitter內(nèi)容。
前面我已經(jīng)定義查詢(xún)是整個(gè)數(shù)據(jù)集上的函數(shù),當(dāng)然,不是所有的查詢(xún)都需要整個(gè)數(shù)據(jù)集,它們只需要數(shù)據(jù)集的一個(gè)子集。但我的定義是涵蓋了所有的查詢(xún)類(lèi)型,如果想要“打敗”CAP定理,我們需要能夠處理所有的查詢(xún)。
打敗CAP定理
計(jì)算查詢(xún)最簡(jiǎn)單的辦法就是按照查詢(xún)語(yǔ)義在整個(gè)數(shù)據(jù)集上運(yùn)行一個(gè)函數(shù)。如果這可以滿(mǎn)足你對(duì)延遲的要求,那么就沒(méi)有其他需要構(gòu)建的了。
可想而知,我們不能指望在整個(gè)數(shù)據(jù)集上的查詢(xún)能夠很快完成,特別是那些服務(wù)大型網(wǎng)站、需要每秒處理幾百萬(wàn)次請(qǐng)求的系統(tǒng)。但假如這種查詢(xún)可以很快完成,讓我們來(lái)看看像這樣的系統(tǒng)和CAP定理的PK結(jié)果:你將會(huì)看到,這個(gè)系統(tǒng)不僅打敗了CAP定理,而且還消滅了它。
CAP定理仍然適用,所以你需要在可用性和一致性上做出選擇,這里的漂亮之處在于,一旦你權(quán)衡之后做出了選擇,你就做完了所有的事情。通常的那些因?yàn)镃AP定理帶來(lái)的問(wèn)題,都可以通過(guò)不可改變的數(shù)據(jù)和從原始數(shù)據(jù)中計(jì)算查詢(xún)來(lái)規(guī)避。
如果你選擇一致性而不是可用性,那么跟以前并沒(méi)有多大的區(qū)別,因?yàn)槟惴艞壛丝捎眯?,所以一些時(shí)候你將無(wú)法讀取或者寫(xiě)入數(shù)據(jù)。當(dāng)然這只是針對(duì)對(duì)強(qiáng)一致性有要求的系統(tǒng)。
如果你選擇可用性而不是一致性,在這種情況下,系統(tǒng)可以達(dá)到最終一致性而且規(guī)避了所有最終一致性帶來(lái)的復(fù)雜問(wèn)題。由于系統(tǒng)總是可用的,所以你總可以寫(xiě)入新數(shù)據(jù)或者進(jìn)行查詢(xún)。在出錯(cuò)情況下,查詢(xún)可能返回的不是最近寫(xiě)入的數(shù)據(jù),但根據(jù)最終一致性,這個(gè)數(shù)據(jù)最終會(huì)一致,而查詢(xún)函數(shù)最終會(huì)把這個(gè)數(shù)據(jù)計(jì)算進(jìn)去。
這里的關(guān)鍵在于數(shù)據(jù)是不可變的。不可變數(shù)據(jù)意味著這里沒(méi)有更新操作,所以不可能出現(xiàn)數(shù)據(jù)復(fù)制不同這種不一致的情況,也意味著不需要版本化的數(shù)據(jù)、矢量時(shí)鐘或者讀取修復(fù)。在一個(gè)查詢(xún)場(chǎng)景中,一個(gè)數(shù)據(jù)只有存在或者不存在兩種情況。這里只有數(shù)據(jù)和在數(shù)據(jù)之上的函數(shù)。這里沒(méi)有需要你為確保最終一致性額外做的事情,最終一致性也不會(huì)因此使你的系統(tǒng)變得復(fù)雜。
之前的復(fù)雜度主要來(lái)自增量更新操作和CAP定理之間的矛盾,在最終一致性系統(tǒng)中可變的值需要通過(guò)讀取修復(fù)來(lái)保證最終一致性。通過(guò)使用不可變數(shù)據(jù),去掉增量更新,使用不可變數(shù)據(jù),每次從原始數(shù)據(jù)計(jì)算查詢(xún),你可以規(guī)避那些復(fù)雜的問(wèn)題。CAP定理就被打敗了。
當(dāng)然,現(xiàn)在講的只不過(guò)是想法而已,而且每次從原始數(shù)據(jù)計(jì)算查詢(xún)基本上不可能。但我們從中可以學(xué)到一些在實(shí)際解決方案中的關(guān)鍵點(diǎn)。
- 數(shù)據(jù)系統(tǒng)因?yàn)椴豢勺償?shù)據(jù)和不斷增長(zhǎng)的數(shù)據(jù)集變得簡(jiǎn)單了。
- 基本的寫(xiě)入操作就是寫(xiě)入一條新的不可變數(shù)據(jù)。
- 數(shù)據(jù)系統(tǒng)通過(guò)重新從原始數(shù)據(jù)計(jì)算查詢(xún)規(guī)避了CAP定理帶來(lái)的復(fù)雜度。
- 數(shù)據(jù)系統(tǒng)利用增量算法使得查詢(xún)的返回延遲降低到一個(gè)可以接受的程度。
讓我們開(kāi)始探索這個(gè)數(shù)據(jù)系統(tǒng)應(yīng)該如何設(shè)計(jì)。請(qǐng)注意從這里開(kāi)始我們所描述都是針對(duì)系統(tǒng)優(yōu)化、數(shù)據(jù)庫(kù)、索引、EFL、批量計(jì)算、流處理——這些技術(shù)都是對(duì)查詢(xún)函數(shù)的優(yōu)化,讓查詢(xún)返回時(shí)間降低到一個(gè)可以接受的程度。這很簡(jiǎn)單,但也是數(shù)據(jù)系統(tǒng)所面對(duì)的現(xiàn)實(shí)。數(shù)據(jù)庫(kù)通常是數(shù)據(jù)管理的核心,但它們是更大藍(lán)圖中的一部分。
批量計(jì)算
“如何讓任意一個(gè)函數(shù)可以在任意一個(gè)數(shù)據(jù)集上快速執(zhí)行完成”這個(gè)問(wèn)題太過(guò)于復(fù)雜,所以我們先放寬了一下這個(gè)問(wèn)題依賴(lài)條件。首先假設(shè),可以允許數(shù)據(jù)滯后幾小時(shí)。放寬這個(gè)條件之后,我們可以得到一個(gè)簡(jiǎn)單、優(yōu)雅、通用的數(shù)據(jù)系統(tǒng)構(gòu)建解決方案。之后,我們會(huì)通過(guò)擴(kuò)展這個(gè)解決方案使得它可以不用放寬條件來(lái)解決問(wèn)題。
由于查詢(xún)是所有數(shù)據(jù)的一個(gè)函數(shù),讓查詢(xún)變快的最簡(jiǎn)單的方法就是預(yù)先計(jì)算好這些查詢(xún)。只要這里有新的數(shù)據(jù),你就重新計(jì)算這些查詢(xún)。這是可能的,因?yàn)槲覀兎艑捔藯l件使得我們的數(shù)據(jù)可以滯后幾個(gè)小時(shí)。圖1展示了這個(gè)工作流程。
圖1 預(yù)計(jì)算工作流程
為了實(shí)現(xiàn)這個(gè),你的系統(tǒng)需要:
- 能很容易存儲(chǔ)大的、不斷增長(zhǎng)的數(shù)據(jù)集;
- 能在數(shù)據(jù)集上可擴(kuò)展地計(jì)算查詢(xún)函數(shù)。
這樣的系統(tǒng)是存在的,即Hadoop。它是一個(gè)成熟的、經(jīng)歷了無(wú)數(shù)團(tuán)隊(duì)實(shí)戰(zhàn)檢驗(yàn)過(guò)的系統(tǒng),同時(shí)擁有一個(gè)巨大的工具生態(tài)系統(tǒng)。它雖不完美,但是這里用來(lái)做批量處理的最好的一個(gè)工具。
許多人也許會(huì)告訴你,Hadoop只適用于那些“非結(jié)構(gòu)化”的數(shù)據(jù),這是完全錯(cuò)誤的看法。Hadoop處理“結(jié)構(gòu)化”的數(shù)據(jù)也很不錯(cuò),通過(guò)使用像Thrift或者Protocol Buffers這樣的工具,你可以使用豐富的數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)你的數(shù)據(jù)。
Hadoop由分布式文件系統(tǒng)HDFS和批處理框架MapReduce兩部分構(gòu)成。HDFS可以通過(guò)文件存儲(chǔ)大量數(shù)據(jù),MapReduce可以在這樣數(shù)據(jù)上進(jìn)行可擴(kuò)展計(jì)算。這個(gè)系統(tǒng)完全符合我們的要求。
我們將數(shù)據(jù)以文件形式存儲(chǔ)到HDFS中去。文件可以包括一個(gè)數(shù)據(jù)記錄序列。新增數(shù)據(jù)時(shí),我們只需要在包括所有數(shù)據(jù)的文件夾中新增一個(gè)包含這條新記錄的文件即可。像這樣在HDFS存儲(chǔ)數(shù)據(jù)滿(mǎn)足了“能夠很容易存儲(chǔ)大的、不斷增長(zhǎng)的數(shù)據(jù)集”這個(gè)要求。
預(yù)計(jì)算數(shù)據(jù)集上的查詢(xún)也很直觀(guān),MapReduce是一個(gè)足夠復(fù)雜的框架,使得幾乎所有的函數(shù)都可以按照多個(gè)MapReduce任務(wù)這種方式實(shí)現(xiàn)。像Cascalog、Cascading和Pig這樣的工具使實(shí)現(xiàn)這些函數(shù)變得十分簡(jiǎn)單。
最后,為了可以快速訪(fǎng)問(wèn)這些預(yù)計(jì)算查詢(xún)結(jié)果,你需要對(duì)查詢(xún)結(jié)果進(jìn)行索引,這里有許多數(shù)據(jù)庫(kù)可以完成這個(gè)工作。ElephantDB和Voldemort read-only可以通過(guò)從Hadoop中導(dǎo)出key/value數(shù)據(jù)來(lái)加快查詢(xún)速度。這些數(shù)據(jù)庫(kù)支持批量寫(xiě)和隨機(jī)讀,同時(shí)不支持隨機(jī)寫(xiě)。隨機(jī)寫(xiě)使得數(shù)據(jù)庫(kù)變得復(fù)雜,所以通過(guò)不支持隨機(jī)寫(xiě),這些數(shù)據(jù)庫(kù)設(shè)計(jì)得特別簡(jiǎn)潔,也就幾千行代碼而已。簡(jiǎn)潔使得這些數(shù)據(jù)庫(kù)魯棒性變得非常好。
下面來(lái)看批量處理系統(tǒng)整體上是如何配合工作的。假設(shè)寫(xiě)一個(gè)網(wǎng)站分析程序來(lái)跟蹤頁(yè)面訪(fǎng)問(wèn)量,你需要能夠查詢(xún)到任意時(shí)間段的頁(yè)面訪(fǎng)問(wèn)量,數(shù)據(jù)是以小時(shí)方式提供的。如圖2所示。
圖2 批處理工程流程示例(timestamp代表時(shí)間戳,count代表個(gè)數(shù))
實(shí)現(xiàn)這個(gè)很簡(jiǎn)單,每一個(gè)數(shù)據(jù)記錄包括一個(gè)單一頁(yè)面的訪(fǎng)問(wèn)量。這些數(shù)據(jù)通過(guò)文件形式存儲(chǔ)到HDFS中,一個(gè)函數(shù)通過(guò)實(shí)現(xiàn)MapReduce計(jì)算任務(wù),來(lái)計(jì)算一個(gè)URL下頁(yè)面每小時(shí)的訪(fǎng)問(wèn)量。這個(gè)函數(shù)產(chǎn)生的是key/value對(duì),其中[URL, hour]是key,value是頁(yè)面的訪(fǎng)問(wèn)量。這些key/value對(duì)被導(dǎo)出到ElephantDB中去,使得應(yīng)用程序可以快速得到任意[URL, hour]對(duì)對(duì)應(yīng)的值。如果應(yīng)用程序想要知道某個(gè)時(shí)間范圍內(nèi)某個(gè)頁(yè)面的訪(fǎng)問(wèn)量,它可以查詢(xún)ElephantDB中那段時(shí)間內(nèi)的數(shù)據(jù),然后把這些數(shù)據(jù)相加就可以得到這個(gè)訪(fǎng)問(wèn)量數(shù)據(jù)了。
在數(shù)據(jù)滯后幾小時(shí)這個(gè)缺陷下,批量處理可以計(jì)算任意數(shù)據(jù)集上的任意函數(shù)。系統(tǒng)中的“任意性”是指這個(gè)系統(tǒng)可以處理任何問(wèn)題。更重要的是,它很簡(jiǎn)單,容易理解和完全可擴(kuò)展,你需要考慮的只是數(shù)據(jù)和查詢(xún)函數(shù),Hadoop會(huì)幫你處理并行的事情。
批處理系統(tǒng)、CAP定理和容忍人為錯(cuò)誤
截至目前,我們的系統(tǒng)都很不錯(cuò),這個(gè)批處理系統(tǒng)是不是可以達(dá)到容忍人為錯(cuò)誤的目標(biāo)呢?
讓我們從CAP定理開(kāi)始。這個(gè)批處理系統(tǒng)總是最終一致的:寫(xiě)入的數(shù)據(jù)總可以在幾小時(shí)后被查詢(xún)到。這個(gè)系統(tǒng)是一個(gè)很容易掌控的最終一致性系統(tǒng),使得你可以只用關(guān)注你的數(shù)據(jù)和針對(duì)數(shù)據(jù)的查詢(xún)函數(shù)。這里沒(méi)有涉及讀取修復(fù)、并發(fā)和其他一些需要考慮的復(fù)雜問(wèn)題。
接下來(lái)看看這個(gè)系統(tǒng)對(duì)人為錯(cuò)誤的容忍性。在這個(gè)系統(tǒng)中人們可能會(huì)犯兩個(gè)錯(cuò)誤:部署了一個(gè)有Bug的查詢(xún)函數(shù)或者寫(xiě)入了錯(cuò)誤的數(shù)據(jù)。
如果部署了一個(gè)有Bug的查詢(xún)函數(shù),需要做的所有事情就是修正那個(gè)Bug,重新部署這個(gè)查詢(xún)函數(shù),然后在主數(shù)據(jù)集上重新計(jì)算它。這之所以能起作用是因?yàn)椴樵?xún)只是一個(gè)函數(shù)而已。
另外,錯(cuò)誤的數(shù)據(jù)有明確的辦法可以恢復(fù):刪除錯(cuò)誤數(shù)據(jù),然后重新計(jì)算查詢(xún)。由于數(shù)據(jù)是不可變的,而且數(shù)據(jù)集只是往后添加新數(shù)據(jù),寫(xiě)入錯(cuò)誤的數(shù)據(jù)不會(huì)覆蓋或者刪除正確的數(shù)據(jù),這與傳統(tǒng)數(shù)據(jù)庫(kù)更新一個(gè)數(shù)據(jù)就丟掉舊的數(shù)據(jù)形成了鮮明的對(duì)比。
注意到MVCC和HBase類(lèi)似的行版本管理并不能達(dá)到上面人為錯(cuò)誤容忍級(jí)別。MVCC和HBase行版本管理不能永久保存數(shù)據(jù),一旦數(shù)據(jù)庫(kù)合并了這些版本,舊的數(shù)據(jù)就會(huì)丟失。只有不可變數(shù)據(jù)系統(tǒng)能夠保證你在寫(xiě)入錯(cuò)誤數(shù)據(jù)時(shí)可以找到一個(gè)恢復(fù)數(shù)據(jù)的方法。
實(shí)時(shí)層
上面的批量處理系統(tǒng)幾乎完全解決了在任意數(shù)據(jù)集上運(yùn)行任意函數(shù)的實(shí)時(shí)性需求。任何超過(guò)幾個(gè)小時(shí)的數(shù)據(jù)已經(jīng)被計(jì)算進(jìn)入了批處理視圖中,所以剩下來(lái)要做的就是處理最近幾個(gè)小時(shí)的數(shù)據(jù)。我們知道在最近幾小時(shí)數(shù)據(jù)上進(jìn)行查詢(xún)比在整個(gè)數(shù)據(jù)集上查詢(xún)要容易,這是關(guān)鍵點(diǎn)。
為了處理最近幾個(gè)小時(shí)的數(shù)據(jù),需要一個(gè)實(shí)時(shí)系統(tǒng)和批處理系統(tǒng)同時(shí)運(yùn)行。這個(gè)實(shí)時(shí)系統(tǒng)在最近幾個(gè)小時(shí)數(shù)據(jù)上預(yù)計(jì)算查詢(xún)函數(shù)。要計(jì)算一個(gè)查詢(xún)函數(shù),需要查詢(xún)批處理視圖和實(shí)時(shí)視圖,并把它們合并起來(lái)以得到最終的數(shù)據(jù)。
圖3 計(jì)算一個(gè)查詢(xún)
在實(shí)時(shí)層,可以使用Riak或者Cassandra這種讀寫(xiě)數(shù)據(jù)庫(kù),而且實(shí)時(shí)層依賴(lài)那些數(shù)據(jù)庫(kù)中對(duì)狀態(tài)更新的增量算法。
讓Hadoop模擬實(shí)時(shí)計(jì)算的工具是Storm。我寫(xiě)Storm的目的是讓Hadoop可以健壯、可擴(kuò)展地處理大量的實(shí)時(shí)數(shù)據(jù)。Storm在數(shù)據(jù)流上運(yùn)行無(wú)限的計(jì)算,并且對(duì)這些數(shù)據(jù)處理提供了強(qiáng)有力的保障。
讓我們回到剛才那個(gè)根據(jù)某個(gè)URL查詢(xún)某個(gè)頁(yè)面在某個(gè)時(shí)間段內(nèi)頁(yè)面訪(fǎng)問(wèn)量的例子,通過(guò)這個(gè)例子我將展示實(shí)時(shí)層是如何工作的。
批處理系統(tǒng)還是跟之前一樣:一個(gè)基于Hadoop和ElephantDB的批處理工作流,在幾個(gè)小時(shí)之前的數(shù)據(jù)上預(yù)計(jì)算查詢(xún)函數(shù)。剩下就是讓實(shí)時(shí)系統(tǒng)去處理最近幾小時(shí)數(shù)據(jù)了。
我們將最近幾小時(shí)的數(shù)據(jù)狀態(tài)存入Cassandra中,用Storm去處理頁(yè)面訪(fǎng)問(wèn)量數(shù)據(jù)流并并行更新到數(shù)據(jù)庫(kù)中,針對(duì)每一個(gè)頁(yè)面訪(fǎng)問(wèn)量,在[URL, hour]所代表的key下,有一個(gè)計(jì)數(shù)器,這個(gè)計(jì)數(shù)器在Cassandra中實(shí)現(xiàn)。這就是所有的事情,Storm讓事情變得非常簡(jiǎn)單。
圖4 批處理/實(shí)時(shí)架構(gòu)示例
批處理層+實(shí)時(shí)層、CAP定理和人為錯(cuò)誤容忍性
貌似又回到一開(kāi)始提出的問(wèn)題上去了,訪(fǎng)問(wèn)實(shí)時(shí)數(shù)據(jù)需要使用NoSQL數(shù)據(jù)庫(kù)和增量算法。這就說(shuō)明回到了版本化數(shù)據(jù)、矢量時(shí)鐘和讀取修復(fù)這些復(fù)雜問(wèn)題中來(lái)。但這是有本質(zhì)區(qū)別的。由于實(shí)時(shí)層只處理最近幾小時(shí)的數(shù)據(jù),所有實(shí)時(shí)層的計(jì)算都會(huì)被最終批處理層重新計(jì)算。所以如果犯了什么錯(cuò)誤或者實(shí)時(shí)層出了問(wèn)題,最終都會(huì)被批處理層更正過(guò)來(lái),所有復(fù)雜的問(wèn)題都是暫時(shí)的。
這并不意味著不需要關(guān)心實(shí)時(shí)層的讀取修復(fù)和最終一致性,你仍然需要實(shí)時(shí)層盡可能的一致。但當(dāng)犯了一個(gè)錯(cuò)誤時(shí),不會(huì)永久性地破壞數(shù)據(jù)。這便移除了許多你所需要面對(duì)的復(fù)雜問(wèn)題。
在批處理層僅需要考慮數(shù)據(jù)和數(shù)據(jù)上的查詢(xún)函數(shù),批處理層因此很好掌控。在實(shí)時(shí)層,需要使用增量算法和復(fù)雜的NoSQL數(shù)據(jù)庫(kù)。把所有的復(fù)雜問(wèn)題獨(dú)立到實(shí)時(shí)層中,對(duì)系統(tǒng)的魯棒性、可靠性做出了重大貢獻(xiàn)。
同樣的,實(shí)時(shí)層并沒(méi)有影響系統(tǒng)的人為錯(cuò)誤容忍性,這個(gè)數(shù)據(jù)不可變和只追加的批處理系統(tǒng),仍然是整個(gè)系統(tǒng)的核心,所以所有的都可以像上面說(shuō)的一樣被糾正過(guò)來(lái)。
我有一個(gè)類(lèi)似的系統(tǒng):Hadoop和ElephantDB組成批處理系統(tǒng),Storm和Cassandra組成實(shí)時(shí)系統(tǒng)。由于缺乏監(jiān)控,某天當(dāng)我起床的時(shí)候發(fā)現(xiàn)Cassandra運(yùn)行滿(mǎn)負(fù)荷了,使得所有的數(shù)據(jù)請(qǐng)求都超時(shí)。這使得Storm計(jì)算失敗,一些數(shù)據(jù)又重新回到了等待隊(duì)列中,這個(gè)數(shù)據(jù)就一次次重復(fù)請(qǐng)求。
如果我沒(méi)有批處理層,那么我就需要擴(kuò)展和恢復(fù)Cassandra,這個(gè)很不容易。更糟的是,因?yàn)檎?qǐng)求不斷的重復(fù),無(wú)法得到正確的數(shù)據(jù)。
幸運(yùn)的是,所有的復(fù)雜問(wèn)題都被隔離到實(shí)時(shí)層中去了,我清空了所有的后臺(tái)請(qǐng)求隊(duì)列,把它們打到了批處理層上,同時(shí)重啟了Cassandra集群,過(guò)了幾個(gè)小時(shí)之后所有數(shù)據(jù)都恢復(fù)正常了。沒(méi)有錯(cuò)誤數(shù)據(jù),請(qǐng)求中也沒(méi)有不準(zhǔn)確的地方。
垃圾回收
上面描述的所有東西都是建立在一個(gè)不可變的、不斷增長(zhǎng)的數(shù)據(jù)集上的。如果數(shù)據(jù)集已經(jīng)很大,使得不可能用水平擴(kuò)展儲(chǔ)存所有時(shí)間的所有數(shù)據(jù),該如何處理呢?這是不是就推翻了我說(shuō)的一切呢?是不是需要回到可變數(shù)據(jù)的系統(tǒng)上呢?
不。我們可以很容易地用“垃圾回收”對(duì)基本模型進(jìn)行擴(kuò)展來(lái)解決上面的問(wèn)題。垃圾回收是一個(gè)在主數(shù)據(jù)集上的簡(jiǎn)單函數(shù),返回的是一個(gè)過(guò)濾版本的主數(shù)據(jù)集。垃圾回收掉了舊數(shù)據(jù),可以選擇任意的垃圾回收策略??梢栽谝鬃兊南到y(tǒng)中只保留數(shù)據(jù)最新的一個(gè)值或者保留每個(gè)數(shù)據(jù)的歷史。比如,如果要處理位置數(shù)據(jù),可以保留每人每年的一個(gè)地點(diǎn)??勺冃允且粋€(gè)不是很靈活的垃圾回收形式(它跟CAP定理交互得也很糟糕)。
垃圾回收可以被實(shí)現(xiàn)成批處理的一個(gè)任務(wù),隔段時(shí)間運(yùn)行一下。由于它是作為離線(xiàn)批處理任務(wù)執(zhí)行的,所以不影響我們與CAP定理的交互。
總結(jié)
讓可擴(kuò)展的數(shù)據(jù)系統(tǒng)復(fù)雜的原因不是CAP系統(tǒng),而是數(shù)據(jù)增量算法和數(shù)據(jù)的可變狀態(tài)。最近由于分布式數(shù)據(jù)庫(kù)的興起導(dǎo)致了復(fù)雜度越來(lái)越不可控。前面講過(guò),我將挑戰(zhàn)對(duì)傳統(tǒng)數(shù)據(jù)系統(tǒng)構(gòu)建方法的假設(shè)。我把CRUD變成了CR,把持久化層分成了批處理和實(shí)時(shí)兩個(gè)層,并且得到對(duì)人為錯(cuò)誤容忍的能力。我花費(fèi)了多年來(lái)之不易的經(jīng)驗(yàn)打破我對(duì)傳統(tǒng)數(shù)據(jù)庫(kù)的假設(shè),并得到了這些結(jié)論。
批處理/實(shí)時(shí)架構(gòu)有許多有趣的能力我并沒(méi)有提到,下面我總結(jié)了一些。
算法的靈活性。隨著數(shù)據(jù)量的增長(zhǎng),一些算法會(huì)越來(lái)越難計(jì)算。比如計(jì)算標(biāo)識(shí)符的數(shù)量,當(dāng)標(biāo)識(shí)符集合越來(lái)越大時(shí),將會(huì)越來(lái)越難計(jì)算。批處理/實(shí)時(shí)分離系統(tǒng)給了你在批處理系統(tǒng)上使用精確算法和在實(shí)時(shí)系統(tǒng)上使用近似算法的靈活性。批處理系統(tǒng)計(jì)算結(jié)果會(huì)最終覆蓋實(shí)時(shí)系統(tǒng)的計(jì)算結(jié)果,所以最終近似值會(huì)被修正,而你的系統(tǒng)擁有了“最終精確性”。
數(shù)據(jù)結(jié)構(gòu)遷移變得很容易。數(shù)據(jù)結(jié)構(gòu)遷移的難題將一去不復(fù)返。由于批量計(jì)算是系統(tǒng)的核心,很容易在整個(gè)系統(tǒng)上運(yùn)行一個(gè)函數(shù),所以很容易更改你數(shù)據(jù)的結(jié)構(gòu)或者視圖。
簡(jiǎn)單的Ad-Hoc網(wǎng)絡(luò)。由于批處理系統(tǒng)的任意性,使得你可以在數(shù)據(jù)上進(jìn)行任意查詢(xún)。由于所有的數(shù)據(jù)在一個(gè)點(diǎn)上都可以獲取,所以Ad-Hoc網(wǎng)絡(luò)變得簡(jiǎn)單而且方便。
自我檢查。由于數(shù)據(jù)是不可變的,數(shù)據(jù)集就可以自我檢查。數(shù)據(jù)集記錄了它的數(shù)據(jù)歷史,對(duì)于人為錯(cuò)誤容忍性和數(shù)據(jù)分析很有用。
我并沒(méi)有說(shuō)我已經(jīng)“解決”了數(shù)據(jù)量過(guò)大的問(wèn)題,但我已經(jīng)為解決大數(shù)據(jù)問(wèn)題制訂了一個(gè)框架。批處理/實(shí)時(shí)架構(gòu)可以應(yīng)用到任何一個(gè)數(shù)據(jù)系統(tǒng)中去,“授人以魚(yú),不如授人以漁”,我已經(jīng)告訴你了如何去構(gòu)建這樣的系統(tǒng)。
為了提高系統(tǒng)整體能力來(lái)解決大數(shù)據(jù)的問(wèn)題,我們還有許多工作需要做。
- 擴(kuò)展數(shù)據(jù)模型,支持批量寫(xiě)和隨機(jī)讀。不是每一個(gè)應(yīng)用程序都支持key/value的數(shù)據(jù)庫(kù),這也是我們團(tuán)隊(duì)對(duì)擴(kuò)展ElephantDB,使得可以支持搜索、文檔數(shù)據(jù)庫(kù)、區(qū)間查詢(xún)感興趣的原因。
- 更好的批處理原語(yǔ)。Hadoop并不是批處理的最終形態(tài),好多批處理計(jì)算Hadoop效率不高。Spark是一個(gè)有意思的擴(kuò)展MapReduce的項(xiàng)目。
- 提升后的讀寫(xiě)NoSQL數(shù)據(jù)庫(kù)。這里不同類(lèi)型數(shù)據(jù)的數(shù)據(jù)庫(kù)還有很大的提升空間,隨著這些數(shù)據(jù)庫(kù)的成熟,它們將收獲很多。
- 高層級(jí)的抽象。未來(lái)工作中最有意思的就是對(duì)批處理模塊和實(shí)時(shí)處理模塊的高層次抽象,在批處理和實(shí)時(shí)架構(gòu)下你沒(méi)有理由不擁有一個(gè)簡(jiǎn)單的、描述性的、魯棒性好的語(yǔ)言。
許多人需要一個(gè)可擴(kuò)展的關(guān)系型數(shù)據(jù)庫(kù),本文就是想讓你知道完全不需要那個(gè)。大數(shù)據(jù)量和NoSQL運(yùn)動(dòng)使數(shù)據(jù)管理比RDBMS更加復(fù)雜。那僅僅是因?yàn)槲覍?duì)大數(shù)據(jù)的處理采用了跟RDBMS同樣的方法:把數(shù)據(jù)和視圖混為一談,并且依賴(lài)增量算法。大數(shù)據(jù)量需要采用完全不同的方式構(gòu)建數(shù)據(jù)系統(tǒng)。通過(guò)存儲(chǔ)持續(xù)增長(zhǎng)的不可變數(shù)據(jù),并且系統(tǒng)核心采用預(yù)計(jì)算,大數(shù)據(jù)系統(tǒng)就可以變得比關(guān)系型數(shù)據(jù)庫(kù)更易掌控,并且可擴(kuò)展性很強(qiáng)。
更多網(wǎng)站建設(shè)IT行業(yè)資訊:開(kāi)發(fā)者需要Mac的理由是什么?
-
杭州網(wǎng)站設(shè)計(jì)公司:品牌網(wǎng)站開(kāi)發(fā)助力企業(yè)成長(zhǎng)
日期:2024-12-20瀏覽次數(shù):146次
-
杭州網(wǎng)站建設(shè)公司:商城網(wǎng)站建設(shè)的六大關(guān)鍵步驟
日期:2024-12-18瀏覽次數(shù):244次
-
杭州網(wǎng)站制作:醫(yī)院網(wǎng)站設(shè)計(jì)與域名備案的復(fù)雜性探討
日期:2024-12-18瀏覽次數(shù):265次
-
杭州網(wǎng)站制作公司:打造安全可靠的醫(yī)院網(wǎng)站
日期:2024-12-11瀏覽次數(shù):512次
-
杭州網(wǎng)站設(shè)計(jì)公司:數(shù)據(jù)庫(kù)在高端網(wǎng)站制作中的關(guān)鍵作用
日期:2024-12-11瀏覽次數(shù):485次
相關(guān)新聞
整合同類(lèi)新聞,相關(guān)新聞一手掌握
-
響應(yīng)式開(kāi)發(fā)技術(shù)
日期:2021-03-16瀏覽次數(shù):1600次
最新新聞
與互聯(lián)網(wǎng)同行,實(shí)時(shí)掌握網(wǎng)建行業(yè)最新動(dòng)態(tài)
-
淺談網(wǎng)站建設(shè)及運(yùn)營(yíng)
日期:2020-02-24瀏覽次數(shù):4032次
-
杭州app開(kāi)發(fā)的核心步驟
日期:2021-06-30瀏覽次數(shù):3858次
-
移動(dòng)端主流杭州定制app模式是怎樣的?
日期:2021-11-15瀏覽次數(shù):3244次
-
梅州網(wǎng)站模板開(kāi)發(fā)找誰(shuí)好?
日期:2023-02-08瀏覽次數(shù):1545次
-
企業(yè)做杭州網(wǎng)站制作,要著重哪幾個(gè)環(huán)節(jié)?
日期:2023-09-28瀏覽次數(shù):2033次
隨機(jī)新聞
新聞新動(dòng)態(tài),您需要的新聞管家
洞悉市場(chǎng)趨勢(shì)演變讓傳播回歸社會(huì)
免費(fèi)獲取網(wǎng)站建設(shè)與網(wǎng)絡(luò)推廣方案報(bào)價(jià)
-
關(guān)于我們
杭州帷拓科技有限公司,是一家新型的全案網(wǎng)絡(luò)開(kāi)發(fā)公司,作為以互聯(lián)網(wǎng)高端網(wǎng)站建設(shè)、APP開(kāi)發(fā)、小程序開(kāi)發(fā)為核心的專(zhuān)業(yè)網(wǎng)絡(luò)技術(shù)服務(wù)供應(yīng)商,帷拓科技致力于全面分析市場(chǎng)環(huán)境、衡量與預(yù)測(cè)市場(chǎng)需求、整合區(qū)別于行業(yè)競(jìng)爭(zhēng)對(duì)手的絕對(duì)優(yōu)勢(shì),結(jié)合品牌理念深度挖掘項(xiàng)目?jī)?yōu)勢(shì)和產(chǎn)品價(jià)值,提升客戶(hù)品牌認(rèn)知、認(rèn)可度。
-
我們的客戶(hù)
帷拓科技?xì)v經(jīng)十年沉淀,與國(guó)內(nèi)外上千家客戶(hù)達(dá)成合作關(guān)系,其中穩(wěn)定合作的公司有:浙江華為、浙江移動(dòng)、浙江5G產(chǎn)業(yè)聯(lián)盟、浙江省社科院、綠城足球俱樂(lè)部、娃哈哈雙語(yǔ)學(xué)校、健康中國(guó)杭州峰會(huì)、科雷機(jī)電等,帷拓科技始終堅(jiān)持“帷有專(zhuān)業(yè),才能拓展無(wú)限”的服務(wù)理念,堅(jiān)持“認(rèn)真堅(jiān)持細(xì)節(jié)”的優(yōu)質(zhì)服務(wù)理念,不斷完善自身,成就企業(yè),最終實(shí)現(xiàn)共贏(yíng)。
-
我們的業(yè)務(wù)
帷拓科技主營(yíng)業(yè)務(wù)范圍包含互聯(lián)網(wǎng)高端網(wǎng)站建設(shè)、APP開(kāi)發(fā)、小程序開(kāi)發(fā)、商城網(wǎng)站建設(shè)、公眾號(hào)運(yùn)營(yíng)以及數(shù)字營(yíng)銷(xiāo)等,涵蓋了服務(wù)、房產(chǎn)、數(shù)碼、服裝、物流貿(mào)易等行業(yè),根據(jù)品牌現(xiàn)狀,為每個(gè)客戶(hù)量身定制項(xiàng)目整體服務(wù)方案,以敏銳的市場(chǎng)洞察力、創(chuàng)新的市場(chǎng)策劃能力,全面把握市場(chǎng)變化,為客戶(hù)實(shí)現(xiàn)從企業(yè)到消費(fèi)者的價(jià)值轉(zhuǎn)換。