Dynamo 解讀 | 面對 Dynamo 我們又將會學到怎樣的產品與技術設計哲學!

語言: CN / TW / HK

本文深度參考了以下這些文章的真知灼見!特此說明,並表示感謝:

  • The Dynamo Paper [1]

  • The DynamoDB paper [2]

  • Key Takeaways from the DynamoDB Paper [3]

  • DynamoDB 2022 論文解讀 [4]

Dynamo 前傳

2004 年,Amazon.com 發展迅速,並開始達到其 Oracle 資料庫的擴充套件上限。它開始考慮在內部構建自己的資料庫。在這個實驗中,工程師建立了 Amazon Dynamo 資料庫,該資料庫支援主要的內部基礎設施,包括 Amazon.com 網站上的購物車。

Amazon Dynamo 資料庫背後的一群工程師於 2007 年發表了 Dynamo 論文 [5] 。它描述了構建內部高可用鍵值儲存的經驗教訓,旨在滿足 Amazon.com 網站的苛刻要求。

該論文極具影響力並啟發了許多 NoSQL 資料庫,包括 Apache Cassandra(最初在 Facebook 開發)和 AWS 產品 SimpleDB 和 DynamoDB。2012 年,Amazon Web Services 推出了 DynamoDB,這是一種以 Dynamo 背後的原理為藍本的託管資料庫服務。

Dynamo 的核心設計理念

沒有關係模型

關係資料模型是對許多型別的資料進行建模的有用方法。通常,對關係資料進行規範化以提高資料的完整性。您可以將其儲存在一個位置並使用從一個表到另一個表的 JOIN 操作來引用它,而不是在多行中複製一條特定的資料。你可以更新單個位置,並且引用該資料的所有的item也將獲得更新的收益。

然而,Amazon.com 工程師在收集資料庫需求時最有趣的發現之一是他們的工程師如何使用他們的關係資料庫:

大約 70% 的操作屬於鍵值型別,僅使用主鍵並返回單行。大約 20% 會返回一組行,但仍然只對單個表進行操作。——沃納·沃格爾斯

90% 的操作沒有使用關係資料庫的核心 JOIN 功能!

JOIN 操作很昂貴。在足夠大的規模上,工程師經常對他們的資料進行非規範化,以避免進行昂貴的join和減慢響應時間。這種響應時間的減少伴隨著應用程式複雜性的增加——現在您需要在程式碼中而不是在資料庫中管理更多的資料完整性問題。

Amazon.com工程師已經在權衡非規範化以縮短響應時間。意識到亞馬遜工程師不需要關係模型,Dynamo 設計人員可以重新評估關係資料庫的其他方面。

可用性 > 一致性

大多數關係資料庫對其資料使用高度一致的模型。簡而言之,這意味著如果同時查詢,伺服器的所有客戶端將看到相同的資料。

讓我們以 Twitter 為例。想象一下,弗吉尼亞州的 Bob 在下午 2:30 釋出了一張貓的照片。在 Bob 釋出照片後,有兩個使用者查看了 Bob 的個人資料:他的鄰居 Cheryl 和住在新加坡的叔叔 Jeffrey。如果 Twitter 使用強一致性模型,那麼 Cheryl 和 Jeffrey 都應該在 Bob 的操作提交到資料庫後立即看到 Bob 的最新推文。

由於幾個原因,這可能並不理想。首先,考慮一下這個場景所涉及的地理環境。Twitter 可以選擇使用單個數據庫例項來實現這種強一致性。此資料庫例項可能位於弗吉尼亞州,靠近 Bob 和 Cheryl。這會導致對 Bob 和 Cheryl 的快速響應,但對 Jeffrey 的響應非常緩慢,因為每個請求都必須從新加坡穿越海洋到弗吉尼亞州以請求資料,然後從弗吉尼亞州返回新加坡以將其返回給 Jeffrey。這會導致某些使用者的讀取時間變慢。

與維護單個數據庫例項不同,Twitter 可能希望擁有兩個完全相同的例項——一個在弗吉尼亞州,一個在新加坡。如果我們仍然想保持強一致性,這意味著如果她同時查詢弗吉尼亞例項或新加坡例項,使用者必須得到相同的答案。這可以通過一個更復雜的資料庫寫入系統來實現——在 Bob 的推文提交到資料庫之前,它必須同時提交給弗吉尼亞例項和新加坡例項。現在 Bob 的請求需要跨越大洋並返回。這會導致某些使用者的寫入時間變慢。

在 Dynamo 論文中,亞馬遜指出,強一致性並非在所有場景中都很重要。在我們的示例中,如果 Jeffrey 和 Cheryl 看到我的個人資料的版本略有不同,即使他們同時查詢也是可以的。有時您可以滿足於最終的一致性,這意味著不同的使用者最終會看到相同的資料檢視。Jeffrey 最終會在新加坡看到 Bob 的推文,但可能是下午 2:32 而不是 2:30。

強一致性對於某些用例很重要——想想銀行賬戶餘額——但對於其他用例來說則不太重要,例如我們的 Twitter 示例或亞馬遜購物車,這是 Dynamo 的推動力。對於這些用例,速度和可用性比一致更重要。通過削弱關係資料庫的一致性模型,Dynamo 工程師能夠提供更符合 Amazon.com 需求的資料庫。

無限可擴充套件

Dynamo 的最後一個關鍵方面是它可以無限擴充套件,不會對效能產生任何負面影響。這方面是放寬先前資料庫的關係和一致性約束的結果。

當擴充套件系統時,您可以垂直擴充套件(使用具有更多 CPU 或 RAM 更大的伺服器例項),也可以通過將資料拆分到多臺機器來水平擴充套件,每臺機器都有完整資料集的一個子集。垂直擴充套件很昂貴,並最終達到硬體的上限瓶頸。水平縮放更便宜但更難實現。

要考慮水平擴充套件,假設您有一個使用者資料集,您希望將其分佈在三臺機器上。您可以選擇根據使用者的姓氏將它們拆分到機器上——A 到 H 進入機器 1,I 到 Q 進入機器 2,R 到 Z 進入機器 3。

如果您只有一個使用者,這很好——檢索 Linda Duffy 的呼叫可以直接轉到機器 1——但如果您的查詢跨越多臺機器,則可能會很慢。獲取所有 18 歲以上使用者的查詢將必須訪問所有三臺機器,從而導致響應速度變慢。

同樣,我們在上一節中看到了強一致性要求如何使其難以橫向擴充套件。我們將在寫入期間引入延遲,以確保在返回寫入使用者之前將寫入提交給所有節點。

放寬這些要求可以讓 Dynamo 在不犧牲效能的情況下更輕鬆地進行水平擴充套件。DynamoDB 使用一致的雜湊將item分佈在多個節點上。隨著 DynamoDB 表中資料量的增加,AWS 可以在後臺新增額外的節點來處理這些資料。

DynamoDB 通過本質上要求所有讀取操作使用主鍵(掃描除外)來避免多機問題。在我們之前的使用者示例中,我們的主鍵可以是姓氏,亞馬遜會相應地分發資料。如果確實需要通過 Age 進行查詢,則可以使用二級索引通過不同的鍵應用相同的分佈策略。

最後,由於 DynamoDB 允許最終一致性,它允許更輕鬆的資料複製策略。您可以將您的item複製到三臺不同的機器上並查詢其中任何一臺以提高吞吐量。由於最終一致性模型,其中一臺機器在不同時間對item的檢視可能略有不同,但對於許多用例來說,這是一個值得接受的權衡。此外,如果您的應用程式需要,您可以顯式指定強一致性讀取。

這些變化使 DynamoDB 能夠為幾乎無限量的資料提供幾毫秒的查詢延遲——100TB+。

十五年後又以一篇論文回顧

十五年後(也就是前不久),亞馬遜的人釋出了一篇 關於 DynamoDB 的新論文 [6] 。大多數作者都發生了變化(除了AWS VP Swami Sivasubramanian ,他同時出現在兩篇上),但令人好奇的是 Dynamo 的核心概念是如何更新和更改以提供完全託管、高度可擴充套件的多租戶雲資料庫服務。

論文公開了一些資料:

2021 年,在 66 小時的 Amazon Prime Day 購物活動中,亞馬遜系統……對 DynamoDB 進行了數萬億次 API 呼叫,峰值達到每秒 8920 萬次請求

從任何標準來看,每秒 8900 萬個請求都是一個大型資料庫(這只是 Amazon 對 DynamoDB 的使用)!

在這篇文章中,我想討論我從新的 DynamoDB 論文中獲得的主要收穫:

  • • DynamoDB 服務的產品級“使用者需求”學習;和

  • • 多年來的技術改進使服務得到進一步發展。

DynamoDB 論文中的產品級要點

Dynamo 論文和 DynamoDB 論文都描述了一些令人難以置信的技術概念,但對使用者需求的討論同樣給我留下了深刻的印象。在這兩篇論文中,都對現有實踐進行了深入調查,以瞭解什麼是重要的,以及應該圍繞核心使用者需求重新考慮什麼。

在 Dynamo 論文中,我們清楚地看到了這一點:即 RDBMS 提供的許多高階查詢功能並未被 Amazon 的服務使用。 70% 的資料庫操作是使用主鍵的單記錄查詢,另外 20% 讀取一組行但只訪問一個表

Dynamo 論文還指出,傳統的強一致性保證雖然在某些情況下至關重要,但並非所有應用程式都需要。在許多情況下,通過放寬一致性要求來提高可用性和減少寫入延遲是非常值得的。

正如 Dynamo 論文重新審視了傳統資料庫系統中的一些陳詞濫調一樣,DynamoDB 論文圍繞使 Dynamo 學習更廣泛適用的使用者需求。通過這樣做,DynamoDB 能夠制定一組明確的產品優先順序,將 DynamoDB 與許多其他資料庫產品區分開來。

我從論文中獲得了關於使用者需求的三個重要說明:

  • • 恆定可預測效能的重要性

  • • 完全託管優於自管理

  • • 使用者資料分佈不均

恆定可預測效能的重要性

DynamoDB 論文反覆強調的一點是,對於許多使用者來說,“ 任何規模的一致性能通常比中值請求服務時間更重要。 ” 換句話說,最好在中值和尾部延遲之間設定更窄的範圍,而不是減少中值(甚至 p90 或 p95)延遲。

對於一些認為“DynamoDB 超級快”的人來說,這是一個令人驚訝的觀點。以下是DynamoDB 跟 RDBMS 在資料規模與效能之間關係的對比圖:

在此圖表中,我們看到 RDBMS 延遲會隨著資料庫中資料量的增加而變差,而 DynamoDB 會隨著資料的增加提供一致的效能。隨著併發請求數量的增加,同樣的關係也成立。

上面的圖表是一個粗略的草圖,但總體而言是站得住腳的。在特定級別的資料和事務量下,RDBMS 將比 DynamoDB 具有更快的響應時間。從概念上講,這很容易理解。對 DynamoDB 的請求將通過多個系統(請求路由器、元資料系統、身份驗證系統),然後再到達儲存請求資料的底層物理儲存節點。雖然這些系統都經過了高度優化,但它們中的每一個都為整體請求增加了延遲。相反,單節點 RDBMS 可以跳過很多工作,直接對本地資料進行操作。

所以 MySQL 可能會在中位數上擊敗 DynamoDB,但這還不是全部。出於兩個原因,您還應該全面考慮資料庫的效能。

首先,尾部延遲很重要,尤其是在具有大量元件和子元件的架構中。如果對後端的一次呼叫導致對底層服務的大量呼叫,那麼每個請求更有可能經歷來自某些服務的尾部延遲,從而導致響應速度變慢。

其次,DynamoDB 效能的一致性和可預測性可減少您的服務的長期維護負擔。由於您的應用效能不可避免地下降,您不必回來進行調查、調整和重構。您知道您將在測試環境中獲得與釋出五年後相同的效能,從而使您能夠專注於為使用者創造更多價值的功能。

總結一下,DynamoDB 的可預測效能的核心在於:

  • • 對 Workload 準確抽象(WCU/RCU)

  • • 對 Partition 預分配配額,並嚴格限流

  • • 在 Node 上留出餘量作為應對突發場景的臨時資源池(Burst)

  • • 使用全域性資訊進行流量排程,在各個層面上都流控

完全託管優於自管理

在無伺服器世界中,我們儘可能專注於構建我們業務的關鍵差異化因素,同時將無差異的繁重工作解除安裝給其他人。但是亞馬遜的內部經驗和 Dynamo(不是 DynamoDB)的創造者真正推動了它的發展。

回想一下,Dynamo 論文在業界具有巨大的影響力,而亞馬遜的內部 Dynamo 系統在可用性和可擴充套件性方面對亞馬遜的巨大運營規模來說是一個巨大的改進。

儘管有這種改進,許多內部工程師還是選擇避開執行 Dynamo,轉而使用Amazon SimpleDB,這是 AWS 首次涉足託管 NoSQL 資料庫市場。

如果你從未聽說過 Amazon SimpleDB,那麼你並不孤單。DynamoDB 本質上是 SimpleDB 的繼任者,幾乎在各個方面都更勝一籌,AWS 很少再推銷它。

SimpleDB 有一些真正令人驚訝的缺點,例如整個資料庫的大小不能超過 10GB。對於大多數應用程式來說,這是一個巨大的限制,對於擁有如此龐大的應用程式以至於不得不設計一個全新的資料庫的公司(Amazom)來說尤其如此。然而工程師選擇使用多個 SimpleDB 表批量處理他們的需求,可能在應用程式層進行分片以將每個資料庫保持在 10GB 以下。這不得不大大增加應用程式邏輯的複雜性。儘管如此,工程師仍然選擇使用 SimpleDB 而不是操作自己的 Dynamo 例項。

Amazon 工程師的這種偏好刺激並促進了 Amazon DynamoDB 的開發,這是一個將 Dynamo 的可擴充套件性與 SimpleDB 的完全託管性質相結合的資料庫。

使用者資料分佈不均

最後的使用者要點是,您必須與給定的使用者合作,而不是與您想要的使用者合作。在理想情況下,使用者將擁有穩定、可預測的流量,將資料訪問均勻地分佈在表的鍵空間中。實際情況大不相同。

最初的 Dynamo 論文使用一致性雜湊的概念將資料分佈在大約 10GB 大小的獨立分割槽中。(分割槽將在下面更深入地討論)。它使用item的分割槽鍵跨分割槽放置資料,從而實現可預測的效能和線性水平擴充套件。

此外,與原始 Dynamo 系統不同,DynamoDB 是一個多租戶系統。你的分割槽可能與其他 DynamoDB 使用者表中的分割槽位於同一位置。

最初,DynamoDB 團隊構建了一個系統來避免嘈雜的租戶干擾問題,即一個分割槽的高流量會導致同一儲存節點上不相關分割槽的體驗降低。然而,隨著系統的發展,他們意識到管理這個問題的初始系統會導致那些工作量激增、不平衡的workload。

隨著 AWS 團隊構建 DynamoDB,他們意識到他們需要改進訪問控制系統,以管理是否允許分割槽為請求提供服務。下面我們將更多地研究這種演變的技術方面。

DynamoDB 論文的技術要點

產品級的學習很吸引人,但這最終是一篇技術論文。DynamoDB 團隊正在大規模開展的工作令人印象深刻,許多技術知識甚至適用於那些沒有 DynamoDB 規模的人。

我從這篇論文中獲得了三個最有趣的技術要點:

  • • 使用日誌副本來提高永續性和可用性;

  • • 為改善對不平衡工作負載的服務而採取的增量步驟;

  • • 使用非同步快取機制來提高底層服務的效能、可用性和彈性

使用日誌副本提高永續性和可用性

更有趣的一點是 DynamoDB 如何使用稱為日誌副本的設計在例項故障期間提供幫助。要了解日誌副本,我們首先需要了解 DynamoDB 儲存的底層架構的一些背景知識。

DynamoDB 儲存背景部分的開始

在後臺,DynamoDB 將您的資料拆分為分割槽,這些分割槽是大小約為 10GB 的獨立儲存段。DynamoDB 使用分割槽鍵將您的item分配給給定的分割槽,這允許 DynamoDB 隨著資料庫的增長水平擴充套件,同時仍將相關item保持在一起。DynamoDB 執行大量儲存節點,這些節點處理來自許多不同使用者表的分割槽。

單個分割槽實際上是一組位於不同可用區的三個分割槽例項,它們形成一個複製組。其中一個例項是該分割槽的leader,負責處理所有寫入。當有資料寫入時,leader將其寫入本地,並確保在返回給客戶端之前將其提交到至少一個額外的副本。這增加了發生故障時的永續性,因為丟失一個節點不會導致資料丟失。

一個分割槽的副本構成一個複製組。複製組使用 Multi-Paxos 進行領導者選舉和共識。只有領導者副本可以服務寫入和強一致性讀取請求。收到寫入請求後,正在寫入的金鑰的複製組的領導者會生成一個預寫日誌記錄並將其傳送給其對等方(副本)。...複製組的任何副本都可以提供最終一致的讀取。

每個儲存分割槽上都有兩個資料結構 - B-Tree 包含分割槽上的索引資料以及預寫日誌 (WAL),其中包含應用於該分割槽的更新的有序列表。預寫日誌是資料庫中常用的策略,用於提高寫入操作的永續性和延遲。更新 B-Tree 比較慢,因為它涉及隨機 I/O,並且可能涉及在磁碟上重寫多個頁面,而更新預寫日誌是一個僅追加的操作,速度要快得多。

請注意,除了針對這些結構的單個操作的效能差異之外,這兩個結構的大小也存在巨大差異。B-Tree的大小可以超過 10 GB(考慮到分割槽的 10 GB 大小以及索引開銷),而預寫日誌只有幾百兆位元組(預寫日誌的完整歷史記錄是定期同步到 S3,用於支援時間點恢復和其他功能)。

DynamoDB 儲存背景部分結束

當您執行像 DynamoDB 這樣大的系統時,例項總是會失敗。當儲存節點發生故障時,您現在可能有數千個分割槽副本需要重新定位到非故障節點。在此故障期間,在該節點上具有副本的每個複製組現在都減少到兩個副本。因為需要兩個副本來確認給定的寫入,所以您現在正在增加寫入的延遲分佈以及如果另一個副本發生故障時降低可用性的概率。

為了減少只有兩個副本處於活動狀態的時間,DynamoDB 使用日誌副本。日誌副本是僅包含預寫日誌的複製組的成員。通過跳過分割槽的 B-Tree,DynamoDB 子系統可以通過複製最後幾百 MB 的日誌來快速啟動日誌副本。此日誌副本可用於確認寫入,但不能用於讀取。

當此日誌副本在幫助複製組時,DynamoDB 子系統可以在後臺執行以啟動一個完整的副本成員來替換失敗的成員。

看到團隊為不斷突破永續性、可用性和延遲的極限而進行的增量調整非常有趣。其中大部分都不會改變系統做出的核心承諾,例如在 CAP 定理上做出不同的選擇。相反,它們是對資料庫可靠性和效能的穩定改進。

首先,DynamoDB 使用預寫日誌與索引儲存的標準組合來提高永續性並減少寫入請求的延遲。

其次,DynamoDB 放棄了 RDBMS 的典型單節點設定,並轉移到分割槽系統。這減少了恢復時間(這意味著可用性的提升),因為恢復 10GB 分割槽比恢復 200GB 表要快得多。此外,此複製跨越三個不同的可用區 (AZ),因此整個 AZ 可以不可用而不會影響系統的可用性。

然後,DynamoDB 放寬了一致性要求,要求複製組中的三個節點中只有兩個節點確認寫入。以一些偶爾過時的資料為代價,DynamoDB 能夠提高可用性並減少寫入延遲。

最後,DynamoDB 使用日誌副本來提高節點故障期間的可用性。

將分割槽與吞吐量解耦

在上一節中,我們討論瞭如何使用分割槽來分割表中的資料並允許水平擴充套件。此外,我們還看到了 DynamoDB 如何將來自不同客戶的分割槽放在同一儲存節點上,以提高 DynamoDB 服務的效率。

第二個有趣的技術要點是對這些分割槽的“准入控制”系統進行緩慢而穩定的改進。准入控制是指 DynamoDB 根據可用容量確定請求是否可以成功的過程。在確定這一點時,DynamoDB 正在檢查兩個軸的容量:

  • • 根據為表預置的容量,是否有可供客戶使用的容量?

  • • 根據分割槽所在儲存節點的總容量,分割槽是否有可用容量?

第一個是成本決策,因為 DynamoDB 希望確保您為他們提供的服務付費。第二個是效能決策,因為他們希望避免來自同位分割槽的嘈雜鄰居問題。

跨分割槽的吞吐量均勻分佈是基於這樣的假設:應用程式一致地訪問表中的鍵,並且根據大小劃分分割槽會平均分配效能。

准入控制的第一次迭代純粹是在分割槽級別。DynamoDB 會將預配置的總吞吐量除以分割槽數,然後將該數量平均分配給每個分割槽。這是最簡單的系統,因為您不必逐秒協調大量分割槽。但是,它導致了工作負載不平衡和 “吞吐量稀釋” [7] 問題。這可能會導致對熱分割槽的請求受到限制。

但是,我們發現應用程式工作負載經常具有隨時間和鍵範圍的非統一訪問模式。當表中的請求率不均勻時,拆分分割槽並按比例劃分效能分配會導致分割槽的熱點部分具有比拆分前更少的可用效能。由於吞吐量是靜態分配的並在分割槽級別強制執行,這些非統一的工作負載偶爾會導致應用程式的讀取和寫入被拒絕,稱為限制。

為了解決這個問題,DynamoDB 想要將准入控制與分割槽解耦,但意識到這將是一個很大的提升。為了解決這個問題,他們分階段進行。

一是完善分割槽級准入控制系統。雖然每個分割槽都受到限制以防止過度消耗單個節點上的資源,但他們也意識到儲存節點經常在滿負荷下執行。為了幫助解決各個分割槽的臨時流量高峰,DynamoDB 添加了短期突發,如果它可用於給定的儲存節點,則可以讓分割槽使用額外的吞吐量。這種改進主要集中在訪問控制的第二個軸上——防止嘈雜的鄰居。

Burst 思路很簡單,在分配配額的時候, DynamoDB 會給各個 Partition 預留一部分 Capacity,就是在短期流量 spike 的時候,用這些預留的 Capacity 扛一扛;

第二個初始改進有助於訪問控制的另一個軸——單個表的預置吞吐量。如前所述,具有傾斜訪問模式的表可能會消耗一個分割槽的所有吞吐量,但仍低於表的總預置吞吐量。為了解決這個問題,DynamoDB 增加了 自適應容量,Adaptive Capacity [8] ,可以將稀疏使用分割槽的吞吐量轉移到高度使用的分割槽。

Adaptive Capacity 就是在使用者的 Workload 在其 Partitions 上出現傾斜後,動態的調整不同 Partition 的配額(但是總量不能超過原來的總配額)。

這兩個變化在保持通用的基於分割槽的訪問控制方案的同時,減輕了基於資料訪問模式不均勻的大量痛苦。

後來,DynamoDB 遷移到全域性訪問控制系統,將吞吐量與分割槽完全解耦。這將自適應容量從較慢的“盡力而為”系統更改為幾乎即時的系統,以將吞吐量分散到各個分割槽。這種靈活性帶來了驚人的其他改進,包括能夠將特別熱點的item分離到它們自己的分割槽上、提供按需計費、以及根據底層分割槽的可預測工作負載“超載”儲存節點。

所有這些都在論文的第 4 節中進行了更詳細的敘述,值得您自己閱讀以瞭解詳細資訊。

使用非同步快取

最後一個技術要點是 DynamoDB 對非同步快取的使用。我所說的“非同步快取”是指一個系統在本地快取資料,然後在後臺非同步對快取進行再更新,以確保其保持最新狀態。

我們都知道快取是一種通過儲存高昂呼叫的結果來減少延遲的方法。在論文中提及,單個請求路由器例項都在本地儲存外部呼叫的結果,以避免緩慢的網路請求。在回顧這些時,我們應該注意 DynamoDB 如何從“內部”系統處理“外部”系統(也稱為“依賴項”)。

DynamoDB 使用其他 AWS 服務,例如 IAM 來驗證請求或使用 KMS 來加密和解密資料。這兩項服務都是外部依賴項,因為它們不受 DynamoDB 團隊的控制。在這裡,DynamoDB 將快取對這些服務的呼叫結果,作為提高可用性的一種方式。這些結果會定期非同步重新整理以確保新鮮度。即使這些外部服務本身存在問題,這也允許 DynamoDB 繼續工作(在某種程度上)。如果沒有這個,DynamoDB 的可用性必然低於 IAM 和 KMS。

DynamoDB 還為“內部”系統使用非同步快取。DynamoDB 有一個元資料系統,用於跟蹤每個 DynamoDB 分割槽的表資訊和位置。當請求到達 DynamoDB 請求路由器時,它需要找到給定item的相關分割槽以將請求轉發到儲存節點。

此元資料資訊不會經常更改,因此請求路由器會大量快取此資料。論文指出,快取命中率為99.75%(!!),相當不錯。但是, 高快取命中率也可能導致一個問題 [9] :流量輕微減少可能導致底層服務負載顯著增加。將元資料快取命中率從 99.75% 降低到仍然驚人的 99.5% 會導致對底層元資料服務的請求數量增加一倍。

DynamoDB 團隊發現元資料服務必須根據請求路由器服務進行擴充套件,因為新的請求路由器有空快取,導致對元資料服務的大量呼叫。這導致了整個系統的不穩定。

在 Request Router 和 Metadata Service 中間加了一級分散式記憶體快取 MemDS,Router 的本地快取失效後,並不直接訪問 Meta Service,而是先訪問 MemDS,然後 MemDS 在後臺批量的訪問 Metadata Service 填充資料。通過新增一層快取進行削峰操作,相當於再加一層保險,屬於常見的手段。

為了提高其內部系統的彈性,DynamoDB 使用非同步快取重新整理來為底層元資料系統提供恆定負載。雖然請求路由器將以高命中率在本地快取,但每次命中都會導致對元資料服務的關聯請求以重新整理快取的資料。

第二個手段比較巧妙,剛才提到 Router 事實上是通過 MemDS 獲取元資訊,當請求在 MemDS 的時候沒命中的時候好理解,但是 MemDS 巧妙地方在於:即使快取命中,MemDS 也會非同步訪問 Meta Service。1) 儘可能保證 MemDS 中已有快取能被及時更新; 2) 給 MetaService 帶來一個’穩定‘的流量;

通過將本地快取命中與對元資料服務的非同步請求配對,它可以確保元資料服務的流量更加一致。快取命中和快取未命中都會導致對元資料服務的請求,因此增加具有冷快取的請求路由器的數量不會導致元資料服務的新流量激增。

完結

亞馬遜再次幫助推動了我們對深層技術主題的理解。正如 Dynamo 論文在設計新的資料庫架構方面具有革命性意義一樣,DynamoDB 論文是執行和發展大規模託管系統的重要課程。

在這篇文章中,我們從 DynamoDB 論文中的使用者需求角度研究了核心設計要素。然後,我們研究了論文中的一些技術設計點。

該論文還有許多沒有涉及的其他有趣點,例如Serverless、儲存的 GC 策略、分散式事務等、DynamoDB 如何通過檢測內部 Amazon 服務來監控客戶端可用性、用於針對大量例項部署新版本 DynamoDB 的策略以及用於防止資料錯誤機制,無論是在inflight還是在靜止時。讓我們對未來保持期待!

引用連結

[1] The Dynamo Paper:  https://www.dynamodbguide.com/the-dynamo-paper

[2] The DynamoDB paper:  https://brooker.co.za/blog/2022/07/12/dynamodb.html

[3] Key Takeaways from the DynamoDB Paper:  https://www.alexdebrie.com/posts/dynamodb-paper/

[4] DynamoDB 2022 論文解讀:  http://blog.0xffff.me/posts/dynamodb-2022/

[5] Dynamo 論文:  http://www.allthingsdistributed.com/files/amazon-dynamo-sosp2007.pdf

[6] 關於 DynamoDB 的新論文:  https://www.usenix.org/system/files/atc22-elhemali.pdf

[7] “吞吐量稀釋”:  https://hackernoon.com/beware-of-dilution-of-dynamodb-throughput-due-to-excessive-scaling-4df51063edae

[8] 自適應容量,Adaptive Capacity:  https://aws.amazon.com/blogs/database/how-amazon-dynamodb-adaptive-capacity-accommodates-uneven-data-access-patterns-or-why-what-you-know-about-dynamodb-might-be-outdated/

[9] 高快取命中率也可能導致一個問題:  https://www.gomomento.com/blog/the-biggest-miss-in-your-cache-hit-rate