本文發於infoq,https://www.infoq.cn/article/rhzs0KI2G*Y2r9PMdeNv 。轉回本身的博客。web
談到 NoSQL,必定會說起一致性(Consistency),按照 CAP 定理,有些 NoSQL 數據庫放棄了一致性,可是 NoSQL 放棄是必然的選擇嗎?數據庫
從 1970’s,關係型數據庫(RDB,Relational Database)被髮明以來,關係型數據庫就是構建應用的一般的選擇。關係型數據庫對用戶提供 ACID 保證,很是方便開發者使用。從 1990’s 開始,NoSQL 系統開始出現。NoSQL 系統是一類對立於關係數據庫的數據庫系統,他們從架構上放棄了傳統的關係型數據庫的的關係模型和 SQL 的接口。緩存
與 NoSQL 系統相伴而來的 2 個詞是 BASE 和 CAP,這 2 個詞對分佈式系統有着很是深遠的影響。我相信就是在這 2 個詞的影響下,不少 NoSQL 系統從架構的初始就放棄了一致性(consistency)選擇了一種最終一致性(Eventual consistency)和可用性 (Availability)。雖然我很是認同 CAP 和 BASE 這 2 個詞,可是我不認爲在 CAP 和 BASE 的做用下,NoSQL 系統選擇放棄一致性是一個必然的事情。網絡
首先來回顧一下 CAP 和 BASE 這 2 個概念的歷史。這 2 個概念都是由 Eric Brewer 提出的,Brewer 目前是 Google 公司的基礎設施部門(Infrastructure)的副總裁(VP,Vice President)。在 1997 年,在 SOSP(Symposium on Operating Systems Principles) 上,名爲的演講 [1] 總結了 Brewer 等人的近期工做,演講中說他們正在工做的集羣服務並無採用當時公認的具備 ACID 特性的關係型數據庫做爲架構,而是在架構上放棄了關係型數據庫的 ACID 特性。而且爲他們的這個架構選擇構造了一個新的詞 BASE,BASE 這個詞的選擇有刻意爲之成分,ACID 在英語裏有酸性的意思,而 BASE 有鹼性的意思,很明顯 BASE 是與?ACID 對立的。架構
ACID 和 BASE 分別是以下單詞的首字母縮寫:
ACID:Atomicity, Consistency, Isolation, Durability
BASE: Basically Available, Soft State, Eventual Consistency併發
BASE 主張放棄掉 ACID,主要是放棄 ACID 中的 Consistency,而且讓系統達到基本可用(Basically Available),柔性狀態(Soft State),最終一致(Eventual Consistency)。系統構建者能夠不只僅選擇 ACID,BASE 也稱爲一種選擇,也就是在 ACID 和 BASE 中選擇其一。本質上來說,就是在 ACID 表明的一致性 (Consistency) 和 BASE 表明的可用性(Availability)兩者之間作出選擇。雖然在 BASE 提出時,尚未明確說明在一致性和可用性間作出架構選擇,可是已經爲後面 CAP 的提出作好了伏筆。運維
到 2000 年,Brewer 在 PODC(Principles of Distributed Computing)作了名爲 [2] 的演講,演講的主旨是闡明如何構建健壯的分佈式系統。在此次演講中,Brewer 近一步分析比較了 ACID 和 BASE,而且抽象了 ACID 和 BASE 的核心特性,也就是 ACID 的一致性(Consistency),BASE 的可用性(Availability),而且擴展了第 3 個維度,也就是網絡分區(Network Partition),從而提出了CAP 猜測,這個猜測說:分佈式
在分佈式系統中,最多能同時知足如下 3 個屬性中的 2 個:
C (Consistency), A (Availability), P (Tolerance to network Partitions)ide
根據這個猜測,會存在 3 類系統:大數據
放棄 P,系統具備 CA 特性,這類系統諸如單機數據庫
放棄 A,系統具備 CP 特性,這類系統諸如分佈式數據庫、分佈式鎖
放棄 C,系統具備 AP 特性,這類系統諸如 web caching、DNS
可用性是很是重要的一個特性,特別是在互聯網行業中,服務宕機對商業的影響是很是大的,因此依據 CAP 定理放棄一致性也就是天然的選擇了。特別是在 Amazon 的 CTO Werner Vogels 詳細介紹了 Eventually Consistent[5] 和 Amazon 的 Dynamo 系統的論文 [12] 發表後,大量追求可用性放棄一致性的 NoSQL 系統出現。
到了 2002 年,GilBert 和 Lynch[3],從新定義了 CAP 這 3 個屬性(從新定義的屬性比 Brewer 猜測中的屬性的範圍小了不少),而且證實了 CAP 這 3 個屬性不能同時達到,從而將 CAP 猜測變成了CAP 定理。
CAP 定理中的 3 個屬性定義以下 [3,6]:
Consistency: 是指原子一致性(Atomic consistency)或者線性一致性(linearizable consistency),這是一種很是高的一致性級別,不多有系統可以達到。
Availability: 是指徹底的可用性,也就是每一個到達每一個沒有宕機的節點上的讀寫請求都能在一個合理的時間返回一個響應。這裏的關鍵點是每一個請求到達每一個非宕機的節點。這也是一種很是高的可用性水平,也不多有系統可以達到。
Partition Tolerant: 是指系統可以在出現網絡分區的狀況下,繼續正確響應,即保持系統該有的特性,或者說保持一致性或者可用性。
Glibert 和 Lynch 從新定義的 CAP 定理很是嚴謹,可是隻證實了 3 個屬性不能同時具備。然而 Brewer 猜測中的 3 個屬性的定義、3 選 2 的描述,3 分的分類法(AP,CP,CA3 種分類)卻不是很是嚴謹,這也是 CAP 出現以後,不少人懷疑和挑戰 CAP 的緣由。Brewer 在 2012 年從新寫了一篇文章 [4],也認可最初的 CAP 表述很是使人誤解。事實上,CAP 定理的適用範圍是很是小的。 雖然 CAP 從出生開始就有不少問題,可是它仍然推進了 NoSQL 運動,不少系統架構者依據 CAP 定理,主動放棄了一致性,但實際上,不少時候這些系統都是不知足 CAP 定理的適用範圍的。
CAP 的故事到此並未完結,2017 年,Brewer 已是 Google 公司的基礎設施(Infrastructure)部門的副總裁(VP,Vice President)了,而且這時 Google 公司的第一代 Spanner 系統已經誕生 [9]。Brewer 寫了一篇文章講述了 Google 公司的 Spanner 系統 [7],而且近一步闡述了按照 CAP 定理 Spanner 是一個什麼樣特性的系統。在文中,Brewer 指出 Spanner 系統說是 " 實際上的 CA"(effectively CA)系統。從架構上來說,Spanner 是一個 CP 系統,也就是說當出現網絡分區時,Spanner 選擇的是保證數據的一致性,放棄可用性的。但實際上,Spanner 是具備很是高可用性效果的一個系統,從架構上 Spanner 沒有達到 CAP 定理要求的那種徹底可用性,可是也達到很是高的可用性,因爲採用多副本的設計,個別副本出現網絡分區,並不影響用戶能感知到的可用性。按 CAP 定理的定義,當這些個別副本出現網絡分區時,這些節點是不可用的,也就是系統沒有達到徹底可用性。可是此時的用戶請求是能夠被其餘副本服務的,此時服務是可用的,也就是說用戶仍然感知到 Spanner 是可用的。因此說用戶感知的可用性和 CAP 定理中的可用性不是一個概念。咱們追求的應該是用戶感知的可用性。
用戶可感知的可用性,一般用 SLA 來表示,也就是咱們一般說的幾個 9 的可用性。Brewer 在文章中也給出了 Google 關於 Spanner 系統的 SLA 的數據,從數據咱們能夠看到,因爲網絡分區致使的服務可用的比例是比較小的,有很大一部分致使服務不可用的緣由是諸如軟件 bug、配置錯誤、運維誤操做等致使的。也就是說,即使在架構上採用了達到 CAP 定理要求的可用性,實際用戶可感覺到的服務可用性,也就 SLA 也不會提升多少。這也是我從業這麼多年的一個體會,系統的不穩定更多來自系統開發者的平常失誤,增強代碼質量,增強開發流程規範,增強生產運維規範,更能大大提升系統的可用性。因此,在架構層面,由於可用性放棄一致性每每是得不償失的。
雲計算的大潮下,不放棄一致性也是很是明智的。一個託管在雲上的數據存儲服務,若是你放棄了一致性選擇可用性,用戶是感覺不明顯,由於使用者不會對架構設計採用達到的 CAP 定理的可用性而買單,用戶只會爲你的服務達到 SLA 買單。然而數據存儲服務是否具備一致性,用戶是可以很是明顯的感覺到的。Amazon 公司的內部的 Dynamo[12] 在架構上是能夠達到 CAP 定理中的可用性要求的,可是 Amazon 在 AWS 雲上售賣的 DynamoDB 並非採用的這一架構,也許就是出於這個緣由 [10]。
那麼咱們選擇一致性獲得的好處是什麼那?不少時候,說到一致性時,都會拿金融和錢相關的例子來講明一致性的必要性,可是我相信金融行業並不強依賴一致性 [10]。我認爲一致性給我帶來的是開發的方便性。Brewer 雖然提出了 BASE 概念,可是他並無詳細闡述這個概念。2008 年 EBay 公司的 Dan Pritchett,寫了一遍文章 [8],經過舉例詳細闡述了在放棄了 ACID 之後,如何採用 BASE 架構實現相同的需求,向咱們推薦了 BASE 這種架構模式。經過這篇文章,咱們我能夠看到若是放棄了 ACID 而選擇 BASE 的話,原本一個很是簡單的功能,須要加入消息隊列等手段才能讓系統達到最終一致性,應用的總體架構複雜了不少。
相似於 Pritchett 文章中說明的同樣,使用不具備一致性的 NoSQL 系統,你須要仔細甄別你的使用場景,判斷你的使用場景是否可讓你放棄一致性。即使你要使用 BASE 架構,也不是簡單地採用一個具備最終一致性的 NoSQL 系統,替換掉 ACID 數據庫就行了,你須要設計好各類手段,處理掉具備最終一致性的 NoSQL 系統帶來的異常,讓你的整個應用達到柔性狀態和最終一致。BASE 中所說的最終一致和不少 NoSQL 系統所具備的最終一致有些細微的差異。這個差異簡單來講是,BASE 中所說的最終一致是保證系統狀態是正確的;而不少 NoSQL 系統最終一致只保證最終一致,可是不保證這個狀態是你想要的正確的狀態 [11]。
最後,我的的一個觀點是,若是一個 NoSQL 系統作爲緩存使用,爲了追求低延時,能夠放棄一致性,大數據和離線計算的場景相似於這種場景,不少 NoSQL 系統是很是適用的;可是若是 NoSQL 系統做爲數據庫來用,那麼這個 NoSQL 系統最好不要由於可用性放棄一致性,同時經過多副本技術和良好運維達到實際的高可用性,即達到實際上的 CA(effectively CA),這樣能夠大大下降使用者的使用負擔。
因爲篇幅所限,本文中關於一致性、CAP、BASE、ACID 的不少技術細節的闡述未能詳盡,擬另行成文討論。成文倉促,有錯漏之處歡迎各位大神指正。
做者簡介:陳東明,餓了麼北京技術中心架構組負責人,負責餓了麼的產品線架構設計以及餓了麼基礎架構研發工做。曾任百度架構師,負責百度即時通信產品的架構設計。具備豐富的大規模系統構建和基礎架構的研發經驗,善於複雜業務需求下的大併發、分佈式系統設計和持續優化。
本文爲雲棲社區原創內容,未經容許不得轉載。