日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Dynamo:亚马逊的高可用键值存储

發布時間:2024/2/28 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Dynamo:亚马逊的高可用键值存储 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

? ? ? ??1. 簡介

? ? ? ? 2. 背景

? ? ? ??3.?相關工作

? ? ? ??4.?系統結構

? ? ? ??5.?實現

? ? ? ??6.?經驗和教訓

? ? ? ??7.?結論


Dynamo亞馬遜的高可用鍵值存儲

摘要大規模的可靠性是我們在?Amazon.com?面臨的最大挑戰之一,它是世界上最大的電子商務運營之一;即使是最輕微的停機也會帶來嚴重的財務后果,并影響客戶的信任。Amazon.com?平臺為世界各地的許多網站提供服務,它是在位于世界各地許多數據中心的數萬臺服務器和網絡組件的基礎架構之上構建的。在這種規模下,大大小小的組件不斷地發生故障,而面對這些故障時管理持久狀態的方式驅動著軟件系統的可靠性和可伸縮性。

本文介紹了?Dynamo 的設計和實現,Dynamo 是一個高度可用的鍵值存儲系統,亞馬遜的一些核心服務使用它來提供?"永遠在線"?的體驗。為了達到這種可用性水平,Dynamo 在某些故障情況下犧牲了一致性。它廣泛使用對象版本控制和應用程序輔助的沖突解決方式,為開發人員提供了一個新穎的接口

?

1. 簡介

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

為了滿足可靠性和可擴展性需求,亞馬遜開發了多種存儲技術,其中最著名的可能是亞馬遜簡單存儲服務也可在亞馬遜之外獲得,Amazon Simple?Storage Service?稱為亞馬遜?S3。本文介紹了?Dynamo 的設計和實現,Dynamo 是為亞馬遜平臺構建的另一個高度可用和可擴展的分布式數據存儲。Dynamo 用于管理具有非常高的可靠性要求并且需要嚴格控制可用性、一致性、成本效益和性能之間權衡的服務狀態。亞馬遜的平臺有一套非常多樣化的應用程序,具有不同的存儲要求。一組選定的應用程序需要一種足夠靈活的存儲技術,以便應用程序設計人員能夠根據這些權衡來適當地配置他們的數據存儲,從而以最經濟高效的方式實現高可用性和有保證的性能。

亞馬遜的平臺上有許多服務只需要對數據存儲進行主鍵訪問。對于許多服務,例如那些提供暢銷書列表、購物車、客戶偏好、會話管理、銷售排名和產品目錄的服務,使用關系數據庫的常見模式會導致效率低下,并限制規模和可用性。Dynamo 提供了一個簡單的主鍵接口來滿足這些應用程序的要求。

Dynamo?綜合了一些眾所周知的技術來實現可伸縮性和可用性:使用一致哈希算法對數據進行分區和復制,并且通過對象版本控制來促進一致性。通過類似仲裁的技術和去中心化的副本同步協議來維護更新過程中副本之間的一致性。Dynamo?采用基于?gossip 的分布式故障檢測和成員協議。Dynamo?是一個完全去中心化的系統,只需要很少的人工管理。可以在?Dynamo?中添加和刪除存儲節點,而不需要任何手動分區或重新分配。

過去一年,Dynamo 一直是亞馬遜電子商務平臺許多核心服務的底層存儲技術。在繁忙的假日購物季節,它能夠高效地擴展到極端峰值負載,而沒有任何停機時間。例如,維護購物車的服務購物車服務為數千萬個請求提供服務,這些請求在一天內導致超過?300?萬次結帳,而管理會話狀態的服務處理了數十萬個并發活動的會話。

這項工作對研究界的主要貢獻是評估如何將不同的技術結合起來,以提供一個高度可用的系統。它表明,最終一致的存儲系統可以用于要求苛刻的應用程序的生產中。它還提供了對這些技術的調整,以滿足對性能要求非常嚴格的生產系統的要求。

論文結構如下。第?2?節介紹了背景,第?3?節介紹了相關工作。第?4?節介紹了系統設計,第?5?節描述了實現。第?6?節詳細介紹了在生產中運行?Dynamo 獲得的經驗和見解,第?7?節總結了本文。本文中有許多地方可能需要額外的信息,但保護亞馬遜的商業利益需要我們減少一些細節。因此,第?6?節中的數據中心內部和數據中心之間的延遲、第?6.2?節中的絕對請求率以及第?6.3?節中的停機時間和工作負載是通過聚合度量而不是絕對細節來提供的。

?

?

2. 背景

亞馬遜的電子商務平臺由數百項服務組成,這些服務協同工作,提供從推薦、訂單執行到欺詐檢測等功能。每個服務都通過一個明確明確定義的接口公開,并可通過網絡訪問。這些服務托管在一個基礎架構中,該基礎架構由遍布全球許多數據中心的數萬臺服務器組成。這些服務中的一些是無狀態的即聚合來自其他服務的響應的服務,一些是有狀態的即通過對存儲在持久存儲中的狀態執行業務邏輯來生成響應的服務

傳統上,生產系統將狀態存儲在關系數據庫中。然而,對于許多更常見的狀態持久化使用模式,關系數據庫是一個遠非理想的解決方案。這些服務中的大多數只按主鍵存儲和檢索數據,不需要關系數據庫管理系統提供的復雜查詢和管理功能。這種多余的功能需要昂貴的硬件和高技能人員來操作,這使得它成為一種非常低效的解決方案。此外,可用的復制技術有限,通常選擇一致性而不是可用性。盡管近年來取得了許多進展,但擴展數據庫或使用智能分區方案進行負載平衡仍然不容易。

本文描述了?Dynamo,一種高度可用的數據存儲技術,解決了這些重要服務類別的需求。Dynamo有一個簡單的鍵/值接口,具有明確定義的一致性窗口,高度可用,資源使用高效,并有一個簡單的橫向擴展方案來解決數據集大小或請求速率的增長。每個使用?Dynamo 的服務都運行自己的?Dynamo 實例。

?

?

2.1?系統假設和要求

此類服務的存儲系統有以下要求

查詢模型對由關鍵字唯一標識的數據項的簡單讀寫操作。狀態存儲為由唯一鍵標識的二進制對象?Blobs沒有跨越多個數據項的操作,也不需要關系模式。這一要求是基于這樣的觀察,即亞馬遜的很大一部分服務可以使用這個簡單的查詢模型,并且不需要任何關系模式。Dynamo 面向需要存儲相對較小通常小于1 MB的對象的應用程序。

ACID?屬性ACID原子性、一致性、隔離性、持久性是一組保證數據庫事務得到可靠處理的屬性。在數據庫環境中,對數據的單個邏輯操作稱為事務。亞馬遜的經驗表明,提供ACID?保證的數據存儲往往可用性較差。這已經得到業界和學術界的廣泛認可。Dynamo 的目標是一致性較弱的應用程序ACID?中的?"C")Dynamo 不提供任何隔離保證,只允許單鍵更新。

效率系統需要在商硬件基礎設施上運行。在亞馬遜的平臺上,服務有嚴格的延遲要求,通常在分布的?99.9%?進行測量。鑒于狀態訪問在服務操作中起著至關重要的作用,存儲系統必須能夠滿足如此嚴格的服務層協議(參見下文第?2.2?。服務必須能夠配置?Dynamo,使其始終達到延遲和吞吐量要求。權衡是在性能、成本效率、可用性和耐用性保證方面。

其他假設Dynamo?只被亞馬遜內部服務使用。其操作環境被友好的,并且沒有諸如認證和授權的安全相關要求。此外,由于每項服務都使用其獨特的?Dynamo 實例,其最初的設計目標是多達數百臺存儲主機的規模。我們將在后面的章節中討論?Dynamo 的可伸縮性限制和可能的可伸縮性相關擴展。

?

?

2.2?服務協議

為了保證應用程序能夠在有限的時間內交付其功能,平臺中的每個依賴項都需要以更嚴格的限制來交付其功能。客戶和服務簽訂服務層協議,這是一種正式協商的合同,客戶和服務就幾個與系統相關的特征達成一致,其中最突出的包括客戶對特定應用編程接口的預期請求速率分布以及在這些條件下的預期服務延遲。簡單?SLA?的一個例子是一個服務,它保證它將在?300?毫秒內對其?99.9%?的請求提供響應,以達到每秒?500?個請求的峰值。

在亞馬遜去中心化的面向服務的基礎設施中,服務協議扮演著重要的角色。例如,對一個電子商務站點的頁面請求通常需要呈現引擎通過向?150?多個服務發送請求來構造其響應。這些服務通常有多個依賴項,這些依賴項通常是其他服務,因此應用程序的調用圖有多個級別并不罕見。為了確保頁面呈現引擎能夠在頁面交付上保持明確的界限,調用鏈中的每個服務都必須遵守其性能契約。

?1?顯示了亞馬遜平臺架構的抽象視圖,其中動態網頁內容是由頁面呈現組件生成的,而頁面呈現組件又會查詢許多其他服務。服務可以使用不同的數據存儲來管理其狀態,并且這些數據存儲只能在其服務邊界內訪問(these?data stores are only accessible within its service boundaries)。一些服務充當聚合器Aggregators),通過使用其他幾個服務來產生復合響應。通常,聚合器服務是無狀態的,盡管它們使用大量的緩存。

行業中形成面向性能服務層協議的一種常見方法是使用平均值、中位數和預期方差來描述它。在亞馬遜,我們發現,如果目標是建立一個所有客戶都有良好體驗的系統,而不僅僅是大多數客戶,那么這些指標就不夠好。例如,如果使用廣泛的個性化技術,那么客戶歷史較請求更多的處理,這會影響高端分布的性能。以平均或中位響應時間表示的服務層協議不能解決這一重要客戶群體的問題。為了解決這個問題,在亞馬遜,服務層協議是在?99.9%?的分布中被傳遞測量的。99.9%?甚至更高百分比的選擇是基于成本效益分析,該分析表明成本顯著增加,從而大大提高了性能。亞馬遜生產系統的經驗表明,與那些滿足基于平均值或中間值定義的服務層協議的系統相比,這種方法提供了更好的整體體驗。

在這篇文章中,有許多對這?99.9%?分布的引用,這反映了亞馬遜工程師從客戶體驗的角度對性能的不懈關注。許多論文都是關于平均值的,所以為了便于比較,這些都包含在內了。然而,亞馬遜的工程和優化工作并不關注平均值。一些技術,如寫協調器(write coordinators)的負載平衡選擇,純粹是為了控制?99.9%?的性能。

存儲系統通常在建立服務的服務層協議中起著重要的作用,尤其是在業務邏輯相對輕量級的情況下,就像許多亞馬遜服務一樣。然后,狀態管理成為服務的服務層協議的主要組成部分。?Dynamo 的主要設計考慮之一是讓服務控制它們的系統屬性,比如持久性和一致性,并讓服務在功能、性能和成本效益之間進行權衡。

?

?

2.3?設計考慮

商業系統中使用的數據復制算法傳統上執行同步副本協調(synchronous replica coordination),以便提供高度一致的數據訪問接口。為了達到這種程度的一致性,這些算法被迫在某些故障情況下權衡數據的可用性。例如,不是處理答案正確性/不確定性,而是在完全確定答案是正確的之前,數據是不可用的。從早期的復制數據庫工作來看,眾所周知,當處理網絡故障的可能性時,強一致性和高數據可用性不能同時實現。因此,系統和應用程序需要知道在什么條件下可以實現哪些特性。

對于容易出現服務器和網絡故障的系統,可以通過使用樂觀復制技術來提高可用性,在樂觀復制技術中,允許將更改傳播到后臺的副本,并且允許并發、斷開連接的工作。這種方法的挑戰在于,它可能導致必須檢測和解決的沖突性變更(The challenge?with this?approach is that it can lead to conflicting changes which?must be detected and resolved)。這個解決沖突的過程引入了兩個問題什么時候解決,誰來解決。Dynamo 被設計成一個最終一致的數據存儲;也就是說,所有更新最終都會到達所有副本。

一個重要的設計考慮是決定何時執行解決更新沖突的過程,即沖突是否應該在讀取或寫入期間解決。許多傳統數據存儲在寫入期間執行沖突解決,并保持簡單的讀取復雜性。在這種系統中,如果數據存儲在給定時間不能到達所有或大部分副本,則寫入可能會被拒絕。另一方面,Dynamo 的目標是?"始終可寫"?數據存儲的設計空間即,對寫入高度可用的數據存儲對于許多亞馬遜服務來說,拒絕客戶更新可能會導致糟糕的客戶體驗。例如,購物車服務必須允許客戶在網絡和服務器出現故障的情況下在購物車中添加和刪除商品。這一要求迫使我們將沖突解決的復雜性推到讀取過程上,以確保寫入永遠不會被拒絕。(何時解決)

下一個設計選擇是由誰來執行沖突解決過程。這可以通過數據存儲或應用程序來完成。如果沖突解決是由數據存儲完成的,那么它的選擇是相當有限的。在這種情況下,數據存儲只能使用簡單的策略來解決沖突的更新,例如?"最后寫入成功"。另一方面,由于應用程序知道數據模式,它可以決定最適合其客戶體驗的沖突解決方法。例如,維護客戶購物車的應用程序可以選擇?"合并"?沖突的版本,并返回一個統一的購物車。盡管有這種靈活性,一些應用程序開發人員可能不想編寫他們自己的沖突解決機制,而是選擇將其下推到數據存儲,而數據存儲又選擇一個簡單的策略,如?"最后一次寫入獲勝"(由誰解決)

設計中包含的其他關鍵原則有

增量可擴展性Dynamo 應該能夠一次橫向擴展一個存儲主機以下簡稱為?"節點"),對系統操作員和系統本身的影響最小。

對稱性Dynamo中的每個節點都應該和它的對等節點有相同的一套職責;不應該有一個或多個特殊的節點承擔特殊的角色或額外的責任。根據我們的經驗,對稱簡化了系統配置和維護的過程。

去中心化:對稱的延伸,設計應該支持去中心化的點對點技術,而不是集中控制。過去,集中控制導致停機,目標是盡可能避免停機。這導致了一個更簡單、更可擴展、更可用的系統。

異構性系統需要能夠在其運行的基礎設施中利用異構性。例如,工作分配必須與各個服務器的能力成比例。這對于添加具有更高容量的新節點而不必一次升級所有主機至關重要

?

?

3.?相關工作

3.1?P2P系統

有幾個?P2P?系統已經研究了數據存儲和分發的問題。第一代?P2P?系統,如?Freenet?和Gnutella,主要用作文件共享系統。這些是非結構化?P2P?網絡的例子,其中對等體之間的覆蓋鏈路是任意建立的。在這些網絡中,搜索查詢通常會在網絡中泛濫,以找到盡可能多的共享數據的對等點。P2P?系統發展到下一代,成為眾所周知的結構化?P2P?網絡。這些網絡采用全球一致的協議,以確保任何節點都可以高效地將搜索查詢路由到擁有所需數據的對等點。像?Pastry?和和?Chord?這樣的系統使用路由機制來確保查詢可以在有限的跳數內得到回答。為了減少由多跳路由引入的額外延遲,一些?P2P?系統采用?O(1) 路由,其中每個對等體在本地維護足夠的路由信息,使得它可以在恒定的跳數內將請求訪問數據項路由到適當的對等體。

各種存儲系統,如?Oceanstore??PAST?是建立在這些路由覆蓋的基礎上。Oceanstore?提供了一種全局、事務性、持久性存儲服務,支持對廣泛復制的數據進行序列化更新。為了允許并發更新,同時避免廣域鎖定固有的許多問題,它使用了基于沖突解決的更新模型。有的系統中引入了沖突解決,以減少事務中止的次數。Oceanstore?通過處理一系列更新來解決沖突,在它們之間選擇一個總順序,然后以該順序自動應用它們。它是為在不受信任的基礎架構上復制數據的環境而構建的。相比之下,PAST?為持久和不可變的對象提供了一個簡單的抽象層。它假設應用程序可以在其上構建必要的存儲語義例如可變文件

?

?

3.2?分布式文件系統和數據庫

在文件系統和數據庫系統社區中,為了性能、可用性和持久性而分發數據已經得到了廣泛的研究。與只支持扁平的名稱空間(flat namespaces)?P2P?存儲系統相比,分布式文件系統通常支持分層名稱空間。像?Fixes??Coda?這樣的系統以犧牲一致性為代價來復制文件以獲得高可用性。更新沖突通常使用專門的沖突解決程序來管理。Farsite?系統是一個分布式文件系統,不像?NFS?那樣使用任何集中式服務器。Farsite?使用復制實現高可用性和可擴展性。GFS 是另一個分布式文件系統,用于托管谷歌內部應用程序的狀態。GFS?使用一個簡單的設計,只有一個?master?來托管整個元數據,數據被分成塊并存儲在塊服務器中。Bayou?是一個分布式關系數據庫系統,它允許斷開連接的操作,并提供最終的數據一致性。

在這些系統中,Bayou、Coda??Ficus?允許斷開連接的操作,并對網絡分區和中斷等問題具有彈性。這些系統在沖突解決程序上有所不同。例如,Coda??Ficus?執行系統級沖突解決,Bayou?允許應用程序級解決。然而,所有這些都保證了最終的一致性。與這些系統類似,?Dynamo 允許讀寫操作甚至在網絡分區期間繼續進行,并使用不同的沖突解決機制來解決更新的沖突。像?FAB?這樣的分布式塊存儲系統將大型對象分割成較小的塊,并以高度可用的方式存儲每個塊。與這些系統相比,鍵值存儲在這種情況下更合適,因為(a) 它旨在存儲相對較小的對象大小< 1M)。?(b) 鍵值存儲更容易根據每個應用程序進行配置。Antiquity?是一個廣域分布式存儲系統,旨在處理多個服務器故障。它使用安全日志(secure log)來保持數據完整性,在多臺服務器上復制每個日志以獲得持久性,并使用拜占庭容錯協議來確保數據一致性。?Antiquity?相比,Dynamo 不關注數據完整性和安全性問題,而是為可信環境而構建。Bigtable?是一個用于管理結構化數據的分布式存儲系統。它維護一個稀疏的多維排序?map,并允許應用程序使用多個屬性訪問它們的數據。?Bigtable?相比,Dynamo?的目標應用程序只需要鍵/值訪問,主要關注高可用性,即使在網絡分區或服務器出現故障時,更新也不會被拒絕。

傳統的復制關系數據庫系統關注于保證復制數據的強一致性問題。雖然強大的一致性為應用程序作者提供了一個方便的編程模型,但這些系統在可擴展性和可用性方面受到限制。這些系統不能處理網絡分區,因為它們通常提供強大的一致性保證。

?

?

3.3?討論

Dynamo 在目標要求方面不同于上述去中心化存儲系統。首先,Dynamo 主要面向那些需要?"始終可寫"?數據存儲的應用程序,在這些應用程序中,不會有因失敗或并發寫入而被拒絕的更新。這是許多亞馬遜應用程序的一個關鍵要求。其次,如前所述,Dynamo 是為單個管理域內的基礎架構而構建的,其中所有節點都被認為是可信的。第三,使用?Dynamo?的應用程序不需要支持分層名稱空間許多文件系統中的一種規范或復雜的關系模式由傳統數據庫支持。第四,Dynamo 是為延遲敏感的應用程序而構建的,這些應用程序需要在數百毫秒內執行至少?99.9%?的讀寫操作。為了滿足這些嚴格的延遲要求,我們必須避免通過多個節點路由請求這是?Chord??Pastry?等幾個分布式哈希表系統采用的典型設計。這是因為多跳路由增加了響應時間的可變性,從而增加了更高百分比的延遲。Dynamo 可以被描述為零跳分布式哈希表(Dynamo can be?characterized as a zero-hop DHT),其中每個節點在本地維護足夠的路由信息,以將請求直接路由到適當的節點。

?

?

4.?系統結構

需要在生產環境中運行的存儲系統的體系結構非常復雜。除了實際的數據持久性組件之外,系統還需要針對負載均衡、成員資格和故障檢測、故障恢復、副本同步、過載處理、狀態轉移、并發和作業調度、請求編組、請求路由、系統監控和報警以及配置管理等方面提供可擴展且強健的解決方案。描述每一個解決方案的細節是不可能的,所以本文主要關注?Dynamo 中使用的核心分布式系統技術分區、復制、版本控制、成員資格、故障處理和擴展。表 1 總結了 Dynamo 使用的技術及其各自的優勢。

?

4.1?系統接口

Dynamo 通過一個簡單的接口存儲與一個?key 相關聯的對象;它公開了兩個操作get() 和put() get(key) 操作在存儲系統中定位與?key 相關聯的對象副本,并返回單個對象或具有沖突版本的對象列表以及上下文。put(key, context, object) 操作根據關聯的?key 確定對象的副本應該放在哪里,并將副本寫入磁盤。context?對調用方不透明的關于對象的系統元數據進行編碼,并包括諸如對象版本等信息。上下文信息與對象一起存儲,以便系統可以驗證?put?請求中提供的上下文對象的有效性。

Dynamo 將調用者提供的?key 和對象都視為不透明的字節數組。它對?key 應用?MD5?哈希來生成?128?位標識符,該標識符用于確定負責提供?key 的存儲節點。

?

?

4.2?分區算法

Dynamo 的關鍵設計要求之一是它必須逐步擴展。這需要一種在系統中的一組節點即存儲主機上動態劃分數據的機制。Dynamo 的分區方案依靠一致性哈希算法在多個存儲主機之間分配負載。在一致性哈希算法中,哈希函數的輸出范圍被視為固定的循環空間或?""(即最大的哈希值繞到最小的哈希值。系統中的每個節點在這個空間內被分配一個隨機值,代表它在環上的?"位置"。由?key 標識的每個數據項通過哈希數據項的?key 以產生其在環上的位置而被分配給一個節點,然后順時針遍歷環以找到位置大于該項的位置的第一個節點。因此,每個節點對其與環上的前一個節點之間的環中的區域負責。一致性哈希的主要優點是,一個節點的離開或到達只影響它的近鄰,而其他節點不受影響。

基本的一致性哈希算法帶來了一些挑戰。首先,環上每個節點的隨機位置分配導致數據和負載分布不均勻。第二,基本算法忽略了節點性能的異質性不同結點處理數據的能力不同為了解決這些問題,Dynamo 使用了一致性哈希算法的變體不是將一個節點映射到圓中的一個點,而是將每個節點分配到環中的多個點。為此,Dynamo 使用了?"虛擬節點"?的概念。虛擬節點看起來像系統中的單個節點,但是每個節點可以負責多個虛擬節點。實際上,當一個新節點被添加到系統中時,它會在環中被分配多個位置此后稱為?"tokens")。第?6?節討論了微調?Dynamo 分區方案的過程。使用虛擬節點有以下優點

(1) 如果某個節點變得不可用由于故障或日常維護,則該節點處理的負載將平均分布在剩余的可用節點上。

(2) 當一個節點再次變得可用時,或者一個新節點被添加到系統中時,新的可用節點從每個其他可用節點接受大致相等的負載量。

(3) 考慮到物理基礎架構的異構性,節點負責的虛擬節點數量可以根據其容量來決定。

?

?

4.3?復制

為了實現高可用性和持久性,Dynamo 在多臺主機上復制其數據。每個數據項在?N?個主機上復制,其中?N?是一個?"每個實例"?配置的參數。每個密鑰?k?被分配給一個協調器節點在前一節中有描述。協調器負責復制其范圍內的數據項。除了在本地存儲其范圍內的每個密鑰之外,協調器還在環中的?N-1?個順時針后續節點上復制這些密鑰。這導致一個系統,其中每個節點負責它和它的第?N?個前身之間的環的區域。在圖?2?中,節點?B?除了在本地存儲密鑰?k?之外,還在節點?C?和節點?D?復制密鑰?k。節點?D?將存儲屬于范圍?(A,B](B,C] ?(C,D] 的鍵。

負責存儲特定?key 的節點列表稱為首選項列表。該系統的設計將在第?4.8?節中進行解釋,以便系統中的每個節點都可以確定對于任何特定的鍵,哪些節點應該在該列表中。考慮到節點故障,首選列表包含?N?個以上的節點。注意,通過使用虛擬節點,特定密鑰的前?N?個后繼位置可能由少于?N?個不同的物理節點擁有即,一個節點可以持有前?N?個位置中的多于一個。為了解決這個問題,通過跳過環中的位置來構建鍵的偏好列表,以確保該列表僅包含不同的物理節點。

?

?

4.4?數據版本控制

Dynamo?提供了最終的一致性,允許更新異步傳播到所有副本。在所有副本應用更新之前,put() 調用可能會返回到其調用,這可能會導致后續?get() 操作可能會返回沒有最新更新的對象的情況如果沒有失敗,則更新傳播時間有一個界限。但是,在某些故障情況下例如,服務器中斷或網絡分區,更新可能不會在很長一段時間內到達所有副本。

亞馬遜的平臺上有一類應用可以容忍這種不一致,并且可以被構建為在這些條件下運行。例如,購物車應用程序要求?"添加到購物車"?操作永遠不能被忘記或拒絕。如果購物車的最新狀態不可用,并且用戶對購物車的舊版本進行了更改,則該更改仍然有意義,應該保留。但與此同時,它不應該取代購物車當前不可用的狀態,購物車本身可能包含應該保留的更改。請注意,"添加到購物車"??"從購物車中刪除項目"?操作都被轉換為向?Dynamo 發出的請求。當顧客想要將物品添加到購物車或從購物車中移除并且最新版本不可用時,該物品被添加到舊版本或從舊版本中移除,并且不同的版本稍后被協調處理

為了提供這種保證,Dynamo 將每次修改的結果視為數據的新的不可變版本。它允許一個對象的多個版本同時出現在系統中。大多數情況下,新版本包含以前的版本,系統本身可以確定權威版本語法協調但是,在出現故障和并發更新的情況下,可能會發生版本分支,從而導致對象的版本沖突。在這些情況下,系統無法協調同一對象的多個版本,客戶端必須執行協調,以便將數據演化的多個分支折疊回一個分支語義協調。折疊操作的一個典型例子是?"合并"?客戶購物車的不同版本。使用這種協調機制,"添加到購物車"?操作永遠不會丟失。但是,刪除的項目可能會重新出現。

重要的是要理解,某些故障模式可能會導致系統不僅有兩個版本,而且有幾個版本的相同數據。存在網絡分區和節點故障時的更新可能會導致對象具有不同的版本,系統需要在將來對其進行協調。這要求我們設計明確承認同一數據的多個版本的可能性的應用程序為了永遠不會丟失任何更新

Dynamo 使用矢量時鐘來捕捉同一對象不同版本之間的因果關系。向量時鐘實際上是(node, counter) 對的列表。一個矢量時鐘與每個對象的每個版本相關聯。人們可以通過檢查一個對象的矢量時鐘來確定它的兩個版本是在平行的分支上還是有因果關系。如果第一個對象時鐘上的計數器小于或等于第二個時鐘上的所有節點,那么第一個是第二個的祖先,可以被忘記。否則,這兩個變化被認為是沖突的,需要和解。

?Dynamo?中,當客戶端希望更新一個對象時,它必須指定要更新哪個版本。這是通過傳遞它從先前的讀取操作中獲得的上下文來完成的,該上下文包含向量時鐘信息。在處理一個讀請求時,如果?Dynamo?訪問了多個無法在語法上協調的分支,它將返回葉處的所有對象,以及上下文中相應的版本信息。使用該上下文的更新被認為已經協調了不同的版本,并且分支被折疊成單個新版本。

為了說明矢量時鐘的使用,讓我們考慮圖?3?所示的例子。客戶端寫入新對象。處理這個鍵的寫操作的節點比如Sx增加了它的序列號,并使用它來創建數據的向量時鐘。系統現在有了對象?D1?及其相關的時鐘?[(Sx,1)]。客戶端更新對象。假設同一個節點也處理這個請求。系統現在也有對象?D2?和它相關的時鐘?[(Sx,2)]。D2??D1?的后裔,因此對?D1?寫得過多,然而可能有?D1?的復制品在尚未見到?D2?的節點上徘徊。讓我們假設同一個客戶端再次更新對象,并且不同的服務器比如Sy處理該請求。系統現在有數據?D3?及其相關時鐘[(Sx,2)(Sy,1)]。

接下來,假設一個不同的客戶端讀取?D2,然后嘗試更新它,另一個節點比如Sz執行寫入。系統現在有?D4D2?的后裔,它的版本時鐘是?[(Sx,2)(Sz,1)]。知道?D1??D2?的節點可以在接收到?D4?及其時鐘時確定?D1??D2?被新數據覆蓋并且可以被垃圾回收。知道?D3?并接收?D4?的節點會發現它們之間沒有因果關系。換句話說,D3??D4?的變化沒有相互反映。數據的兩個版本都必須保存并呈現給客戶端在讀取時,以便進行語義協調。

現在假設一些客戶端讀取?D3??D4上下文將反映這兩個值都是通過讀取找到的。讀者的上下文是?D3??D4?時鐘的摘要,即?[(Sx,2)(Sy,1)(Sz,1)]。如果客戶端執行協調,并且節點?Sx?協調寫入,Sx?將更新其在時鐘中的序列號。新數據?D5?將有以下時鐘[(Sx,3)(Sy,1)(Sz,1)]。

向量時鐘的一個可能問題是,如果許多服務器協調對對象的寫入,向量時鐘的大小可能會增加。實際上,這是不可能的,因為寫入通常由首選項列表中的前?N?個節點之一處理。在網絡分區或多個服務器出現故障的情況下,寫請求可能由不在首選項列表前?N?個節點中的節點處理,導致矢量時鐘的大小增加。在這些情況下,最好限制矢量時鐘的大小。為此,Dynamo 采用了以下時鐘截斷方案與每個?(node, counter)?對一起,Dynamo 存儲一個時間戳,該時間戳指示節點上次更新數據項的時間。當向量時鐘中的?(node, counter)?對的數量達到閾值比如?10時,從時鐘中移除最老的對。顯然,這種截斷方案會導致協調效率低下,因為不能準確地導出后代關系。然而,這個問題在生產中沒有出現,因此這個問題沒有得到徹底調查分析

?

?

4.5 get() ?put() 操作的執行

Dynamo 中的任何存儲節點都有資格接收任何?key 的客戶端?get ?put 操作。在本節中,為了簡單起見,我們描述了如何在無故障環境中執行這些操作,在后續章節中,我們描述了如何在故障期間執行讀寫操作。

get ?put 操作都是使用亞馬遜的基礎設施特定的請求處理框架通過?HTTP 協議調用的。客戶端可以使用兩種策略來選擇節點(1) 通過通用負載平衡器路由其請求,該負載平衡器將根據負載信息選擇節點,或者?(2) 使用分區感知客戶端庫,該庫將請求直接路由到適當的協調器節點。第一種方法的優點是客戶端不必在其應用程序中鏈接任何特定于?Dynamo 的代碼,而第二種策略可以實現更低的延遲,因為它跳過了潛在的轉發步驟。

處理讀或寫操作的節點稱為協調器。通常,這是首選項列表中前?N?個節點中的第一個。如果請求是通過負載均衡器接收的,則訪問?key 的請求可以被路由到環中的任何隨機節點。在這種情況下,如果接收請求的節點不在所請求?key 的首選項列表的前?N?名中,則該節點將不會協調它。相反,該節點會將請求轉發給首選項列表中前?N?個節點中的第一個。讀寫操作涉及首選項列表中的前?N?個健康節點,跳過那些關閉或不可訪問的節點。當所有節點都正常時,訪問鍵的首選列表中的前?N?個節點。當存在節點故障或網絡分區時,訪問在首選項列表中排名較低的節點。

為了保持副本之間的一致性,Dynamo 使用了類似于使用法定人數系統(quorum systems)中使用的一致性協議。該協議有兩個關鍵的可配置值R??W。R?是成功讀取操作必須參與的最小節點數。W 是成功寫入操作必須參與的最小節點數。設置?R??W,使得?R + W > N?產生一個類似群體的系統。在這個模型中,get?put操作的延遲由最慢的復制決定。因此,R??W?通常配置為小于?N,以提供更好的延遲。

當接收到一個?key??put() 請求時,協調器為新版本生成向量時鐘,并在本地寫入新版本。然后,協調器將新版本(連同新的矢量時鐘)發送到?N?個排名最高的可到達節點。如果至少有?W-1?節點響應,則認為寫入成功。

類似地,對于?get() 請求,協調器從該關鍵字的首選項列表中排名最高的?N?個可達節點請求該關鍵字的所有現有數據版本,然后在將結果返回給客戶端之前等待?R?個響應。如果協調器最終收集了數據的多個版本,它會返回所有它認為不相關的版本。然后,不同的版本被協調,取代當前版本的協調版本被寫回。

?

?

4.6?處理故障提示移交

如果?Dynamo 使用傳統的方法,它將在服務器故障和網絡分區期間不可用,并且即使在最簡單的故障條件下也會降低耐用性。為了彌補這一點,它沒有強制執行嚴格的法定人數成員,而是使用了?"草率的法定人數";所有讀和寫操作都是在首選項列表中的前?N?個健康節點上執行的,這可能不總是在遍歷一致性哈希環時遇到的前?N?個節點。

考慮圖?2?中給出的?Dynamo 配置的例子,N?=?3。在本例中,如果節點?A?在寫入操作期間暫時關閉或不可訪問,則通常位于節點?A?上的副本現在將被發送到節點?D。這樣做是為了保持所需的可用性和持久性保證。發送到?D?的副本在其元數據中將有一個提示,提示哪個節點是副本的預期接收者在本例中為?A。收到提示副本的節點會將它們保存在一個單獨的本地數據庫中,并定期進行掃描。一旦檢測到?A?已經恢復,D?將嘗試將副本傳送給?A。一旦傳輸成功,D?可以從其本地存儲中刪除該對象,而不會減少系統中副本的總數。

使用提示切換,Dynamo 確保讀寫操作不會因臨時節點或網絡故障而失敗。需要最高級別可用性的應用程序可以將?W?設置為?1,這可以確保只要系統中的單個節點將?key 持久寫入其本地存儲,寫入就可以被接受。因此,只有當系統中的所有節點都不可用時,寫請求才會被拒絕。但實際上,生產中的亞馬遜大部分服務都設置了較高的?W,以滿足期望的耐用性水平。第?6?節將更詳細地討論配置?N、R??W。

高度可用的存儲系統必須能夠處理整個數據中心的故障。數據中心故障是由于斷電、冷卻故障、網絡故障和自然災害造成的。Dynamo?配置為每個對象在多個數據中心之間復制。本質上,key 的首選列表是這樣構建的,即存儲節點分布在多個數據中心。這些數據中心通過高速網絡連接在一起。這種跨多個數據中心復制的方案允許我們在不中斷數據的情況下處理整個數據中心的故障。

?

?

4.7?處理永久故障副本同步

如果系統成員流失率較低并且節點故障是暫時的,則暗示切換效果最佳。在某些情況下,提示副本(hinted replicas)在返回到原始副本節點之前變得不可用。為了處理這種和其他對持久性的威脅,Dynamo 實現了一個反熵(anti-entropy)(副本同步協議來保持副本的同步。

為了更快地檢測副本之間的不一致,并最大限度地減少傳輸的數據量,Dynamo 使用了Merkle?樹。Merkle?樹是一種?hash 樹,葉子是各個鍵的值的哈希。樹中較高的父節點是它們各自子節點的?hash。Merkle?樹的主要優點是可以獨立檢查樹的每個分支,而不需要節點下載整個樹或整個數據集。此外,Merkle?樹有助于減少需要傳輸的數據量,同時檢查副本之間的不一致性。例如,如果兩棵樹的根的哈希值相等,則樹中葉節點的值相等,并且節點不需要同步。如果沒有,則意味著某些副本的值不同。在這種情況下,節點可以交換子節點的哈希值,并且該過程繼續進行,直到到達樹葉,此時主機可以識別?"不同步"??keyMerkle?樹最大限度地減少了同步所需傳輸的數據量,并減少了反熵過程中執行的磁盤讀取次數。

Dynamo 使用?Merkle?樹進行反熵,如下所示每個節點為其托管的每個?key 范圍虛擬節點覆蓋的密鑰集維護一個單獨的?Merkle?樹。這允許節點比較一個鍵范圍內的鍵是否是最新的。在該方案中,兩個節點交換對應于它們共同擁有的?key 范圍的?Merkle?樹的根。隨后,使用上述樹遍歷方案,節點確定它們是否有任何差異,并執行適當的同步動作。該方案的缺點是,當節點加入或離開系統時,許多關鍵范圍會改變,從而需要重新計算樹。然而,這個問題是通過第?6.2?節中描述的細化分區方案來解決的。

?

?

4.8?成員資格和故障檢測

4.8.1?Ring Membership

在亞馬遜的環境中,節點中斷由于故障和維護任務通常是短暫的,但可能會持續很長時間。節點中斷很少意味著永久脫離,因此不應導致分區分配的重新平衡或不可達副本的修復。類似地,手動錯誤可能會導致新?Dynamo 節點的意外啟動。由于這些原因,使用顯式機制來啟動從?Dynamo 環添加和移除節點被認為是合適的。管理員使用命令行工具或瀏覽器連接到?Dynamo 節點,并發布成員資格更改,以將節點加入環或從環中刪除節點。服務于該請求的節點將成員變更及其發布時間寫入持久存儲。成員關系的變化形成了一個歷史,因為節點可以多次刪除和添加回來。基于?gossip 協議傳播成員關系的變化,并維護最終一致的成員關系視圖。每個節點每秒鐘都會聯系一個隨機選擇的對等節點,這兩個節點可以有效地協調它們持久的成員關系變化歷史。

當一個節點第一次啟動時,它選擇它的令牌集(set of tokens)(一致性哈希空間中的虛擬節點,并將節點映射到它們各自的令牌集。映射保存在磁盤上,最初只包含本地節點和令牌集。存儲在不同?Dynamo 節點上的映射在協調成員資格改變歷史的相同通信交換期間被協調。因此,分區和放置信息也通過基于?gossip 協議傳播,并且每個存儲節點都知道其對等節點處理的令牌范圍。這允許每個節點將?key 的讀/寫操作直接轉發到正確的節點集。

?

4.8.2?外部發現

上述機制可能暫時導致一個邏輯分區的?Dynamo?環。例如,管理員可以聯系節點?A?將節點?A?加入環,然后聯系節點?B?將節點?B?加入環。在這種情況下,節點?A?和節點?B?都認為自己是環中的一員,但兩者都不會立即意識到對方。為了防止邏輯分區,一些?Dynamo 節點扮演種子的角色。種子是通過外部機制被發現,同時,所有節點都知道它的存在。因為所有節點最終都用一個種子來協調它們的成員關系,所以邏輯分區是極不可能的。種子可以從靜態配置或配置服務中獲得。種子通常是?Dynamo 環中功能齊全的節點。

?

4.8.3?故障檢測

Dynamo中的故障檢測用于避免在?get() ?put() 操作期間以及傳輸分區和提示副本時嘗試與不可達的對等通信。為了避免失敗的通信嘗試,故障檢測的純本地概念是完全足夠的如果節點?B?不響應節點?A?的消息即使節點?B?響應節點?C?的消息,節點?A?可以認為節點?B?失敗。在?Dynamo 環中產生節點間通信的客戶端請求的穩定速率存在的情況下,當節點?B?未能響應消息時,節點?A?迅速發現節點?B?無響應;然后,節點?A?使用備用節點來服務映射到節點?B?的分區的請求;甲定期重試乙,以檢查后者的恢復。在沒有客戶端請求來驅動兩個節點之間的流量的情況下,兩個節點都不需要知道另一個節點是否可達和響應。

去中心化故障檢測協議使用簡單的?gossip 協議,使系統中的每個節點能夠了解其他節點的加入(或離開。關于去中心化式故障檢測器和影響其準確性的參數的詳細信息,請感興趣的讀者參考。Dynamo 的早期設計使用去中心化的故障檢測器來保持故障狀態的全局一致性。后來確定,顯式節點加入和離開方法消除了對故障狀態全局視圖的需要。這是因為節點通過顯式節點加入和離開方法被通知永久節點添加和移除,并且當單個節點無法與其他節點通信時在轉發請求時,臨時節點故障被檢測到。

?

4.9?添加/刪除存儲節點

當一個新節點比如說?X被添加到系統中時,它會被分配一些令牌,這些令牌隨機分布在環上。對于分配給節點?X?的每個密鑰范圍,可能有許多節點小于或等于?N當前負責處理屬于其令牌范圍內的密鑰。由于將密鑰范圍分配給?X,一些現有的節點不再需要它們的一些密鑰,這些節點將這些密鑰傳輸給?X。讓我們考慮一個簡單的自舉場景,其中節點?X?被添加到圖?2?所示的?A??B 之間的環中。當?X?被添加到系統中時,它負責將密鑰存儲在范圍(F,G]、(G,A] ?(A,X] 中。因此,節點?B、C??D?不再需要存儲這些各自范圍內的密鑰。因此,節點?B、C??D?將向?X?提供并在?X?確認后傳輸適當的密鑰集。當一個節點從系統中移除時,密鑰的重新分配以相反的過程發生。

運行經驗表明,這種方法在存儲節點之間均勻地分配密鑰分配負載,這對于滿足延遲要求和確保快速引導非常重要。最后,通過在源節點和目標節點之間添加一輪確認,可以確保目標節點在給定的密鑰范圍內不會接收到任何重復的傳輸。

?

?

5.?實現

?Dynamo?中,每個存儲節點都有三個主要的軟件組件請求協調、成員資格和故障檢測以及本地持久性引擎。所有這些組件都是用?Java?實現的。

Dynamo 的本地持久組件允許插入不同的存儲引擎。正在使用的引擎是?Berkeley?數據庫BDB事務數據存儲、BDB Java?版、MySQL?和一個帶有持久后備存儲的內存緩沖區。設計可插拔持久性組件的主要原因是選擇最適合應用程序訪問模式的存儲引擎。例如,BDB?通常可以處理幾十?kb 的對象,而?MySQL?可以處理更大的對象。應用程序根據其對象大小分布選擇?Dynamo 的本地持久性引擎。Dynamo 的大多數生產實例使用?BDB?交易數據存儲。

請求協調組件建立在事件驅動的消息傳遞基礎之上,其中消息處理流水線被分成多個階段,類似于?SEDA?架構。所有通信都是使用?Java NIO?通道實現的。協調器通過從一個或多個節點收集數據在讀取的情況下或在一個或多個節點存儲數據用于寫入來代表客戶端執行讀取和寫入請求。每個客戶端請求都會導致在接收客戶端請求的節點上創建一個狀態機。狀態機包含識別負責密鑰的節點、發送請求、等待響應、可能進行重試、處理響應以及將響應打包到客戶端的所有邏輯。每個狀態機實例只處理一個客戶端請求。例如,讀操作實現以下狀態機(1) 向節點發送讀請求,(2) 等待所需響應的最小數量,(3) 如果在給定的時間范圍內收到太少的響應,則請求失敗,(4) 否則收集所有數據版本并確定要返回的版本,以及(5) 如果啟用了版本控制,則執行語法協調并生成包含所有剩余版本的矢量時鐘的不透明寫上下文。為了簡潔起見,省略了故障處理和重試狀態。

在讀響應返回給調用方之后,狀態機等待一小段時間以接收任何未完成的響應。如果在任何響應中返回了過時版本,協調器會用最新版本更新這些節點。這個過程被稱為讀取修復,因為它在一個時刻修復了錯過最近更新的副本,并且解除了反熵協議必須做的事情。

如前所述,寫請求由首選項列表中的前?N?個節點之一協調。盡管總是希望讓前?N?個節點中的第一個節點來協調寫入,從而在單個位置序列化所有寫入,但這種方法導致了不均勻的負載分布,從而導致違反服務層協議這是因為請求負載不是均勻分布在對象之間的。為了解決這個問題,首選項列表中的前?N?個節點中的任何一個都可以協調寫入。特別地,由于每次寫操作通常跟隨讀操作,所以寫操作的協調器被選擇為對存儲在請求的上下文信息中的先前讀操作做出最快響應的節點。這種優化使我們能夠選擇包含由之前的讀取操作讀取的數據的節點,從而增加了獲得?"-"?一致性的機會。它還減少了請求處理性能的可變性,從而將性能提高到?99.9%。

?

?

6.?經驗和教訓

Dynamo?被幾種不同配置的服務使用。這些實例因其版本協調邏輯和讀/寫仲裁特征而不同。以下是?Dynamo 使用的主要模式

業務邏輯特定的協調這是?Dynamo 的一個常見用例。每個數據對象跨多個節點復制。在不同版本的情況下,客戶端應用程序執行自己的協調邏輯。前面討論的購物車服務就是這類服務的一個典型例子。它的業務邏輯通過合并客戶購物車的不同版本來協調對象。

基于時間戳的協調這種情況與前一種情況的不同之處僅在于協調機制。在不同版本的情況下,Dynamo 執行簡單的基于時間戳的?"最后寫入獲勝"?的協調邏輯;即具有最大物理時間戳值的對象被選為正確的版本。維護客戶會話信息的服務是使用這種模式的服務的一個很好的例子。

高性能讀取引擎雖然?Dynamo 被構建為一個?"始終可寫"?的數據存儲,但一些服務正在調整其仲裁特征,并將其用作高性能讀取引擎。通常,這些服務的讀取請求率很高,只有少量更新。在這種配置中,通常將?R?設置為?1,將?W?設置為?N。對于這些服務,Dynamo 提供了跨多個節點分區和復制數據的能力,從而提供了增量可擴展性。其中一些實例充當存儲在更大權重后備存儲中的數據的權威持久性緩存。維護產品目錄和促銷項目的服務屬于這一類。

Dynamo 的主要優勢是其客戶端應用程序可以調整?N、R??W?的值,以實現所需的性能、可用性和耐用性水平。例如,N?的值決定了每個物體的耐久性。Dynamo 的用戶使用的一個典型的?N?值是?3。

W??R?的值影響對象的可用性、持久性和一致性。例如,如果?W?設置為?1,則只要系統中至少有一個節點可以成功處理寫請求,系統就永遠不會拒絕寫請求。然而,較低的?W??R?值會增加不一致的風險,因為寫請求被認為是成功的,并返回給客戶端,即使它們沒有被大多數副本處理。這還會在寫入請求成功返回到客戶端時引入一個持久性漏洞窗口,即使它只在少數節點上保持不變(This?also introduces a vulnerability window for durability when a write?request is successfully returned to the client even?though it has?been persisted at only a small number of nodes)

傳統方法認為耐用性和可用性是相輔相成的。然而,這里不一定是這樣。例如,可以通過增加?W?來減少持久性的漏洞窗口。這可能會增加拒絕請求的概率從而降低可用性,因為需要更多的存儲主機處于活動狀態才能處理寫請求。Dynamo 的幾個實例使用的常見配置 ?(N,R,W)?3,2,2。選擇這些值是為了滿足必要的性能、持久性、一致性和可用性級別協議。

本節中介紹的所有測量都是在運行配置為3,2,2的實時系統上進行的,該系統運行數百個具有相同硬件配置的節點。如前所述,Dynamo 的每個實例都包含位于多個數據中心的節點。這些數據中心通常通過高速網絡鏈接連接。回想一下,要生成成功的?get?put響應,節點需要響應協調器。顯然,數據中心之間的網絡延遲會影響響應時間,節點及其數據中心位置的選擇會滿足應用程序的目標服務層協議

?

?

6.1?平衡性能和耐用性

雖然?Dynamo 的主要設計目標是建立一個高度可用的數據存儲,但性能在亞馬遜的平臺上是一個同樣重要的標準。如前所述,為了提供一致的客戶體驗,亞馬遜的服務將性能目標設置在較高的百分點?99.9%??99.99%。使用?Dynamo 的服務需要的典型服務層協議?99.9%?的讀寫請求在?300?毫秒內執行。

由于?Dynamo 運行在標準的商用硬件組件上,這些組件的輸入/輸出吞吐量遠遠低于高端企業服務器,因此為讀寫操作提供一致的高性能是一項非常重要的任務。多個存儲節點參與讀寫操作使其更具挑戰性,因為這些操作的性能受到最慢的讀寫副本的限制。圖?4?顯示了?30?天內?Dynamo 讀寫操作的平均延遲和?99.9%?延遲。如圖所示,延遲呈現出明顯的晝夜模式,這是傳入請求速率的晝夜模式的結果即,白天和夜晚之間的請求速率存在顯著差異。此外,寫延遲明顯高于讀延遲,因為寫操作總是導致磁盤訪問。還有,99.9%?的延遲約為?200?毫秒,比平均值高一個數量級。這是因為?99.9%?的延遲受幾個因素的影響,如請求負載的可變性、對象大小和位置模式。

雖然這種性能水平對于許多服務來說是可以接受的,但是一些面向客戶的服務需要更高的性能水平。對于這些服務,Dynamo 提供了權衡耐用性保證和性能的能力。在優化中,每個存儲節點在其內存中維護一個對象緩沖區。每個寫操作都存儲在緩沖區中,并由寫線程定期寫入存儲。在該方案中,讀取操作首先檢查所請求的密鑰是否存在于緩沖區中。如果是這樣,則從緩沖區而不是存儲引擎中讀取對象。

這種優化使得?99.9%?的延遲在高峰流量期間降低了?5?倍,即使是一千個對象的非常小的緩沖區也是如此參見圖?5。此外,如圖所示,寫緩沖可以消除較高百分比的延遲。顯然,這個方案是以性能換取耐用性的。在這種方案中,服務器崩潰會導致緩沖區中排隊的寫入丟失。為了降低持久性風險,寫入操作被細化為讓協調器從?N?個副本中選擇一個來執行?"持久性寫入"。因為協調器只等待?W?響應,所以寫操作的性能不受單個副本執行的持久寫操作的性能的影響。

?

?

6.2?確保均勻的負載分布

Dynamo 使用一致的哈希算法在副本之間劃分其?key 空間,并確保均勻的負載分布。假設?key 的訪問分布不是高度傾斜的,統一的?key 分布可以幫助我們實現統一的負載分布。具體來說,Dynamo 的設計假設即使在訪問分布中存在明顯的偏斜,在分布的流行端也有足夠的?key,以便處理熱點?key 的負載可以通過分區均勻地分布在節點上。本節討論了?Dynamo 中的負載不平衡以及不同分區策略對負載分布的影響。

為了研究負載不平衡及其與請求負載的相關性,對每個節點接收的請求總數進行了?24?小時的測量,細分為?30?分鐘的間隔。在給定的時間窗口內,如果節點的請求負載偏離平均負載的值小于某個閾值此處為?15%,則該節點被視為?"不平衡"。否則,該節點被視為?"失衡"。圖?6?顯示了這段時間內?"失衡"(以下稱為?"失衡比率")的節點比例。作為參考,整個系統在此期間接收到的相應請求負載也被繪制出來。如圖所示,不平衡率隨著負載的增加而降低。例如,在低負載期間,不平衡率高達?20%,而在高負載期間,不平衡率接近?10%。直觀地說,這可以用以下事實來解釋在高負載下,大量熱點?key 被訪問,并且由于密鑰的均勻分布,負載被均勻分布。然而,在低負載(負載是測量的峰值負載的?1/8)期間,訪問的熱點 key 較少,從而導致更高的負載不平衡。本節討論了?Dynamo 的分區方案是如何隨著時間的推移而演變的,以及它對負載分布的影響。

策略1每個節點測試隨機令牌,并根據令牌值進行分區這是在生產中部署的初始策略在第?4.2?節中有所描述。在這個方案中,每個節點都被分配了?T?個令牌從散列空間中統一隨機選擇。所有節點的標記根據它們在哈希空間中的值進行排序。每兩個連續的標記定義一個范圍。最后一個標記和第一個標記形成一個范圍,該范圍在散列空間中從最高值到最低值?"環繞"。因為令牌是隨機選擇的,所以范圍大小不一。隨著節點加入和離開系統,令牌集會發生變化,因此范圍也會發生變化。請注意,維護每個節點的成員資格所需的空間隨著系統中節點數量的增加而線性增加。

使用此策略時,遇到了以下問題。首先,當一個新節點加入系統時,它需要從其他節點?"竊取"?它的密鑰范圍。然而,將密鑰范圍移交給新節點的節點必須掃描它們的本地持久性存儲來檢索適當的數據項集合。請注意,在生產節點上執行這樣的掃描操作很棘手,因為掃描是高度資源密集型操作,并且需要在后臺執行,而不會影響客戶性能。這要求我們以最低優先級運行引導任務。然而,這大大降低了引導過程,在繁忙的購物季節,當節點每天處理數百萬個請求時,引導幾乎需要一天才能完成。第二,當一個節點加入/離開系統時,由許多節點處理的?key 范圍發生變化,并且需要重新計算新范圍的?Merkle?樹,這是一個在生產系統上執行的非常重要的操作。最后,由于密鑰范圍的隨機性,沒有簡單的方法來拍攝整個密鑰空間的快照,這使得存檔過程變得復雜。在這個方案中,歸檔整個密鑰空間需要我們分別從每個節點檢索密鑰,這是非常低效的。

?

這種策略的根本問題是數據分區和數據放置的方案是相互交織的。例如,在某些情況下,為了處理請求負載的增加,最好向系統添加更多的節點。但是,在這種情況下,不可能在不影響數據分區的情況下添加節點。理想情況下,最好使用獨立的分區和放置方案。為此,評估了以下戰略

策略2每個節點?T?個隨機令牌和相等大小的分區在這個策略中,散列空間被分成?Q?個相等大小的分區/范圍,每個節點被分配?T?個隨機令牌。Q?通常設置為?Q >> N??Q >> S*T,其中?S?是系統中的節點數。在這種策略中,令牌僅用于構建將散列空間中的值映射到有序節點列表的函數,而不是決定分區。一個分區被放置在從該分區的末端順時針遍歷一致性哈希環時遇到的前?N?個唯一節點上。圖?7?說明了?N?=?3?的策略。在這個例子中,節點?A、B、C?在從包含密鑰?k1?的分區的末端遍歷環時遇到。這種策略的主要優點是(1) 分區和分區放置的解耦,以及?(2) 能夠在運行時更改放置方案。

?

策略3每個節點?Q/S?令牌,大小相等的分區與策略?2?類似,該策略將哈希空間劃分為Q?個大小相等的分區,分區的放置與分區方案解耦。此外,每個節點都被分配了?Q/S?令牌,其中?S?是系統中的節點數。當一個節點離開系統時,它的令牌被隨機分配給剩余的節點,這樣這些屬性被保留。類似地,當一個節點加入系統時,它會以保留這些屬性的方式從系統中的節點?"竊取"?令牌。

對于一個?S?=?30,N?=?3?的系統,對這三種策略的效率進行了評估。然而,公平地比較這些不同的策略是困難的,因為不同的策略有不同的配置來調整它們的效率。例如,策略?1?的負載分布屬性取決于令牌的數量?T,而策略?3?取決于分區的數量?Q比較這些策略的一個公平的方法是評估負載分布的偏差,而所有策略都使用相同的空間來維護其成員信息。例如,在策略?1?中,每個節點需要維護環中所有節點的令牌位置,而在策略?3?中,每個節點需要維護關于分配給每個節點的分區的信息。

在我們的下一個實驗中,通過改變相關參數T??Q來評估這些策略。每種策略的負載平衡效率是針對每個節點需要維護的不同大小的成員信息來衡量的,其中負載平衡效率定義為每個節點服務的平均請求數與最熱節點服務的最大請求數之比。

結果如圖?8?所示。如圖所示,策略?3?實現了最好的負載平衡效率,而策略?2?的負載平衡效率最差。在很短的時間內,策略?2?充當了從使用策略?1?遷移到策略?3?的過程中的臨時設置。與策略?1?相比,策略?3?實現了更高的效率,并將每個節點上維護的成員信息的大小減少了三個數量級。雖然存儲不是主要問題,但是節點周期性地散布成員信息,因此希望盡可能緊湊地保存該信息。除此之外,由于以下原因,策略?3?是有利的,并且部署更簡單(1) 更快的引導/恢復由于分區范圍是固定的,它們可以存儲在單獨的文件中,這意味著可以通過簡單地傳輸文件來將分區作為一個單元重新定位避免定位特定項目所需的隨機訪問。這簡化了引導和恢復過程。(2) 易于存檔數據集的定期存檔是大多數亞馬遜存儲服務的強制性要求。在策略?3?中,歸檔由?Dynamo?存儲的整個數據集更簡單,因為分區文件可以單獨歸檔。相比之下,在策略?1?中,令牌是隨機選擇的,并且將存儲在?Dynamo 中的數據存檔需要分別從各個節點檢索密鑰,這通常是低效和緩慢的。策略?3?的缺點是改變節點成員需要協調,以保持分配所需的屬性。

?

?

6.3?分歧版本什么時候,有多少?

如前所述,Dynamo 旨在權衡一致性和可用性。為了了解不同故障對一致性的精確影響,需要多種因素的詳細數據停機時間、故障類型、組件可靠性、工作負載等。詳細介紹這些數字超出了本文的范圍。但是,本節討論了一個很好的總結指標在實際生產環境中應用程序所看到的不同版本的數量。

數據項的不同版本出現在兩種情況下。第一種是當系統面臨諸如節點故障、數據中心故障和網絡分區等故障情況時。第二種情況是,系統正在處理大量并發寫入單個數據項的操作,而多個節點最終會同時協調更新。從可用性和效率的角度來看,最好在任何給定的時間將不同版本的數量保持在盡可能低的水平。如果版本不能單獨基于向量時鐘進行語法協調,它們必須被傳遞給業務邏輯進行語義協調。語義協調會給服務帶來額外的負載,因此最好盡量減少對它的需求。

在我們的下一個實驗中,返回購物車服務的版本數量被分析了?24?小時。在此期間,99.94%的請求只看到一個版本;0.00057%?的請求看到?2?個版本;0.00047%?的請求看到了?3?個版本,0.00009%?的請求看到了?4?個版本。這說明發散版本很少被創造出來(This shows?that divergent versions are created rarely)

經驗表明,不同版本數量的增加不是由失敗造成的,而是由于并發編寫器數量的增加。并發寫入數量的增加通常是由忙碌的機器人自動化客戶端程序觸發的,很少是由人類觸發的。由于故事的敏感性,這個問題沒有詳細討論。

?

?

6.4?客戶端驅動或服務器驅動的協調

如第?5?節所述,Dynamo 有一個請求協調組件,它使用狀態機來處理傳入的請求。負載平衡器將客戶端請求統一分配給環中的節點。任何?Dynamo 節點都可以作為讀取請求的協調者。另一方面,寫請求將由鍵的當前首選項列表中的一個節點協調。這種限制是由于這些優選節點具有創建新版本標記的額外責任,該新版本標記必然包含由寫請求更新的版本。請注意,如果?Dynamo 的版本方案基于物理時間戳,任何節點都可以協調寫請求。

請求協調的另一種方法是將狀態機移動到客戶端節點。在這個方案中,客戶端應用程序使用一個庫在本地執行請求協調。客戶端定期選擇一個隨機的?Dynamo 節點,并下載其?Dynamo 成員狀態的當前視圖。使用這些信息,客戶端可以確定哪組節點構成了任何給定鍵的首選列表。讀取請求可以在客戶端節點處被協調,從而避免了額外的網絡跳躍,如果請求被負載均衡器分配給一個隨機的?Dynamo 節點,則會產生額外的網絡跳躍。如果?Dynamo?使用基于時間戳的版本控制,則寫操作要么轉發到鍵的首選項列表中的節點,要么可以在本地進行協調。

客戶端驅動的協調方法的一個重要優點是不再需要負載平衡器來統一分配客戶端負載。通過將密鑰近乎統一地分配給存儲節點,公平的負載分布得到了隱含的保證。顯然,這個方案的效率取決于客戶端的成員信息有多新。目前,客戶端每?10?秒鐘輪詢一個隨機的?Dynamo 節點以獲取成員更新。基于?pull?的方法比基于?push?的方法更受歡迎,因為前者可以更好地適應大量客戶端,并且需要在服務器上維護非常少的客戶端狀態。但是,在最壞的情況下,客戶端可能會暴露于過期成員身份達?10?秒鐘。在這種情況下,如果客戶端檢測到其成員資格表過時例如,當某些成員不可訪問時,它將立即刷新其成員資格信息。

?2?顯示了與服務器驅動的方法相比,使用客戶端驅動的協調在?24?小時內觀察到的99.9%?的延遲改善和平均值。如表中所示,對于?99.9%?的延遲,客戶端驅動的協調方法將延遲減少了至少?30?毫秒,并將平均值減少了?3??4?毫秒。延遲的改善是因為客戶端驅動的方法消除了負載平衡器的開銷和當請求被分配給隨機節點時可能產生的額外網絡跳。如表中所示,平均潛伏期往往明顯低于?99.9%?的潛伏期。這是因為?Dynamo 的存儲引擎緩存和寫緩沖區有很好的命中率。此外,由于負載平衡器和網絡會給響應時間帶來額外的可變性,因此?99.9%?的響應時間增益高于平均值。

?

?

6.5?平衡后臺和前臺任務

除了正常的前臺?put/get 操作之外,每個節點還執行不同種類的后臺任務,用于副本同步和數據切換由于提示或添加/移除節點。在早期的生產環境中,這些后臺任務觸發了資源爭用問題,并影響了常規?put??get?操作的性能。因此,有必要確保后臺任務僅在常規關鍵操作未受到顯著影響時運行。為此,后臺任務與準入控制機制相結合。每個后臺任務都使用這個控制器來保留資源例如數據庫的運行時間片,在所有后臺任務之間共享。基于前臺任務的監控性能的反饋機制被用來改變可用于后臺任務的切片的數量。

準入控制器在執行?"前臺"?put/get 操作時,不斷監視資源訪問的行為。受監控的方面包括磁盤操作的延遲、由于鎖爭用和事務超時導致的數據庫訪問失敗以及請求隊列等待時間。此信息用于檢查給定跟蹤時間窗口中延遲或失敗的百分比是否接近所需的閾值。例如,后臺控制器檢查第?99% 數據庫讀取延遲過去?60?秒內與預設閾值比如?50?毫秒的接近程度。控制器使用這種比較來評估前臺操作的資源可用性。隨后,它決定多少時間片可用于后臺任務,從而使用反饋循環來限制后臺活動的侵入性。

?

?

6.6?討論

本節總結了?Dynamo 在實施和維護過程中獲得的一些經驗。在過去的兩年里,亞馬遜的許多內部服務都使用了?Dynamo,并且為其應用程序提供了很高的可用性。特別是,應用程序?99.9995%?的請求都收到了成功的響應沒有超時,迄今為止沒有發生數據丟失事件。

此外,Dynamo 的主要優勢是它提供了必要的旋鈕,使用三個參數來根據他們的需要調整他們的實例與流行的商業數據存儲不同,Dynamo 向開發人員公開了數據一致性和協調邏輯問題。一開始,人們可能會認為應用程序邏輯會變得更加復雜。然而,從歷史上看,亞馬遜的平臺是為高可用性而構建的,許多應用程序都是為處理不同的故障模式和可能出現的不一致而設計的。因此,移植這樣的應用程序來使用?Dynamo 是一個相對簡單的任務。對于希望使用?Dynamo 的新應用程序,在開發的初始階段需要進行一些分析,以選擇合適的沖突解決機制來適當地滿足業務案例。最后,Dynamo 采用了完全成員模型,其中每個節點都知道其對等體托管的數據。為此,每個節點主動與系統中的其他節點共享完整的路由表。該模型適用于包含數百個節點的系統。然而,將這種設計擴展為運行數萬個節點并不容易,因為維護路由表的開銷會隨著系統大小的增加而增加。這個限制可以通過在?Dynamo 中引入分層擴展來克服。此外,請注意,這個問題由?O(1)?DHT系統主動解決。

?

?

7.?結論

本文描述了一個高度可用和可擴展的數據存儲庫?Dynamo,用于存儲亞馬遜電子商務平臺的一些核心服務的狀態。Dynamo 提供了所需的可用性和性能水平,并成功地處理了服務器故障、數據中心故障和網絡分區。Dynamo?具有增量可伸縮性,允許服務所有者根據其當前的請求負載進行上下伸縮。Dynamo 允許服務所有者通過調整參數?N、R??W?來定制他們的存儲系統,以滿足他們期望的性能、耐用性和一致性服務層協議

Dynamo 在過去一年的生產使用表明,去中心化技術可以結合起來提供一個單一的高可用性系統。它在最具挑戰性的應用程序環境中的成功表明,最終一致的存儲系統可以成為高可用性應用程序的構建模塊

超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生

總結

以上是生活随笔為你收集整理的Dynamo:亚马逊的高可用键值存储的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。