Facebook如何使用ZippyDB構建通用鍵值存儲?

{"type":"doc","content":[{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"ZippyDB 是 Facebook 最大的強一致性、地理分佈的鍵值存儲。自從我們在 2013 年首次部署 ZippyDB 以來,這個鍵值存儲的規模迅速擴大,如今,ZippyDB 爲許多用例服務,包括分佈式文件系統的元數據、爲內部和外部目的計算事件,以及用於各種應用功能的產品數據。ZippyDB 在可調整的持久性、一致性、可用性和延遲保證方面爲應用程序提供了極大的靈活性,這使得它在 Facebook 內部成爲存儲短暫和非短暫的小型鍵值數據的首選。在本文中,我們將首次分享 ZippyDB 的歷史和開發,以及在構建這項服務時做出的一些獨特的設計選擇和權衡,這項服務解決了 Facebook 的大多數鍵值存儲場景。"}]}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"ZippyDB 的歷史"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"ZippyDB 使用 "},{"type":"link","attrs":{"href":"https:\/\/www.facebook.com\/notes\/facebook-engineering\/under-the-hood-building-and-open-sourcing-rocksdb\/10151822347683920\/","title":null,"type":null},"content":[{"type":"text","text":"RocksDB"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" 作爲底層存儲引擎。在 ZippyDB 之前,Facebook 的各個團隊直接使用 RocksDB 來管理他們的數據。但是,這產生了很多重複工作,每個團隊都要解決類似的挑戰,例如一致性、容錯、故障恢復、複製和容量管理。爲滿足這些不同團隊的需求,我們構建了 ZippyDB,以提供一個高度持久和一致的鍵值數據存儲,通過將所有數據和與大規模管理這些數據相關的挑戰轉移到 ZippyDB,使得產品的開發速度大大加快。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"我們早期在開發 ZippyDB 時作出的一個重要設計決策是,儘可能地重用現有的基礎設施。所以,我們最初的工作重點是建立一個可重用、靈活的數據複製庫,即 Data Shuttle。將 Data Shuttle 與已有的、成熟的存儲引擎(RocksDB)結合起來,在我們現有的分片管理("},{"type":"link","attrs":{"href":"https:\/\/engineering.fb.com\/2020\/08\/24\/production-engineering\/scaling-services-with-shard-manager\/","title":null,"type":null},"content":[{"type":"text","text":"Shard Manager"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":")和分佈式配置服務(基於 "},{"type":"link","attrs":{"href":"https:\/\/zookeeper.apache.org\/","title":null,"type":null},"content":[{"type":"text","text":"ZooKeeper"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":")的基礎上建立了一個完全管理的分佈式鍵值存儲,共同解決了負載平衡、分片放置、故障檢測和服務發現等問題。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"架構"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/ea\/6d\/ea01f60d430bc0e34c93720de0a4d26d.jpg","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"ZippyDB 被部署在所謂層的單元中。一個層由分佈在全球多個地理區域的計算和存儲資源組成,這使得它在故障恢復方面具有彈性。當前只有少數 ZippyDB 層,其中包括默認的“通配符”層和用於分佈式文件系統元數據和 Facebook 內部其他產品組的專用層。每個層都承載着多個用例。一般來說,用例是在通配符層中創建的,該層是通用多租戶層。這是首選的層,因爲它可以更好地利用硬件,並減少操作開銷,但有時我們也會在需要時提議使用專用層,這通常是由於更嚴格的隔離要求。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"屬於某一層上的用例的數據被分割成所謂的分片(shard)單元,這是服務器端數據管理的基本單元。每個分片都是通過使用 Data Shuttle 在多個區域進行復制(用於容錯),它使用 "},{"type":"link","attrs":{"href":"https:\/\/dl.acm.org\/doi\/10.1145\/279227.279229","title":null,"type":null},"content":[{"type":"text","text":"Paxos"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" 或異步複製來複制數據,這取決於配置。在一個分片內,一個複製子集被配置爲 Paxos 仲裁組的一部分,也被稱爲全局範圍,其中數據使用 Multi-Paxos 進行同步複製,以便在故障出現時提供高耐久性和可用性。其餘的副本,如果有的話,將作爲跟隨者配置。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"在 Paxos 術語中,這些副本與接收異步數據的學習者類似。跟隨者允許應用程序在多個區域內複製,以支持低延遲的讀取和寬鬆的一致性,同時保持較小的仲裁組以降低寫操作延遲。分片內複製角色配置的這種靈活性允許應用程序能夠在持久性、寫操作性能和讀操作性能之間取得平衡,這取決於它們的需求。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"除了同步或異步複製策略外,應用程序還可以選擇向服務提供“提示”,指出在哪些區域必須放置分片副本。這些提示,也被稱爲“粘性約束”,允許應用程序對讀寫的延遲有一定程度的控制,即在它們期望訪問的大部分區域建立副本。ZippyDB 還提供了一個緩存層,並與一個允許訂閱分片上的數據突變的 pub-sub 系統集成,這兩者都可以根據用例的需求選擇加入。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"數據模型"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"ZippyDB 支持一個簡單的鍵值數據模型,它的 API 可以獲取、放置和刪除鍵以及它們的批處理變體。它支持遍歷鍵的前綴和刪除鍵的範圍。這種 API 非常類似於底層 RocksDB 存儲引擎所提供的 API。另外,我們還支持對基本的讀-改-寫操作和事務進行測試和設置的 API,對更通用的讀-改-寫操作進行條件寫操作(後面將詳細介紹)。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"事實證明,這個最小的 API 集足以滿足大多數用例在 ZippyDB 上管理它們的數據。對於短暫的數據,ZippyDB 有原生的 TTL 支持,允許客戶端在寫操作時指定對象的到期時間。通過對 RocksDB 的定期壓實支持,我們可以有效地清除所有過期的鍵,同時在壓實操作過程中過濾掉讀取端的死鍵。在 ZippyDB 上,很多應用程序實際上是通過 ORM 層來訪問 ZippyDB 上的數據,該層將這些訪問轉換爲 ZippyDB 的 API。在其他方面,這個層的作用是抽象出底層存儲服務的細節。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/13\/e2\/1362bf502c4c2e8ebb8bda9e5b08c9e2.jpg","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"分片是服務器端的數據管理單元。分片到服務器的最佳分配需要考慮到負載、故障域、用戶限制等因素,這由 ShardManager 處理。ShardManager 負責監控服務器的負載失衡、故障,並啓動服務器之間的分片移動。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"分片,通常被稱爲物理分片(physical shard,p-shard),是一種服務器端的概念,不會直接嚮應用程序公開。取而代之的是,我們允許用例將它們的鍵空間劃分爲更小的相關數據單元,稱爲微分片(μshard)。一個典型的物理分片的大小爲 50~100GB,承載着幾萬個微分片。這個額外的抽象層允許 ZippyDB 透明地充分分區數據,而無需更改客戶端。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"ZippyDB 支持兩種從微分片到物理分片的映射:緊湊型映射和 Akkio 映射。緊湊型映射是在一個相當靜態的分配,並且只有在分割過大或者過熱的分片時纔會更改映射。在實踐中,與 Akkio 映射相比,這是一種非常少見的操作,在 "},{"type":"link","attrs":{"href":"https:\/\/engineering.fb.com\/2018\/10\/08\/core-data\/akkio\/","title":null,"type":null},"content":[{"type":"text","text":"Akkio"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" 映射中,微分片的映射由名爲 Akkio 的服務管理。Akkio 將用例的鍵空間分割成微分片,並將這些微分片放置在信息通常被訪問的區域。Akkio 有助於減少數據集的重複,併爲低延遲訪問提供一個明顯比在每個區域放置數據更有效的解決方案。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/27\/c9\/27859e71193457bf243f1e99804ce6c9.jpg","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"如前所述,Data Shuttle 使用 Multi-Paxos 將數據同步複製到全局範圍內的所有副本。從概念上講,時間被細分成一個單位,稱爲輪數(epoch)。每個輪數都有一個唯一的領導者,它的角色是通過名爲 ShardManager 的外部分片管理服務分配的。一旦領導者被分配,它在整個輪數的持續時間內都有一個租約。週期性的心跳用於保持租約的活躍性,直到 ShardManager 將分片上的輪數調高(例如,用於故障轉移、主負載平衡等)。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"當故障發生時,ShardManager 會檢測到故障,分配一個具有更高的輪數的新領導者,並恢復寫操作可用性。在每個輪數內,領導者通過給每個寫操作分配一個單調增加的序列號,生成對分片的所有寫操作的總排序。然後,通過使用 Multi-Paxos 將這些寫操作寫入到一個複製的持久日誌中,以實現對排序的共識。一旦寫入達成共識,它們就會在所有副本中按順序排出。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"爲了在最初的實施中簡化服務設計,我們選擇了使用外部服務來檢測故障並分配領導者。但是,在將來,我們計劃完全在 Data Shuttle 內部檢測故障(“帶內”),並且更加主動地重新選擇領導者,而不必等待 ShardManager 併產生延遲。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"一致性"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"ZippyDB 爲應用程序提供了可配置的一致性和持久性級別,可以在讀寫 API 中指定爲選項。這樣,應用程序就可以在每個請求級別上動態地權衡持久性、一致性和性能。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"在大多數副本的 Paxos 日誌中,默認情況下寫操作包括持久化數據,並且在確認向客戶端之前向主服務器的 RocksDB 寫入數據。在默認的寫操作模式下,在主服務器上的讀操作將總是看到最近的寫入。一些應用程序不能容忍每次寫的跨區域延遲,因此 ZippyDB 支持快速確認模式,即寫操作一旦在主服務器上被排隊複製就被確認。這種模式的持久性和一致性保證顯然較低,這是對更高的性能的折衷。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"在讀操作方面,最流行的三個一致性級別是最終一致性、讀寫一致性(Read-your-writes Consistency)和強一致性。ZippyDB 所支持的最終一致性級別,實際上比更著名的最終一致性的級別要強得多。ZippyDB 爲分片內的所有寫操作提供總排序,並確保讀操作不會由落後於主\/仲裁超過某個可配置閾值的副本提供(心跳用於檢測延遲),因此由 ZippyDB 支持的最終讀操作更加接近文獻中的有界過時一致性。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"對於讀寫操作,客戶端緩存服務器返回的最新序列號用於寫操作,並在讀取時使用該版本來運行或稍後的查詢。版本的緩存是在同一個客戶進程中。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"ZippyDB 還提供了強一致性或"},{"type":"link","attrs":{"href":"https:\/\/dl.acm.org\/doi\/10.1145\/78969.78972","title":null,"type":null},"content":[{"type":"text","text":"線性化能力"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":",無論這些寫操作或讀操作來自何處,客戶端都可以看得到最近的寫操作的效果。目前強讀操作是通過將讀操作路由到主服務器來實現的,以避免需要進行仲裁對話,這主要是出於性能方面的考慮。主服務器依靠擁有租約,以確保在提供讀操作之前沒有其他主服務器。在某些例外情況下,如果主服務器沒有聽說過租約續期,那麼主服務器的強讀操作就會變成一個仲裁檢查和讀操作。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"事務與條件寫操作"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/67\/e9\/674862bc47e1e3b90b26ce4c8a5435e9.jpg","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"ZippyDB 支持事務和條件寫操作,以滿足需要對一組鍵進行原子式讀-改-寫操作的用例。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"在分片上,所有事務默認爲可序列化,我們不支持更低的隔離級別。這樣可以簡化服務器端實現和客戶端併發執行事務的正確性推理。事務使用樂觀的併發控制來檢測和"},{"type":"link","attrs":{"href":"https:\/\/dl.acm.org\/doi\/10.1145\/568271.223787","title":null,"type":null},"content":[{"type":"text","text":"解決衝突"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":",其作用如上圖所示。一般情況下,客戶端讀取二級數據庫的快照中所有的數據,組成一個寫操作集,然後把讀寫操作集全部發送到一級數據庫提交。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"當接收到一個讀寫操作集,並接受了讀操作的快照之後,主服務器檢查是否對其他正在執行的事務執行了衝突的寫操作。當沒有衝突時,才能接受事務;然後,如果服務器不發生故障,則確保事務成功。主服務器上的衝突解決取決於跟蹤之前被接受的事務在主服務器上同一輪數內執行的所有最新寫操作。跨輪數的事務將被拒絕,因爲這簡化了寫操作集跟蹤,而不需要複製。在主服務器上維護的寫操作歷史也會被定期清除,以保持低空間使用率。因爲不會維護完整的歷史記錄,主服務器需要維護一個最低跟蹤版本,並拒絕所有針對較低版本的快照進行讀操作的事務,以保證可序列化。只讀操作事務的工作方式完全類似於讀寫操作事務,除了寫操作集爲空。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"通過“服務端事務”實現條件寫操作。它提供了一個更加友好的客戶端 API,用於客戶端希望根據一些常見的前提條件(例如 "},{"type":"codeinline","content":[{"type":"text","text":"key_present"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"、"},{"type":"codeinline","content":[{"type":"text","text":"key_not_present"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" 和"},{"type":"codeinline","content":[{"type":"text","text":"value_matches_or_key_not_present"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":")原子化地修改一組鍵的情況。如果主服務器收到有條件的寫請求,它會建立事務上下文,並將前提條件和寫操作集轉換爲服務器上的一個事務,重複使用所有的事務機制。在客戶端可以計算前提條件而不需要讀操作的情況下,條件寫操作 API 可能比事務 API 更有效。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"ZippyDB 的未來"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"分佈式鍵值存儲有很多應用,在構建各種系統時,從產品到爲各種基礎設施服務存儲元數據,經常會出現對分佈式鍵值存儲的需求。構建可擴展的、強一致性的、容錯的鍵值存儲是一項挑戰,往往需要通過許多權衡思考,以提供規劃好的系統功能和保證的組合,從而在實踐中有效地處理各種工作負載。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"本文介紹了 Facebook 最大的鍵值存儲 ZippyDB,它已經生產了六年多,爲很多不同的工作負載服務。該服務自從推出以來得到了很高的採用率,主要是因爲它在效率、可用性和性能權衡方面具有靈活性。該服務也使我們能夠作爲一家公司高效地使用工程資源,並作爲一個單一的池有效地利用我們的鍵值存儲容量。ZippyDB 仍在不斷髮展,目前正在經歷重大的架構變化,比如存儲-計算分解、成員管理的根本變化、故障檢測和恢復以及分佈式交易,以適應不斷變化的生態系統和產品要求。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}},{"type":"strong"}],"text":"作者介紹:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"Sarang Masti,Facebook 軟件工程師。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}},{"type":"strong"}],"text":"原文鏈接:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"https:\/\/engineering.fb.com\/2021\/08\/06\/core-data\/zippydb\/"}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章