HighLoad++,Mikhail Tyulenev (MongoDB):因果一致性:從理論到實踐

下一次 HighLoad++ 會議將於 6 年 7 月 2020 日至 XNUMX 日在聖彼得堡舉行。
詳情及門票 鏈接。 HighLoad++ 西伯利亞 2019。「克拉斯諾亞爾斯克」大廳。 25 月 12 日 00:XNUMX。 論文和 介紹.

HighLoad++,Mikhail Tyulenev (MongoDB):因果一致性:從理論到實踐

實際需求與理論有時會發生衝突,而對於商業產品來說重要的方面卻沒有被考慮到。 本演講介紹了一個基於商業產品要求的學術研究選擇和組合不同方法來創建因果一致性組件的過程。 聽眾將了解邏輯時鐘、依賴性追蹤、系統安全性、時鐘同步的現有理論方法,以及 MongoDB 選擇某些解決方案的原因。

米哈伊爾·秋列涅夫(以下簡稱MT): – 我將討論因果一致性 – 這是我們在 MongoDB 中開發的功能。 我在一個分散式系統小組工作,我們大約兩年前做的。

HighLoad++,Mikhail Tyulenev (MongoDB):因果一致性:從理論到實踐

在這個過程中,我必須熟悉很多學術研究,因為這個特性已經研究得相當好了。 事實證明,由於任何生產應用程式中都可能存在非常具體的要求,沒有一篇文章適合生產資料庫的要求。

我將討論我們作為學術研究的消費者如何從中準備一些東西,然後將其作為方便且安全使用的現成菜餚呈現給我們的用戶。

因果一致性。 讓我們定義一下概念

首先,我想籠統地說一下什麼是因果一致性。 有兩個角色-倫納德和潘妮(電視劇《生活大爆炸》):

HighLoad++,Mikhail Tyulenev (MongoDB):因果一致性:從理論到實踐

假設 Penny 在歐洲,Leonard 想為她舉辦一個驚喜派對。 他想不出還有什麼比把她從朋友名單中剔除、向所有朋友發送更新消息更好的了:“讓 Penny 開心吧!” (她在歐洲,當她睡覺的時候,她看不到這一切,也看不到,因為她不在那裡)。 最終,她刪除了這篇文章,將其從動態中刪除並恢復了存取權限,這樣她就不會注意到任何事情,也不會出現醜聞。
這一切都很好,但我們假設系統是分散式的,並且出現了一些問題。 例如,如果事件之間沒有因果關係,則 Penny 的存取限制可能是在該貼文出現後發生的。 實際上,這是需要因果一致性才能執行業務功能的範例(在本例中)。

事實上,這些都是資料庫的非常重要的屬性——很少有人支援它們。 讓我們繼續討論模型。

一致性模型

資料庫中的一致性模型到底是什麼? 這些是分散式系統對客戶端可以接收哪些資料以及以什麼順序接收的一些保證。

原則上,所有一致性模型都取決於分散式系統與在筆記型電腦的一個節點上運行的系統的相似程度。 這就是在數千個地理分散式「節點」上運行的系統與筆記型電腦的相似之處,其中所有這些屬性原則上都是自動執行的。

因此,一致性模型僅適用於分散式系統。 以前存在並以相同垂直尺度運行的所有系統都沒有遇到此類問題。 有一個緩衝區高速緩存,所有內容總是從其中讀取。

模型強

實際上,第一個模型是“強”(或通常所說的“上升能力線”)。 這是一個一致性模型,可確保每次變更一旦確認發生,對系統的所有使用者都是可見的。

這將建立資料庫中所有事件的全域順序。 這是一個非常強的一致性屬性,而且通常非常昂貴。 然而,它得到了很好的支持。 它只是非常昂貴且緩慢 - 只是很少使用。 這就是所謂的上升能力。

Spanner 支援另一個更強大的屬性 - 稱為外部一致性。 我們稍後再討論。

因果關係

下一個是因果關係,這正是我所說的。 強和因果之間還有幾個子級別,我不會談論,但它們都歸結為因果。 這是一個重要的模型,因為它是所有模型中最強的,在存在網路或分區的情況下具有最強的一致性。

因果其實是一種事件透過因果關係連結起來的情況。 他們常常被認為是從客戶的角度來理解您的權利。 如果客戶觀察到了一些數值,他就看不到過去的數值。 他已經開始看到前綴讀數了。 這一切都歸結為同一件事。
作為一致性模型的因果關係是伺服器上事件的部分排序,其中來自所有客​​戶端的事件以相同的順序觀察。 在這種情況下,倫納德和佩妮。

最終的

第三個模型是最終一致性。 這絕對是所有分散式系統都支援的,是有意義的最小模型。 這意味著:當我們對數據進行一些更改時,它們在某些時候會變得一致。

這種時候她什麼也不能說,否則她就會變成外在一致性──那將會是個完全不同的故事。 儘管如此,這是一個非常流行、最常見的模型。 預設情況下,分散式系統的所有使用者都使用最終一致性。

我想舉幾個對比的例子:

HighLoad++,Mikhail Tyulenev (MongoDB):因果一致性:從理論到實踐

這些箭頭是什麼意思?

  • 潛伏。 隨著一致性強度的增加,它會變得更大,原因很明顯:您需要進行更多記錄,從參與叢集的所有主機和節點獲得資料已經存在的確認。 因此,最終一致性有最快的答案,因為通常,您甚至可以將其保存到記憶體中,原則上這就足夠了。
  • 可用性。 如果我們將其理解為系統在出現網路中斷、分區或某種故障時做出回應的能力,那麼容錯能力會隨著一致性模型的降低而增加,因為對我們來說,一台主機同時存在就足夠了時間產生一些數據。 最終一致性根本不保證資料的任何內容——它可以是任何資料。
  • 異常現象。 當然,同時,異常的數量也在增加。 在強一致性中,它們幾乎根本不應該存在,但在最終一致性中,它們可以是任何東西。 問題出現了:如果最終一致性包含異常,為什麼人們會選擇它? 答案是最終一致性模型是適用的,並且異常存在,例如在短時間內; 可以使用嚮導讀取並且或多或少讀取一致的資料; 通常可以使用強一致性模型。 在實踐中,這是有效的,並且異常的數量通常在時間上是有限的。

CAP定理

當您看到一致性、可用性這些字詞時,您會想到什麼? 沒錯——CAP定理! 現在我想消除這個神話……不是我,而是馬丁·克萊普曼(Martin Kleppmann),他寫了一篇精彩的文章,一本精彩的書。

HighLoad++,Mikhail Tyulenev (MongoDB):因果一致性:從理論到實踐

CAP定理是2000年代訂定的原則,一致性、可用性、分區:任意取兩個,不能選三個。 這是一定的原則。 幾年後,吉爾伯特和林奇證明了它是一個定理。 然後這開始被用作口頭禪——系統開始分為CA、CP、AP等。

這個定理實際上在以下情況下被證明了......首先,可用性不被認為是從零到數百的連續值(0 - 系統“死機”,100 - 快速響應;我們習慣這樣考慮) ,但作為演算法的屬性,它保證其所有執行都會傳回資料。

根本沒有提到響應時間! 有一種演算法可以在 100 年後返回資料 - 一種絕對精彩的可用演算法,它是 CAP 定理的一部分。
第二:該定理針對同一鍵的值的變化而得到證明,儘管這些變化是可調整大小的。 這意味著實際上它們實際上沒有被使用,因為模型是不同的最終一致性、強一致性(也許)。

這一切是為了什麼? 此外,CAP 定理以其被證明的形式實際上不適用且很少使用。 從理論上來說,它在某種程度上限制了一切。 事實證明,某個原理直觀上是正確的,但總體上尚未得到證明。

因果一致性是最強的模型

現在發生的事情是,您可以使用分割區來獲得所有三件事:一致性、可用性。 特別是,因果一致性是最強的一致性模型,在存在分區(網路中斷)的情況下仍然有效。 這就是為什麼它如此令人感興趣,這就是為什麼我們接受它。

HighLoad++,Mikhail Tyulenev (MongoDB):因果一致性:從理論到實踐

首先,它簡化了應用程式開發人員的工作。 特別是,來自伺服器的大力支援:保證一個客戶端內發生的所有記錄都以相同的順序到達另一個客戶端。 其次,它能承受隔間。

MongoDB 內部廚房

想起今天是午餐,我們就去廚房。 我會告訴你係統模型,也就是對於那些第一次聽說這樣一個資料庫的人來說MongoDB是什麼。

HighLoad++,Mikhail Tyulenev (MongoDB):因果一致性:從理論到實踐

HighLoad++,Mikhail Tyulenev (MongoDB):因果一致性:從理論到實踐

MongoDB(以下簡稱「MongoDB」)是一個支援水平擴展,即分片的分散式系統; 並且在每個分片內還支援資料冗餘,即複製。

MongoDB(不是關聯式資料庫)中的分片執行自動平衡,即每個文件集合(或關聯式資料中的「表」)被分成多個片段,伺服器會自動在分片之間移動它們。

為客戶端分發請求的查詢路由器是其工作的某個客戶端。 它已經知道資料所在的位置和內容,並將所有請求定向到正確的分片。

另一個重要觀點:MongoDB 是單一主控。 有一個主資料庫 - 它可以獲取支援其包含的鍵的記錄。 您不能進行多主機寫入。

我們發布了 4.2 版本 - 那裡出現了新的有趣的東西。 特別是,他們將 Lucene - 搜索 - 即可執行 java 直接插入到 Mongo 中,這樣就可以透過 Lucene 執行搜索,就像在 Elastica 中一樣。

他們做了一個新產品-Charts,它也可以在Atlas(Mongo自己的雲端)上使用。 他們有一個免費套餐 - 您可以嘗試一下。 我真的很喜歡圖表——數據視覺化,非常直覺。

成分 因果一致性

我統計了大約 230 篇關於這個主題的文章——來自 Leslie Lampert。 現在我憑記憶將這些資料的部分內容轉達給大家。

HighLoad++,Mikhail Tyulenev (MongoDB):因果一致性:從理論到實踐

這一切都始於 Leslie Lampert 於 1970 世紀 XNUMX 年代撰寫的一篇文章。 如您所見,有關此主題的一些研究仍在進行中。 現在,因果一致性正在引起人們對分散式系統開發的興趣。

限制

有什麼限制? 這實際上是要點之一,因為生產系統施加的限制與學術文章中存在的限制非常不同。 它們通常是相當人為的。

HighLoad++,Mikhail Tyulenev (MongoDB):因果一致性:從理論到實踐

  • 首先,正如我已經說過的,「MongoDB」是一個單一的主機(這大大簡化了)。
  • 我們認為系統應該支援大約10個分片。 我們無法做出任何明確限制該值的架構決策。
  • 我們有云,但我們假設一個人仍然有機會下載二進位文件,在筆記型電腦上運行它,並且一切都運作良好。
  • 我們假設一些研究很少假設的事情:外部客戶可以為所欲為。 MongoDB 是開源的。 因此,客戶可能會變得如此聰明和憤怒——他們可能想破壞一切。 我們推測拜占庭費勒斯可能起源於拜占庭。
  • 對於邊界之外的外部用戶端,有一個重要的限制:如果停用此功能,則不應觀察到效能下降。
  • 另一點通常是反學術的:以前版本和未來版本的兼容性。 舊驅動程式必須支援新更新,且資料庫必須支援舊驅動程式。

一般來說,所有這些都會施加限制。

因果一致性成分

我現在將討論一些組件。 如果我們一般考慮因果一致性,我們可以選擇區塊。 我們從屬於某個區塊的作品中進行選擇:依賴跟踪,選擇時鐘,這些時鐘如何彼此同步,以及我們如何確保安全 - 這是我將要討論的內容的粗略概述:

HighLoad++,Mikhail Tyulenev (MongoDB):因果一致性:從理論到實踐

完整的依賴跟踪

為什麼需要它? 這樣,當複製資料時,每個記錄、每個資料變更都包含有關其所依賴的變更的資訊。 第一個也是幼稚的變化是,每個包含記錄的訊息都包含先前訊息的資訊:

HighLoad++,Mikhail Tyulenev (MongoDB):因果一致性:從理論到實踐

在此範例中,大括號中的數字是記錄編號。 有時甚至會整體轉移這些帶有值的記錄,有時會轉移一些版本。 最重要的是,每個更改都包含有關前一個更改的資訊(顯然其自身包含所有這些資訊)。

為什麼我們決定不使用這種方法(全面追蹤)? 顯然,因為這種方法是不切實際的:對社交網路的任何更改都取決於該社交網路之前的所有更改,例如在每次更新中傳輸 Facebook 或 VKontakte。 儘管如此,有許多關於完全依賴追蹤的研究——這些都是前社交網路;在某些情況下它確實有效。

顯式依賴跟踪

下一篇更有限。 這裡也考慮了資訊的傳輸,但僅限於明顯相關的資訊。 一般來說,什麼取決於什麼,由應用程式決定。 複製資料時,查詢僅在滿足先前的依賴關係(即顯示)時才回傳回應。 這就是因果一致性運作原理的本質。

HighLoad++,Mikhail Tyulenev (MongoDB):因果一致性:從理論到實踐

她看到記錄 5 依賴於記錄 1、2、3、4 - 因此,當所有先前的變更都已通過資料庫時,她會在客戶端有權存取 Penny 的存取決策所做的變更之前等待。

這也不適合我們,因為資訊仍然太多,而且會減慢速度。 還有另一種方法...

蘭波特時鐘

他們已經很老了。 Lamport Clock 的意思是將這些依賴關係折疊成一個標量函數,稱為 Lamport Clock。

標量函數是一些抽象數字。 它通常被稱為邏輯時間。 對於每個事件,該計數器都會增加。 進程目前已知的計數器發送每個訊息。 很明顯,進程可能不同步,它們可能有完全不同的時間。 儘管如此,系統還是以某種方式透過此類訊息傳遞來平衡時鐘。 在這種情況下會發生什麼?

我將這個大分片分成兩部分,以明確說明:朋友可以生活在一個節點中,其中包含該集合的一部分,而 Feed 可以生活在另一個節點中,其中包含該集合的一部分。 是否清楚他們如何能夠越軌? 第一個提要會說:“已複製”,然後是“朋友”。 如果系統不提供某種保證,在 Friends 集合中的 Friends 依賴項也被傳遞之前不會顯示 Feed,那麼我們就會遇到我提到的情況。

您將看到 Feed 上的計數器時間如何按邏輯增加:

HighLoad++,Mikhail Tyulenev (MongoDB):因果一致性:從理論到實踐

因此,Lamport Clock 和因果一致性(透過 Lamport Clock 進行解釋)的主要屬性是:如果我們有事件 A 和 B,且事件 B 依賴事件 A*,那麼事件 A 的 LogicalTime 小於事件 B 的邏輯時間。

* 有時他們也會說A發生在B之前,也就是A發生在B之前──這是一種對總體發生的整個事件集進行部分排序的某種關係。

反之則不正確。 這其實是 Lamport Clock 的主要缺點之一——偏序。 有一個關於同時事件的概念,即既沒有(A 發生在 B 之前)也沒有(A 發生在 B 之前)的事件。 一個例子是倫納德同時將其他人添加為朋友(甚至不是倫納德,而是謝爾頓)。
這是使用 Lamport 時鐘時經常使用的屬性:他們專門查看該函數,並由此得出結論,這些事件可能是相關的。 因為一種方式是正確的:如果 LogicalTime A 小於 LogicalTime B,則 B 不可能在 A 之前發生; 如果更多,那麼也許吧。

向量時鐘

Lamport 時鐘的邏輯發展是向量時鐘。 它們的不同之處在於,這裡的每個節點都包含自己單獨的時鐘,並且它們作為向量傳輸。
在本例中,您會看到向量的第 1 個索引負責 Feed,向量的第一個索引負責 Friends(每個節點)。 現在它們會增加:「Feed」的零索引在寫入時增加 - 2, 3, XNUMX:

HighLoad++,Mikhail Tyulenev (MongoDB):因果一致性:從理論到實踐

為什麼向量時鐘更好? 因為它們允許您找出哪些事件是同時發生的以及它們何時發生在不同的節點上。 這對 MongoDB 這樣的分片系統來說非常重要。 然而,我們沒有選擇這個,儘管它是一件很棒的事情,而且效果很好,而且可能會適合我們......

如果我們有 10 個分片,即使我們對其進行壓縮或提出其他方法,我們也無法傳輸 10 個組件 - 有效負載仍然比整個向量的體積小幾倍。 於是,我們咬緊牙關,放棄了這種做法,轉向了另一種做法。

扳手 TrueTime。 原子鐘

我說過會有一個關於斯潘納的故事。 這是一件很酷的事情,直接來自 XNUMX 世紀:原子鐘、GPS 同步。

有什麼想法嗎? 「Spanner」是 Google 的一個系統,最近甚至可供人們使用(他們向其中添加了 SQL)。 每筆交易都有一些時間戳記。 由於時間是同步的*,每個事件都可以被分配一個特定的時間 - 原子鐘有一個等待時間,之後保證會「發生」不同的時間。

HighLoad++,Mikhail Tyulenev (MongoDB):因果一致性:從理論到實踐

因此,只需寫入資料庫並等待一段時間,事件的可串行性就會自動得到保證。 他們擁有原則上可以想像的最強的一致性模型——它就是外部一致性。

* 這是 Lampart 時脈的主要問題 - 它們在分散式系統上永遠不會同步。 它們可能會出現分歧;即使使用 NTP,它們仍然不能很好地工作。 「Spanner」有一個原子鐘,同步似乎是微秒。

為什麼我們不選擇? 我們不假設我們的用戶有內建原子鐘。 當它們出現時,內置在每台筆記型電腦中,將會有某種超酷的GPS 同步- 那麼是的......但目前最好的可能是亞馬遜,基地台- 對於狂熱者... ……所以我們使用其他手錶。

混合時鐘

這其實是 MongoDB 在確保因果一致性時所採取的措施。 他們是如何混血的? 混合是一個標量值,但它有兩個組成部分:

HighLoad++,Mikhail Tyulenev (MongoDB):因果一致性:從理論到實踐

  • 第一個是 Unix 紀元(自「電腦世界開始」以來已經過了多少秒)。
  • 第二個是一些增量,也是一個 32 位元無符號整數。

事實上,僅此而已。 有這樣的做法:負責時間的部分始終與時鐘同步; 每次發生更新時,這部分都會與時鐘同步,結果表明時間總是或多或少正確,並且增量允許您區分在同一時間點發生的事件。

為什麼這對 MongoDB 很重要? 因為它可以讓你在某個時間點做某種備份餐廳,即事件按時間索引。 當需要某些事件時,這一點很重要; 對於資料庫來說,事件是資料庫中以特定時間間隔發生的變更。

我只告訴你最重要的原因(請不要告訴任何人)! 我們這樣做是因為這就是 MongoDB OpLog 中組織化、索引化的資料。 OpLog 是一種資料結構,絕對包含資料庫中的所有變更:它們首先進入 OpLog,然後在複製日期或分片的情況下套用到儲存本身。

這是主要原因。 儘管如此,開發資料庫也有實際要求,這意味著它應該很簡單——程式碼很少,需要重寫和測試的損壞的東西盡可能少。 我們的操作日誌由混合時鐘索引這一事實很有幫助,讓我們能夠做出正確的選擇。 它確實得到了回報,並且在第一個原型上神奇地發揮了作用。 太酷了!

時鐘同步

科學文獻中描述了多種同步方法。 當我們有兩個不同的分片時,我正在談論同步。 如果有副本集,則不需要任何同步:這是「單主」; 我們有一個 OpLog,所有更改都落入其中 - 在這種情況下,所有內容都已在“Oplog”本身中按順序排序。 但如果我們有兩個不同的分片,時間同步在這裡就很重要。 這就是向量時鐘發揮更大作用的地方! 但我們沒有。

HighLoad++,Mikhail Tyulenev (MongoDB):因果一致性:從理論到實踐

第二個是合適的——這是「心跳」。 可以交換每個單位時間發生的一些訊號。 但心跳太慢,我們無法向客戶端提供延遲。

當然,真正的時間是一件美妙的事。 但是,這可能是未來......雖然它已經可以在 Atlas 中完成,但已經有了快速的“Amazon”時間同步器。 但它不會提供給所有人。

八卦是指所有訊息都包含時間。 這大約是我們使用的。 節點之間的每個訊息、驅動程式、資料節點路由器,絕對 MongoDB 的所有內容都是某種元素,即包含運行時鐘的資料庫元件。 它們到處都有混合時間的意義,它被傳遞。 64位? 這允許,這是可能的。

這一切是如何協同工作的?

在這裡,我正在查看一個副本集,以使其更容易一些。 有小學和中學之分。 輔助節點進行複製,並不總是與主節點完全同步。

插入發生在「Primery」並具有一定的時間值。 如果這是最大值,則此插入會將內部計數增加 11。 或者它會檢查時鐘值,如果時鐘值更大,則同步到時鐘。 這使您可以按時間進行組織。

在他錄製完之後,一個重要的時刻發生了。 時鐘位於“MongoDB”中,並且僅在寫入“Oplog”時才會遞增。 這是改變系統狀態的事件。 在絕對所有經典文章中,事件被認為是當訊息到達節點時:訊息已到達,這意味著系統已更改其狀態。

這是因為在研究過程中並不完全清楚如何解釋該訊息。 我們確信,如果沒有反映在「Oplog」中,那麼它不會以任何方式被解釋,系統狀態的變化只是「Oplog」中的一個條目。 這為我們簡化了一切:模型簡化了它,並允許我們將其組織在一個副本集中,以及許多其他有用的東西。

傳回已寫入「Oplog」的值 - 我們知道「Oplog」已包含該值,其時間為 12。現在,假設從另一個節點(Secondary)開始讀取,並且在 ClusterTime 之後傳輸訊息。 他說:「我需要至少在 12 點之後或 XNUMX 點期間發生的所有事情」(見上圖)。

這就是所謂的因果一致性(CAT)。 理論上有這樣一個概念,這是某個時間片,它本身是一致的。 在這種情況下,我們可以說這是在時間 12 觀察到的系統狀態。

現在這裡還什麼都沒有,因為這種模擬的是當您需要輔助節點從主節點複製資料時的情況。 他等待……現在數據已經到達——他將這些值回傳。

HighLoad++,Mikhail Tyulenev (MongoDB):因果一致性:從理論到實踐

這幾乎就是一切的運作方式。 幾乎。

「幾乎」是什麼意思? 讓我們假設有人已經閱讀並理解了這一切是如何運作的。 我意識到每次 ClusterTime 發生時,它都會更新內部邏輯時鐘,然後下一個條目加一。 這個函數需要 20 行。 假設這個人傳輸最大的 64 位數減一。

為什麼要「減一」呢? 因為內部時鐘將被替換為這個值(顯然,這是最大可能的並且大於當前時間),那麼“Oplog”中將出現一個條目,並且時鐘將增加另一個單位 - 並且已經有是最大值(只有所有單位,沒有其他地方可去),非聖整數)。

很明顯,在此之後系統將變得絕對無法存取任何內容。 它只能卸載和清潔——大量的手工工作。 完全可用:

HighLoad++,Mikhail Tyulenev (MongoDB):因果一致性:從理論到實踐

此外,如果這被複製到其他地方,那麼整個叢集就會崩潰。 這是絕對不可接受的情況,任何人都可以非常快速、輕鬆地組織起來! 因此,我們認為這一刻是最重要的時刻之一。 如何預防呢?

我們的方式是對 clusterTime 進行簽名

這就是它在訊息中的傳輸方式(在藍色文字之前)。 但我們也開始產生簽名(藍色文字):

HighLoad++,Mikhail Tyulenev (MongoDB):因果一致性:從理論到實踐

簽名由儲存在安全範圍內的資料庫內的金鑰產生; 其本身已生成並更新(用戶看不到任何有關它的資訊)。 產生哈希值,每個訊息在創建時進行簽名,並在接收時進行驗證。
人們的腦海中可能會出現這樣的問題:“這會在多大程度上減慢速度?” 我告訴過你它應該很快就能工作,特別是在沒有這個功能的情況下。

在這種情況下使用因果一致性意味著什麼? 這是為了顯示 afterClusterTime 參數。 如果沒有這個,它無論如何都會簡單地傳遞值。 從 3.6 版本開始,閒聊總是有效的。

如果我們不斷產生簽名,即使沒有某個功能,也會減慢系統速度,這不符合我們的方法和要求。 那我們做了什麼?

快點做吧!

這是一個相當簡單的事情,但其中的技巧很有趣——我會分享它,也許有人會感興趣。
我們有一個儲存簽名資料的哈希值。 所有資料都會經過快取。 快取不標註具體時間,而是標註Range。 當某個值到達時,我們產生一個 Range,屏蔽掉最後 16 位,然後對該值進行簽署:

HighLoad++,Mikhail Tyulenev (MongoDB):因果一致性:從理論到實踐

透過接收這樣的簽名,我們將系統速度(相對)提高了 65 倍。 它效果很好:當我們進行實驗時,當我們進行順序更新時,時間實際上減少了​​一萬倍。 很明顯,當他們意見不合時宜時,這是行不通的。 但在大多數實際情況下它是有效的。 Range簽名與簽名的結合解決了安全問題。

我們學到了什麼?

我們從中學到的教訓:

  • 我們需要閱讀材料、故事、文章,因為我們有很多有趣的東西。 當我們研究某些功能時(尤其是現在,當我們進行交易等時),我們需要閱讀和理解。 這需要時間,但它實際上非常有用,因為它讓我們清楚地知道我們在哪裡。 我們似乎沒有想出任何新東西——我們只是採用了原料。

    一般來說,學術會議(例如Sigmon)的思維會有一定的差異──每個人都專注於新的想法。 我們的演算法有什麼新內容? 這裡沒有什麼特別新的東西。 新穎之處在於我們將現有方法融合在一起的方式。 所以,首先要讀經典,從蘭帕特開始。

  • 在生產中,要求完全不同。 我確信你們中的許多人面對的並不是抽象真空中的「球形」資料庫,而是正常的、真實的存在可用性、延遲和容錯性問題的資料庫。
  • 最後一件事是,我們必須考慮不同的想法,並將幾篇完全不同的文章組合成一種方法。 例如,關於簽名的想法通常來自一篇考慮Paxos 協議的文章,對於非拜占庭失敗者來說,它位於授權協議之內,對於拜占庭失敗者來說,它位於授權協議之外……總的來說,這正是我們所希望的。最終做了。

    這裡絕對沒有什麼新鮮事! 但一旦我們把它們混合在一起……就等於說奧利維爾沙拉食譜是無稽之談,因為雞蛋、蛋黃醬和黃瓜已經被發明了……這是同一個故事。

HighLoad++,Mikhail Tyulenev (MongoDB):因果一致性:從理論到實踐

我就講完這個。 謝謝你!

問題

觀眾提問(以下簡稱B): – 謝謝米哈伊爾的報告! 關於時間的話題很有趣。 您正在使用閒聊。 他們說每個人都有自己的時間,每個人都知道自己當地時間。 據我了解,我們有一個驅動程式- 可能有很多帶有驅動程式的客戶端,也有查詢規劃器,也有分片......如果我們突然出現差異,系統會歸結為什麼呢:有人決定它是為了領先一分鐘,有人落後一分鐘? 我們最終會去哪裡?

公噸: – 確實是個好問題! 我只是想談談碎片。 如果我正確理解這個問題,我們會遇到以下情況:有分片 1 和分片 2,讀取發生在這兩個分片上 - 它們有差異,它們彼此不交互,因為它們知道的時間不同,尤其是它們存在於oplog 的時間。
假設分片 1 建立了 2 萬筆記錄,分片 2 完全沒有執行任何操作,並且請求到達了兩個分片。 第一個的 afterClusterTime 超過一百萬。 在這種情況下,正如我所解釋的,分片 XNUMX 根本不會回應。

在: – 我想知道他們如何同步並選擇一個邏輯時間?

公噸: - 非常容易同步。 分片,當 afterClusterTime 到來時,他在“Oplog”中找不到時間,則不會發起批准。 也就是說,他用手將自己的時間提高到這個價值。 這意味著它沒有與此請求相符的事件。 他人為地創造了這個事件,從而變得因果一致。

在: – 如果此後他又遇到一些其他事件,而這些事件在網路中的某個地方遺失了怎麼辦?

公噸: – 碎片的設計方式是它們不會再來,因為它是單一的主設備。 如果他已經報名了,那麼他們就不會來,而是稍後會來。 不可能發生某些事情卡在某個地方,然後他不寫,然後這些事件到達 - 並且因果一致性被打破。 當他不寫時,他們都應該下一個(他會等待他們)。

HighLoad++,Mikhail Tyulenev (MongoDB):因果一致性:從理論到實踐

在: – 我有幾個關於隊列的問題。 因果一致性假設存在需要執行的特定操作隊列。 如果我們的其中一個包裹消失了怎麼辦? 10號、11號來了……12號已經消失了,其他人都在等待它的實現。 我們的車突然壞了,我們無能為力。 在執行之前累積的佇列是否有最大長度? 當任何一種狀態遺失時會發生什麼致命故障? 而且,如果我們寫下有一些先前的狀態,那麼我們應該以某種方式從它開始嗎? 但他們並沒有把他推開!

公噸: –也是一個很好的問題! 我們在做什麼? MongoDB 有仲裁寫入、仲裁讀取的概念。 什麼情況下訊息會遺失? 當寫入不是法定人數或讀取不是法定人數時(某種垃圾也可能會黏住)。
關於因果一致性,進行了大規模的實驗測試,結果是在寫入和讀取非法定人數的情況下,會發生違反因果一致性的情況。 正是你所說的!

我們的建議:在使用因果一致性時至少使用法定人數閱讀。 在這種情況下,即使仲裁記錄遺失,也不會遺失任何內容…這是一個正交情況:如果使用者不希望資料遺失,則需要使用仲裁記錄。 因果一致性並不能保證持久性。 持久性由複製和與複製相關的機制來保證。

在: – 當我們建立一個為我們執行分片的實例(分別不是master,而是slave)時,它依賴於自己機器的Unix時間或「master」的時間; 是第一次同步還是定期同步?

公噸: – 我現在就澄清一下。 分片(即水平分區)-總有一個主分片。 一個分片可以有一個“主分片”,也可以有多個副本。 但分片始終支援記錄,因為它必須支援某個域(分片有 Primary)。

在: ——所以一切完全取決於「主人」? 是否總是使用主時間?

公噸: - 是的。 你可以形像地說:當進入「master」、進入「Oplog」時,時鐘正在滴答作響。

在: – 我們有一個連線的客戶端不需要知道任何時間?

公噸: – 你根本不需要知道任何事! 如果我們談論它在客戶端是如何運作的:當客戶端想要使用因果一致性時,他需要開啟一個會話。 現在一切都已就緒:會話中的交易、檢索權限…會話是客戶端發生的邏輯事件的順序。

如果他打開此會話並在那裡說他想要因果一致性(如果會話默認支援因果一致性),則一切都會自動進行。 驅動程式會記住這個時間,並在收到新訊息時增加它。 它會記住前一個從返回資料的伺服器傳回的回應。 下一個請求將包含 afterCluster(“時間大於此”)。

客戶不需要知道任何事! 這對他來說是完全不透明的。 如果人們使用這些功能,他們可以做些什麼? 首先,您可以安全地讀取輔助節點:您可以寫入主節點並從地理複製的輔助節點中讀取數據,並確保其正常運作。 同時,在主伺服器上記錄的會話甚至可以轉移到輔助伺服器,也就是您可以使用多個會話,而不是一個會話。

在: – 計算科學的新層 – CRDT(無衝突複製資料類型)資料類型 – 與最終一致性主題密切相關。 您是否考慮過將這些類型的資料整合到資料庫中?您對此有何評論?

公噸: - 好問題! CRDT 對於寫入衝突是有意義的:在 MongoDB 中,單主。

在: – 我有一個來自開發人員的問題。 在現實世界中,當拜占庭失敗發生時,會出現這樣的耶穌會情況,受保護範圍內的邪惡人士開始刺探協議,以特殊方式發送工藝包?

HighLoad++,Mikhail Tyulenev (MongoDB):因果一致性:從理論到實踐

公噸: – 外圍的惡人就像特洛伊木馬! 外圍的壞人可以做很多壞事。

在: – 很明顯,粗略地說,在服務器上留下一個洞,你可以通過它放置大象動物園並永遠崩潰整個集群......手動恢復需要時間......這,溫和地說,是錯誤的。 另一方面,這很有趣:在現實生活中,在實踐中,是否存在自然發生類似內部攻擊的情況?

公噸: – 由於我在現實生活中很少遇到安全漏洞,所以我不能說它們是否確實發生。 但如果我們談論開發理念,我們會這樣想:我們有一個邊界,可以為負責安全的人員提供服務——這是一座城堡,一堵牆; 在邊界內你可以做任何你想做的事。 很明顯,有些使用者只能查看目錄,有些使用者只能刪除目錄。

根據權利的不同,使用者造成的損害可能是一隻老鼠,也可能是一頭大象。 顯然,擁有完全權限的用戶可以做任何事情。 權限有限的使用者造成的傷害會小得多。 特別是它不能破壞系統。

在: – 在受保護的範圍內,有人試圖為伺服器創建意想不到的協議,以徹底摧毀伺服器,如果幸運的話,整個叢集......它有那麼「好」嗎?

公噸: “我從來沒有聽說過這樣的事情。” 透過這種方式可以使伺服器崩潰這一事實已不是什麼秘密。 內部失敗,來自協議,作為授權用戶可以在訊息中寫這樣的內容......事實上,這是不可能的,因為它仍然會被驗證。 可以為不需要的用戶停用此身份驗證 - 那麼這就是他們的問題; 粗略地說,他們自己破壞了牆壁,你可以把大象推進去,大象會踐踏……但總的來說,你可以裝扮成修理工,來把它拉出來!

在: – 感謝您的報告。 謝爾蓋(Yandex)。 Mong中有一個常數限制了副本集中投票成員的數量,這個常數是7(七)。 為什麼這是一個常數? 為什麼這不是某種參數?

公噸: – 我們有 40 個節點的副本集。 總是有多數的。 不知道哪個版本...

在: – 在Replica Set中,你可以運行無投票權的成員,但是最多有7個投票權的成員。如果我們的Replica Set分佈在3個資料中心,那麼在這種情況下,我們如何才能在關閉時倖存下來? 一個資料中心很容易關閉,而另一台機器可能會掉下來。

公噸: – 這已經有點超出了報告的範圍。 這是一個一般性問題。 也許我可以稍後再告訴你。

HighLoad++,Mikhail Tyulenev (MongoDB):因果一致性:從理論到實踐

一些廣告🙂

感謝您與我們在一起。 你喜歡我們的文章嗎? 想看更多有趣的內容? 通過下訂單或推薦給朋友來支持我們, 面向開發人員的雲 VPS,4.99 美元起, 我們為您發明的入門級服務器的獨特模擬: VPS (KVM) E5-2697 v3(6 核)10​​4GB DDR480 1GB SSD 19Gbps XNUMX 美元或如何共享服務器的全部真相? (適用於 RAID1 和 RAID10,最多 24 個內核和最多 40GB DDR4)。

Dell R730xd 在阿姆斯特丹的 Equinix Tier IV 數據中心便宜 2 倍? 只有這裡 2 x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 電視低至 199 美元 在荷蘭! Dell R420 - 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB - 99 美元起! 閱讀 如何建設基礎設施公司同級使用價值730歐元的Dell R5xd E2650-4 v9000服務器一分錢?

來源: www.habr.com

添加評論