著名的分散式事務資料庫谷歌Spanner設計有坑!

banq發表於2018-09-22
CAP定理指出,在網路分割槽的情況下,不可能同時保證一致性和可用性。由於網路分割槽在可擴充套件的分散式系統中理論上是可行的,因此現代可擴充套件資料庫系統的架構師分為兩大陣營:優先考慮可用性的陣營(NoSQL陣營)和優先考慮一致性的陣營(NewSQL陣營)。

有一段時間,NoSQL陣營顯然是兩者中的主導者 - 在“永遠線上”的網際網路世界中,停機時間是不可接受的,開發人員被迫降低一致性水平。

在過去的十年中,應用開發人員發現,在不保證一致性的資料庫系統上構建無錯誤的應用程式非常困難。這導致了驚人轉變的動力,許多最近釋出的系統都聲稱保證一致性(並且是來自CAP的CP)。包括在新的系統中是:Spanner(和 Cloud Spanner),FaunaDB,CockroachDB和YugaByte。在這篇文章中,我們將更深入地研究這四個系統(以及類似系統)的一致性宣告,並注意到雖然有些確實保證了一致性,但是其實並不能完全保證一致性。我們將追蹤故障失敗,以驗證Spanner所做的一致性設計決策,而這在其他系統中已被悲慘地和不完美地模仿。

什麼是一致性?
一致性,也稱為“原子一致性”或“線性化”,保證一旦寫入完成,所有未來的讀取都將是立即是剛寫入的值。例如,假設我們有一個名為X的變數,其值當前為4.如果我們執行以下程式碼:
X = 10; Y = X + 8;

在一致的系統中,執行此程式碼後Y只有一個可能的值(假設第二個語句在第一個語句完成後執行):18。

在一個不保證一致性的系統中,執行此程式碼後Y的值也可能是18.但是有可能它是12(因為X的原始值是4)。即使系統返回一個明確的訊息:“我已經完成了X = 10語句”,但仍然有可能後續讀取X將反映舊值(4)而Y將最終為12。

因此,應用程式開發人員必須知道Y不是18的非零可能性,並且必須在後續程式碼中處理Y的所有可能值。這非常複雜,超出了應用程式開發人員的能力。

[附註:“一致性”的另一個名稱是“強一致性”。這個替代名稱是為了區分完整一致性保證和較弱的一致性級別而區分的,這些一致性級別在其名稱中也使用了“一致性”一詞(儘管沒有提供完整的一致性保證)。實際上,這些較弱的一致性級別中有一些例如“因果一致性”,“會話一致性”和“有界陳舊性一致性”提供了有用的保證,可以在一定程度上降低應用程式開發人員的複雜性。儘管如此,避免在應用程式中存在錯誤可能性的最佳方法是在強一致性系統之上構建,以保證完整,強大的一致性。

為什麼要放棄一致性?
一致性是基礎,如果沒有就幾乎做不了事,那麼為什麼大多數NoSQL系統都無法保證一致性呢?他們責怪CAP定理,(例如,啟發了許多NoSQL系統的Amazon Dynamo論文,在“設計考慮因素”一節的第一段中提到了可用性與一致性的權衡,他們提出著名的“最終一致”架構。)在不保證一致性的系統上構建應用程式是非常困難的,但並非不可能。

但CAP定理表明,在存在網路分割槽時保證100%可用性,保證一致性的系統是不可能的。因此,你只能選擇一個,那麼選擇可用性是有意義的。

正如我們上面所說的,一旦系統無法保證一致性,在沒有醜陋的案例錯誤的情況下開發應用程式是非常具有挑戰性的,並且通常需要能夠處理這種開發環境的知識嚴謹的高技能應用程式開發人員。儘管如此,這些熟練的開發人員確實存在,並且這是避免CAP定理100%可用性的不可能性證明的唯一方法。

前一段的推理雖然可能經過深思熟慮和令人信服,但從根本上是有缺陷的。CAP定理存在於理論世界中,其中存在100%可用性。在現實世界中,沒有100%的可用性。高度可用的系統以“9s”定義。你有99.9%可用嗎?或99.99%可用?9s越多越好。可用性從根本上說是一種不完美的追求。沒有系統可以保證100%可用性。

當考慮CAP定理所聲稱的可用性與一致性權衡時,這一事實具有重大影響。如果我們保證一致性,我們就不能放棄可用性的保證。可是我們從來沒有保證100%可用性!相反,保證一致性反而更會降低我們已經不完善的可用性。

因此,問題變成:當我們保證一致性時,可用性會丟失多少?在實踐中,答案是會丟失很少。

保證一致性的系統僅在網路分割槽的情況下肯定會經歷一些可用性降低。隨著網路變得越來越冗餘(banq注:資料複製到位),分割槽變得越來越少見,即使存在分割槽,仍然可以使多數分割槽可用的策略(法定人數)。只有少數分割槽就只能判斷為不可用。

因此,除非存在一個客戶端:在存在網路分割槽情況下正在與少數分割槽(而不是多數分割槽)中節點進行通訊,這個客戶端可用性就非常低。但是這種情況通常比系統其他不可用原因更罕見。

因此,同時保證高可用性和一致性在現實中是可能的。


一致性NEWSQL系統的輝煌迴歸
上面的論點實際上導致現代系統選擇CP而不是AP(即選擇可用性的一致性)的3個不同原因:
(1)不能保證一致性的系統會導致複雜,昂貴且經常出錯的應用程式程式碼。
(2)由於保證一致性而導致的可用性降低是微不足道的,並且對於許多部署而言幾乎不可察覺。
(3)CAP定理從根本上說是不對稱的。CP系統可以保證一致性;AP系統卻不一定保證100%可用性(沒有系統可以保證100%的可用性)。

因此,只有CAP定理的一面為任何有用的保證開啟了大門。

我認為,上述三點導致分散式事務資料庫系統的驚人復興 - 其中許多已在過去幾年中已商業化 - 選擇CP而不是AP。對於AP系統及其相關的NoSQL實現,仍然有一席之地。但對於大多數開發人員來說,建立在CP系統之上是一個更安全的選擇。

但是,當我說CP系統是更安全的賭注時,我打算參考實際上保證一致性的一些CP系統,不幸的是,與他們聲稱的正好相反,這些現代NewSQL系統中有太多不能保證一致性。一旦這種保證被刪除,就會出現個別案件的錯誤、複雜性和成本回報。

Spanner是問題的根源

我在之前的帖子中已經討論過,有很多方法可以保證分散式系統的一致性。最流行的機制是以最低的可用性成本保證一致性,就是使用Paxos或Raft共識協議來強制跨資料的多個副本實現一致性。

在簡化的層面上,這些協議透過多數表決機制起作用。對資料的任何更改都需要大多數副本同意更改。這允許少數複製品停機或不可用,並且系統仍然可以繼續讀取或寫入資料。

大多數NewSQL系統使用這種共識協議來實現強一致性。但是,它們在如何使用這些協議方面存在顯著差異。我將NewSQL系統分為兩個類別:
第一類,如Calvin(來自我的研究小組)和FaunaDB等系統所體現的,每個資料庫使用一個單一的全域性共識協議。每個事務都參與相同的全域性協議。

第二類,如Spanner,CockroachDB和YugaByte等系統所體現,將資料劃分為“分片”,併為每個分片應用單獨的共識協議。

第一類的主要缺點是可擴充套件性。伺服器可以每秒處理固定數量的訊息。如果系統中的每個事務都參與相同的共識協議,則同一組伺服器對每個事務進行投票。由於投票需要通訊,因此每秒的投票數受每個伺服器可以處理的訊息數量的限制。這限制了系統可以處理的每秒事務總量。

Calvin和FaunaDB透過批處理來繞過這個缺點。他們不是單獨對每筆交易進行投票,而是對批次交易進行投票。每個伺服器在固定時間段(例如,10毫秒)內批處理它接收到的所有事務,然後立即啟動對整個批處理的投票。

憑藉每10毫秒的一個批次處理,Calvin能夠實現每秒超過500,000次交易的吞吐量。相比之下,即使在峰值工作負載期間,Amazon.com和NASDAQ也可能每秒處理不超過10,000個訂單/交易(事務)。

第二類的主要缺點是,透過在每個分片的基礎上本地化共識,在觸及多個分片中的資料的事務時保證一致性就變得非常重要。

典型的例子是有人在一個照片共享app上執行兩個動作的序列(1)刪除她的父母,讓他們無權檢視她的照片(2)釋出她的照片。即使從使用者的有利位置有明確的這些操作序列,如果許可權資料和照片資料這兩種位於單獨的分片中,並且分片單獨執行共識,則父母仍然可能有能力檢視使用者最近上傳的照片。

Spanner使用他們的TrueTime API解決了這個問題。所有事務都會收到一個基於實際(掛鐘)當前時間的時間戳。這使得對於兩個不同的事務,即使是由完全不相交的伺服器集處理的事務,存在“之前”和“之後”的概念。具有較低時間戳的事務是具有較高時間戳的事務“之前”。顯然,不同伺服器的時鐘可能存在少量偏差。因此,Spanner利用“不確定性”視窗的概念,該視窗基於系統中伺服器上時鐘的最大可能時間偏差。在完成寫入之後,事務會等到這個不確定性視窗過去之後才允許任何客戶端檢視他們寫入的資料。

Spanner因此面臨著可能不舒服的權衡。期望不確定性視窗應該儘可能小,因為隨著它變大,事務的等待時間增加,並且系統的整體併發性降低。

另一方面,它需要100%確定時鐘偏差永遠不會大於不確定性視窗(因為否則將不再保證一致性),因此較大的視窗比較小的視窗更安全。

Spanner透過使用GPS和原子鐘的專用硬體解決方案來處理這種權衡,以確保伺服器上的時鐘偏差最小。該解決方案允許系統保持不確定性視窗相對窄,同時保持不正確的不確定性視窗估計(和相應的一致性違反)的機率非常小。事實上,機率是如此之小,以至於Spanner的架構師感到很自在,聲稱Spanner“保證”一致性。

[值得注意的是,使用全球共識的系統完全避免了這個問題。如果每個事務都透過相同的協議,那麼所有事務的自然順序就會出現 - 順序只是協議期間事務的投票順序。當使用批次而不是事務時,它是在協議期間順序的批次,並且透過將批次識別符號與批次中的序列號組合來全域性排序事務。不需要使用時鐘時間來建立之前或之後的概念。相反,共識協議本身可用於優雅地建立全域性順序。]

(banq注:如何保證順序是設計分散式事務的關鍵之關鍵!Spanner敗在順序設計有漏洞上,區塊鏈為了保證順序,直接一個塊鏈到上一個塊,這種極端線性設計確實保證了順序,如同幼兒園小朋友手牽手,順序不會亂,人也不會丟,但是走起路就不方便,如同過獨木橋,吞吐量不夠,效率低!)

Spanner衍生品

Spanner是一個美觀和創新的系統。它也是由谷歌發明並在那裡廣泛使用的。無論是前者還是後者(或兩者),它都具有極大的影響力,許多系統(例如,CockroachDB和YugaByte)都受到了Spanner的架構決策的啟發。不幸的是,這些衍生系統只是純軟體,這意味著他們只繼承了軟體創新,而沒有Spanner那樣依賴谷歌的硬體和基礎設施。

鑑於Spanner決定每個分片具有單獨的共識協議,那些軟體衍生產品就會極其危險。與Spanner一樣,這些系統依靠現實世界的時間來實現一致性--CockroachDB的HLC(混合邏輯時鐘)和 YugaByte混合時間。與Spanner一樣,這些系統依賴於瞭解伺服器之間的最大時鐘偏差,以避免一致性違規。但與Spanner不同,這些系統缺乏硬體和基礎設施支援,以最小化和測量時鐘偏差不確定性。

值得稱道的是,CockroachDB已經承認,透過僅結合Spanner的軟體創新,系統無法保證CAP的一致性(如上所述,它是線性化的)。

然而,YugaByte繼續聲稱自己是保證一致性的。我建議人們不要相信這種說法。YugaByte憑藉其Spanner根源,當伺服器上的本地時鐘突然超出偏斜不確定性視窗時,會遇到一致性違規。

這可能發生在各種情況下,例如執行YugaByte的VM凍結或遷移到其他計算機時。即使沒有突然跳躍,YugaByte的免費版依賴於使用者設定有關最大時鐘偏差的假設。代表使用者的任何錯誤假設都可能導致一致性違規。

與CockroachDB和YugaByte相比,FaunaDB的靈感來自Calvin而不是Spanner。[歷史記錄:Calvin和Spanner的論文均於2012年出版]。

因此,FaunaDB具有單一、優雅的全球共識協議,並且在時鐘偏差假設方面不需要小的假設修補。因此,FaunaDB能夠保證修改資料庫中任何資料的事務的一致性,而不用擔心可能困擾Spanner風格系統的純軟體衍生品的個別案例違規。

我在過去談到的 Calvin風格的系統和Spanner風格的系統之間還存在其他差異。在這篇文章中,我們關注的可能是最重要的差異:全域性共識與分割槽共識,與任何架構決策一樣,需要在這兩個選項之間進行權衡,對於絕大多數應用程式來說,每秒超過500,000次交易超出了他們最大的夢想,如果是這樣,全球共識可能是更好的選擇。

DBMS Musings: NewSQL database systems are failing

相關文章