AWS Dynamo 系統設計概念,16 頁改變世界的論文

瞭解如何在你的系統設計中使用 Dynamo 系列、AWS DynamoDB、Cassandra 和 SimpleDB

在我們開始之前的快速介紹

早在 2004 年,亞馬遜正在運行一個大型的分佈式 Oracle 數據庫集羣。想象一下,大量的服務器,運行大量笨重的閉源專有軟件,並沒有真正關注規模和可用性。他們在當時的規模下挑戰了商業數據庫的極限。

重要的是要了解這是個不同的時代。分佈式系統並不常見,關係型數據庫是唯一的主要 OLTP 數據庫,最重要的是,當時沒有足夠的人或數據在線。

看到互聯網在過去十年或二十年裏的爆炸性增長,真是太瘋狂了!

此時,亞馬遜的服務正處於突破當時傳統 SQL 數據庫規模的邊緣,他們決定需要一個長期可持續的解決方案來繼續以他們的速度增長。

關係型數據庫是複雜的系統。它們在你可以運行的查詢類型方面給你很大的靈活性,給你很強的 ACID 兼容性,在表之間建立關係,並有能力連接表。這些功能不是免費的,是有代價的。其代價通常是有限的擴展性、可用性和較低的性能。

正如亞馬遜的首席技術官 Werner Vogels 解釋的那樣, 他們評估了他們 70% 的操作是基於主鍵的,另外 20% 沒有使用任何類型的 JOIN。因此,他們正在使用關係型數據庫,但他們意識到他們並不真正需要關係型數據庫提供的大部分優勢。此外,他們在橫向擴展他們的數據庫方面面臨着困難。

因此,他們在內部建立了一個名爲 "Dynamo" 的內部數據庫,並對其進行了數年的測試。2007 年,他們公開發布了一份白皮書:"Dynamo, 亞馬遜的高可用鍵值存儲",以幫助其他在關係型數據庫中面臨類似可擴展性問題的人。

這篇論文大受歡迎,成爲 NoSQL 數據庫背後的驅動力,現在 NoSQL 數據庫已經成爲任何大型科技組織的技術棧的重要組成部分。正如 Werner Vogels 所描述的,"Dynamo 論文廣受好評,成爲創建今天通常稱爲'NoSQL'的分佈式數據庫技術類別的催化劑。'"

Dynamo 能夠處理大量的規模,單個表能夠每秒提供數千萬個請求。最初的 Dynamo 在 2017 年就能每秒提供 1290 萬個請求。我相信,現在的 DynamoDB 加強了很多,可能會進一步突破極限。

Dynamo 最終激發了當今許多最流行的數據庫,如 AWS 的 SimpleDB 和 DynamoDB,以及 Cassandra。這些數據庫中的大多數,如 Cassandra,和 DynamoDB 最後都與 Dynamo 論文非常相似,通常有相同的優點和缺點。瞭解 Dynamo 論文也會幫助你更好地理解這個 Dynamo 系列的數據庫。

當我讀到這個似乎是有史以來最神奇的數據庫的成功、性能和幾乎像童話一樣的故事時,我想知道爲什麼其他數據庫仍在使用?亞馬遜的工程師們最終用什麼來換取這些在性能、規模和可用性方面的巨大收益?無限規模的實際成本是多少?它是否負擔得起?

Dynamo 系統的快速概述

Dynamo 描述了一個由多個節點構建的分佈式數據庫系統。

這些數據庫可以在彼此完全隔離的情況下運行,事實上,它們在物理上位於世界的不同地方。

它描述了該系統將是一個無主的系統。這意味着所有的節點都是同質的,行爲都是一樣的。

所有的數據都會分佈在這些相同的節點中,然後在它們之間進行復制。例如,如果我不得不存儲兩行,比方說僱員數據,dynamo 內部會將其存儲爲以下內容。

請注意,數據甚至可以在不同的洲上進行復制!

爲了保證性能,集羣往往不會等待所有節點真正寫入數據。例如,要寫一個 ID 爲 3 的新員工,Dynamo 可能會等待一個節點真正確認寫入,而其他節點甚至沒有完成寫入數據到磁盤,Dynamo 可能會返回一個響應給用戶,說寫入已經完成。

這意味着你的整個數據庫集羣可能處於不一致的狀態,一些節點可能會存儲某些行,而另一些節點可能不會。例如,在上圖中,有兩個節點沒有完成寫入新行,而其中一個節點已經完成。這意味着,在某種意義上,這些節點在行是否存在的問題上彼此不一致。不要擔心,這很正常。

最終,所有的節點都將完成新行的寫入,集羣將處於一致狀態。這是一個最終一致的數據模型,因爲整個集羣最終都會達到一致。

在我繼續之前,有必要指出這個新實體的存在,即集羣。在我職業生涯的早期,我曾在一臺服務器上運行一個 Postgres 數據庫,所以當我被介紹到分佈式數據系統的想法時,我很難理解集羣的概念。

爲了更好地理解這一點,不要把節點想成你必須管理的單個節點。想想一個全新的實體,即集羣。這個集羣是由這些運行在服務器上的單個更小、更簡單的數據庫進程組成的。

集羣實際上是在管理這些節點,照顧它們的健康,以及它們的通信,在需要時使更多的節點上升,在不需要時使節點下降。

有點像分行經理。

節點本身也意識到集羣,並意識到它們是集羣的一部分。節點之間可以相互交談,討論與集羣有關的信息。

你作爲一個客戶會經常與集羣進行互動,並經常關心整個集羣所表現出來的特徵,而不是個別節點。例如,集羣可能處於不一致的狀態,因爲有些節點會存儲更新的數據,而有些則可能沒有。

Dynamo 的論文如何改變了世界

亞馬遜的首席技術官維爾納 - 沃格爾斯(Werner Vogels)說。

"Dynamo 的論文廣受好評,成爲創建今天通常稱爲"NoSQL "的分佈式數據庫技術類別的催化劑。"

Dynamo 啓發了許多其他的 NoSQL 數據庫,併爲大規模的高可用分佈式數據存儲創建了一個框架。它已經被引用了 2000 多次,並影響了各種數據庫中分佈式數據存儲的工作方式。

簡單地說,簡單的關係型數據庫根本無法維持現代應用程序的寫入能力。大多數大型科技公司,如 Netflix、蘋果、Discord、AirBnB 等,都使用 Dynamo 系列數據庫(DynamoDB、Cassandra 等)中的一種。

"改變世界" 可能是一種誇張的說法,但 Dynamo 論文絕對是最具影響力的白皮書之一,並影響了許多現有的大型科技公司。

主要收穫和權衡

鍵值存儲

Dynamo 提出了一個鍵值數據存儲,這意味着不支持表,也不支持關係,等等。

你只能存儲鍵和它們相應的值。你使用的鍵將是你的分區鍵,這就是 Dynamo 用來計算將你的數據放在哪個分區的鍵。或者,從另一個角度看,分區鍵決定了你的數據將進入哪個節點。

分區鍵必須是唯一的,爲了確保在各節點間的平等分配,它應該能夠有一大組分佈大致相同的值。

例如,假設我必須存儲這些數據。

| ID | Name | Location

| 1 | Sanil Khurana | Delhi
| 2 | Prerna Sharma | Delhi
| 3 | Shivam Kalra | Bangalore
| 4 | Nilesh Jain | Delhi
| 5 | Hardik | Chennai

如果我選擇 Location 作爲分區鍵,這將意味着我的集羣中的每個節點將負責存儲與某一組地點相關的數據。

在上面的例子中,你可以看到,每個節點都被指定爲存儲一個位置。

這已經顯示出問題。根據人口和你的組織可能針對的地點,有些地方必然比其他地方更受歡迎。例如,你的平臺在德里比在欽奈被更多地使用。這導致了數據在你的節點上的不平衡分佈。由於所有的節點都是同質的,你正在浪費那些沒有存儲大量數據的節點的資源。

然而,基於 ID 的數據存儲可能要好得多。你的應用邏輯可以爲每個數據項分配一個增量 ID 或一個隨機 ID,你可以根據這個 ID 來劃分你的數據。

儘管這種數據模型相當簡單,但 Dynamo 系列數據庫已經發展到支持更復雜的數據模型。DynamoDB 和 Cassandra 確實支持表,但沒有分區鍵是不可能查詢的。

它們還支持基本的排序水平,限制返回的結果等。總之,Dynamo 論文的迭代能夠支持更豐富的模型,儘管它缺乏關係型數據庫一般所具有的功能。

選擇你的分區鍵也有其他細微差別。Dynamo 系列數據庫支持較弱的 ACID 模型,其中一些基本的隔離或交易或一致性水平是可以實現的。當你與之交互的行在同一個分區上時,這些通常是可能的。

因此,Dynamo 的數據模型是非常簡單的。DynamoDB 和 Cassandra 支持更豐富的數據模型,但仍然沒有任何關係,關係,靈活的查詢,等等。

選擇你的分區鍵是決定你的數據模型的一個非常重要的部分,需要比關係型數據庫考慮得更多。

不太靈活的查詢模式

Dynamo 暴露了一個更簡單、更受限制的查詢模型。

它只暴露了兩個函數,get(partition key) 和 put(partition key, object)。這意味着不支持排序數據,限制返回的行數,等等,你通常會在關係型數據庫中發現。

然而,正如我之前解釋的那樣,Cassandra 和 DynamoDB 提供了一個更豐富的模型,能夠過濾數據(類似於 SQL 中的 WHERE),對數據進行排序,限制行數等。它們仍然有侷限性,主要是由於數據必須存儲在不同的節點上。

你一般會受到你的分區主鍵的限制,如果你還沒有意識到,這非常重要。

分佈式

Dynamo 作爲一個分佈式系統工作。在一個單節點系統中運行它是沒有意義的。如果你正在運行 Dynamo,你有可能正在運行幾十個甚至幾百個節點,因爲這正是 Dynamo 的優勢所在。

缺少 ACID 支持

"亞馬遜的經驗表明,提供 ACID 保證的數據存儲往往有很差的可用性。這一點已經被業界和學術界廣泛認可 [5]。Dynamo 的目標是以較弱的一致性(ACID 中的"C")操作的應用程序,如果這能帶來高可用性。Dynamo 不提供任何隔離保證,只允許單鍵更新。"

正如論文中所說的那樣,Dynamo 不支持 ACID 屬性。它沒有支持更高的一致性,而是提出了一個 AP 系統,其目標是可用性而不是一致性。

這是有道理的。對於很多應用來說,嚴格的一致性可能是很重要的。這意味着你的集羣中的節點應該總是同意數據的當前狀態。例如,如果你正在處理與支付有關的數據,嚴格的一致性可能很重要。想象一下,如果集羣中的節點在你的賬戶上有多少錢上有分歧。有些節點會允許借記交易,有些節點可能會拒絕。

然而,嚴格的一致性是有代價的。這個代價往往是可用性、性能和耐久性。

對於大多數應用來說,如果你的數據存儲處於不一致的狀態並不重要。例如,如果一些節點認爲某條推文有 2000 個贊,而一些節點認爲有 2,001 個,這並不重要。有些用戶可能看到 2000 個,有些可能看到 2,001 個,但這幾乎不影響用戶體驗。Dynamo 是爲這些應用而建立的。在這裏,一致性並不重要,可用性和性能纔是最重要的。

順便提一下,Dynamo 確實給了你一個可調整一致性的選項。簡單地說,你可以定義你想要的一致性水平。這有更多的細微差別,但也可以有嚴格的一致性,儘管是以可用性爲代價。這個概念需要更多的深度,所以,爲了節省時間,我暫時跳過它。然而,如果你想讓我寫更多關於這個問題的文章,請在評論中告訴我。

可線性擴展的寫入性能

當你橫向擴展關係型數據庫時,你並不能獲得系統中所有節點的全部力量。這是因爲在水平擴展的集羣中運行的關係數據庫,特別是當每個節點只存儲關係的一部分,而不是整個關係的時候,會爲了最簡單的查詢而不斷地互相交談。

例如,假設你有一個簡單的客戶表,在 Postgres 的三個節點之間分片,所以每個節點都存儲了整個表的一些行。由於你爲每一行存儲了電子郵件地址和電話號碼,你也想確保這些在整個表中是唯一的(同樣,它跨越了多個節點)。

如果你要寫一個新的客戶,你首先要決定把它寫在哪個節點上,然後檢查其他節點上是否有相同的電話號碼或電子郵件地址的客戶存在,然後再寫它。

在做這些工作的同時,你還需要確保其他節點上沒有新的客戶被寫入,因爲兩個具有相同電子郵件或電話的客戶可能同時被寫入,從而破壞了 UNIQUE 約束。現在想象一下,如果這些節點在物理上也相距甚遠。

即使在這樣一個簡單的場景中,已經可以看出關係型數據庫中的分片是多麼複雜。添加更多的節點也會增加每個現有節點的工作,因爲現在它需要與另一個節點連接、交談和閒談。

Dynamo 背後的道理很簡單。單個節點無法維持所需的讀寫數量。解決這個問題的唯一方法是建立一個具有橫向擴展能力的多節點系統。Dynamo 是爲了呈現一個可以輕鬆處理數百、數千甚至更多節點的系統。它之所以這樣做,是因爲它可以線性地擴展寫入性能。

因此,目標應該是,增加一個節點不會增加其他節點的工作。每個節點只傳遞所需的信息,Dynamo 不承諾驗證或唯一的約束或其他功能,這將增加系統中節點的負擔。

Netflix 進行了大量的測試,以瞭解 Cassandra(屬於 Dynamo 數據庫家族)在增加節點數時的表現。這張圖完美地總結了這個線性比例。

你可以看到,增加更多的節點並不會降低其他節點的性能。

在哪裏使用 Dynamo 家族的數據庫?

我認爲維爾納 - 沃格爾斯真的很好地總結了這一點。

"我們的目標是建立一個具有無限制的可擴展性、一致的性能和高可用性的數據庫,以支持我們快速增長的業務需求。" - Werner Vogels

Dynamo 和 Dynamo 系列數據庫提出了一個理念,即以一致的性能保證來存儲絕對大量的難以想象的數據。它承諾了高可用性、低延遲和可線性擴展的寫入性能。

但它犧牲了其數據模型和查詢能力的靈活性,並且缺乏 ACID 支持。它還提出了一個分佈式系統,作爲一個單節點系統運行將是無用的。

我最近寫了一篇關於 Cassandra 的深度文章,我在文章中打了個比方,也同樣適用於 Dynamo。

把 Dynamo 想象成蘭博基尼 Huracan,把傳統的關係型數據庫想象成勞斯萊斯幻影。幻影會給你更多的奢侈,在這種情況下,奢侈的是你的查詢的靈活性,以及 ACID 屬性,但是當你想踩油門,你想獲得絕對的原始性能時,蘭博基尼 - 胡拉康會直接擊敗幻影的。

因此,當你想在分佈式環境中獲得大規模的規模和可用性,並且性能穩定時,請使用 Dynamo。

有趣的語錄

一個始終可寫的數據存儲

"Dynamo 主要針對那些需要一個" 永遠可寫 "的數據存儲的應用,在那裏沒有更新會因爲失敗或併發寫入而被拒絕。這是許多亞馬遜應用程序的一個關鍵要求。"

有趣的是,上述段落在論文中的措辭。它強調了 Dynamo 是如何爲寫作而建立的,並始終確保更新或失敗不會被拒絕。

這種永遠可寫的數據存儲的理念貫穿本文,是該系統的主要目標之一。

強調不斷的失敗和如何處理它

"在一個由數百萬個組件組成的基礎設施中處理故障是我們的標準操作模式;在任何時候都有少量但重要的服務器和網絡組件出現故障。因此,亞馬遜的軟件系統需要以一種將故障處理視爲正常情況的方式來構建,而不影響可用性或性能。"

我非常喜歡上面這句話,這句話作爲論文導言的一部分,真正設定了對 Dynamo 的期望。能夠每天處理失敗是 Dynamo 工作要求的一部分。

它還強調了 Dynamo 的關鍵焦點是可用性和性能。

流言蜚語

Dynamo 是爲了以分佈式方式工作而建立的。在任何時候,系統中都應該有多個節點在存儲數據。這些數據經常被複制到多個節點。這些節點需要知道彼此的情況,彼此的健康狀況,以及系統的總體情況。有很多有趣的問題,如負載平衡、作業調度、請求路由、複製同步、處理故障、併發等,這些都需要在節點之間不斷溝通。

節點之間使用基於 gossip 協議進行通信。這是一種點對點的通信方法,事實上數據庫系統也經常使用這種方法。我之前在談論 Redis 的時候談到了這一點 here 和 Cassandra 的時候,我在之前的文章中談到過這個問題。The Wikipedia page 關於 gossip 通信的文章也是一個有趣的閱讀。

簡而言之,把節點想象成普通的高中生,討論我們某個節點的尷尬故障。

版本管理和衝突解決

"Dynamo 不提供任何隔離保證,只允許單一主鍵更新。"

這很有意思,因爲在分佈式系統中沒有隔離保證,你的數據存儲有可能有一個數據項的多個版本。

事實上,Dynamo 論文中描述的數據庫系統也是如此。Dynamo 沒有像傳統的關係型數據庫系統那樣回落到保證隔離,而是擁抱了多版本的可能性。

發生這種情況是因爲更新需要異步傳播系統。這種傳播可能需要少量的時間。在這段時間裏,數據存儲將存儲同一數據項的多個版本。Dynamo 使用矢量時鐘的概念來確定版本,並試圖解決版本衝突,但它不能總是解決它們。在它不能解決的情況下,它將多個版本返回給用戶,讓用戶來決定正確的版本。

這篇論文談了很多關於版本的問題,關於他們是如何做出這些決定的,以及哪些因素促成了這些決定,這真是一篇引人入勝的文章。

重要的是要明白,某些故障模式有可能導致系統對相同的數據不只是有兩個而是有幾個版本。在網絡分區和節點故障的情況下,更新有可能導致一個對象有不同的版本子歷史,系統將需要在未來進行協調。

這就要求我們在設計應用程序時,明確承認同一數據存在多個版本的可能性(以便永遠不會丟失任何更新)。

上面這段話特別強調,這些多版本是以 "永遠不會錯過更新" 的承諾爲代價的。" 這又與 Dynamo 所承諾的永遠可寫的數據存儲有關。

論文的另一個節選談到了版本問題和決定誰應該做衝突解決的決策過程,數據存儲還是應用程序。Dynamo 並不是懶得做衝突解決,而是 Dynamo 背後的工程師認爲讓應用程序做衝突解決可能更好一些

下一個設計選擇是由誰來執行衝突解決的過程。這可以由數據存儲或應用程序來完成。如果衝突解決是由數據存儲完成的,那麼它的選擇就相當有限。在這種情況下,數據存儲只能使用簡單的策略,例如 "最後寫的贏"[22],來解決衝突的更新。另一方面,由於應用程序知道數據模式,它可以決定最適合其客戶端經驗的衝突解決方法。

在讀這一節的時候,我直覺地在想,爲什麼不直接用 "最後一次寫入獲勝" 的方法來確定所有數據項的當前狀態,而這篇論文提供了一個非常好的例子,說明這種解決方案在什麼時候是行不通的。

例如,維護客戶購物車的應用程序可以選擇 "合併" 相互衝突的版本,並返回一個統一的購物車。

對高可用性缺乏耐久性的看法很有趣

一般來說,數據庫被迫在可用性和一致性之間做出選擇。這是數據庫做出的最大的選擇之一,對他們的使用情況有很大的影響。

本文深入討論了這一點,因爲 Dynamo 試圖帶來的現狀的一個重大變化是,在不需要的時候從一致性轉向可用性和性能。

人們會認爲可用性和耐用性是相輔相成的,該文件也指出了這一點。

傳統的智慧認爲,耐用性和可用性是相輔相成的。然而,這在這裏不一定是真的

它進一步談到,在 Dynamo 的情況下,情況恰恰相反。因爲所有的節點並不總是承認寫入,所以有可能數據項只被寫入少數的節點,甚至是一個節點。

這意味着有一個小的時間窗口,數據還沒有被複制和持久地存儲在多個位置。這可能會影響耐久性,因爲單個節點很少會因爲硬件故障而丟失數據。

這也爲持久性引入了一個漏洞窗口,當一個寫請求被成功返回到客戶端時,儘管它只在少數節點上被持久化。

這篇論文沒有談及耐用性,如果能讀到他們是如何將數據同步到操作系統的,是類似於關係型數據庫的每次交易的強制同步,還是像今天的 NoSQL 數據庫中有時看到的更多的週期性同步,那將是很有趣的。另外,找不到任何與寫頭日誌或類似東西有關的東西,所以很難評估單個節點的耐久性。

結論和資源

我覺得這份白皮書非常有趣,它是以普通軟件工程師能夠理解和理解的方式寫的。我真的推薦你全文閱讀,它比我所能涉及的要詳細得多。

我非常推薦維爾納 - 沃格爾斯在 Dynamo 十年後寫的文章.

AWS 關於 DynamoDB 的數據建模的兩部分系列文章也非常有趣,儘管那更多地是關注 DynamoDB 而不是 Dynamo。它真正展示了數據查詢和數據模型是如何與關係模型完全不同的。

如果你喜歡這篇文章,請在評論中告訴我你是否使用過 Cassandra 或 DynamoDB,以及你的使用經驗如何。

來源:

https://www.toutiao.com/article/7117092391676346920/?log_from=bd8d977031e0f_1657521672759

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/0ussMqMCGtUbFe5D1Xkn-Q