Jepsen:測試PostgreSQL、Redis、MongoDB以及Riak的分區容忍性

來源:互聯網
上載者:User

分布式系統的特性是能夠在高延遲或不可靠的傳輸條件下進行狀態交換。如果 要保證系統的操作的可靠性,必須保證在節點及網路兩方面故障發生時的健壯性 ,但並非所有系統都能夠滿足我們所要求的安全能力。在本文中,我們將探索分 布式資料庫在設計上的一些考慮,以及它們是如何對網路磁碟分割的情況作出響應。

在兩個節點間發送訊息時,IP網路可能會任意地刪除、延遲、重新排序或複製 訊息,因此許多分布式系統都使用TCP以防止訊息的重新排序與複製。但TCP/IP在 本質上仍然是非同步:網路會任意地延遲訊息,串連可能會被隨時切斷。此外, 對故障的診斷也並不可靠:要判斷某個節點是否出現故障、網路連接是否被切斷 、或者操作是否比預計中運行得慢也許是不可能實現的。

訊息被任意地延遲或切斷的這種故障叫做網路磁碟分割。分區可能出於多種原因發 生在生產環境的網路中:記憶體回收(GC)的壓力、網卡(NIC)故障、交換器故障 、配置出錯、網路擁塞等等。由於分區的發生,使CAP定理限制了分布式系統能夠 達到的最大擔保能力。當訊息被切斷時,“一致的”(CP)系統會拒 絕某些節點的請求,以保持線性一致性。“可用的”(AP)系統雖然 能夠處理所有節點上的請求,但必須犧牲線性一致性,因為不同的節點對於操作 的順序可能會產生不同意見。當網路情況良好時,系統可以保證一致性與可用性 ,但由於真實的網路中總會產生分區,因此不存在能夠完全做到“一致且可 用”(CA)的系統。

另外值得一提的是,CAP定理不僅僅對資料庫的整體有效,對其中的各種子系 統,例如表、鍵、列,甚至是各種操作也有效。舉例來說,資料庫可以為每個鍵 獨立地提供一致性,但不能保證鍵之間的一致性。建立這一折衷的策略可以允許 系統在分區發生時處理更多的請求數量。許多資料庫能夠調節單個讀寫操作的一 致性層級,其代價就是效能與正確性。

測試分區

理論界定了一個設計空間,但真實的軟體未必能夠達到這種範圍。我們需要測 試某個系統的表現,以真實地瞭解它的表現情況。

首先,我們需要準備一組節點以進行測試,我在一台Linux電腦上搭建了5個 LXC節點,但你也可以選擇使用Solaris zone、VM、EC2節點以及物理硬體等等。 你需要這些節點共用某種網路,在我的例子中使用了一個單獨的虛擬橋接器 (virtual bridge interface),我將這些節點命名為n1、n2、…n5,並 且在它們之間建立了DNS以及主機作業系統。

為了建立一個分區,你需要某種方式以切斷或延遲訊息,例如防火牆規則。在 Linux上,你可以使用iptables -A INPUT -s some-peer -j DROP命令以造成一種 單向的分區,使某些節點傳給當前節點的訊息會被切斷。當你在多台主機上應用 了這些規則之後,就建立了一個網路資料丟失的人為的模式。

在多台主機上重複地運行這些命令需要你花費一些精力,我使用了一個我自己 編寫的工具,名為Salticid。但你也可以使用CSSH或其它任意一種叢集自動化系 統。關鍵的因素是延遲——你需要能夠快速地啟動和終止某個分布, 因此像Chef或其它慢收斂系統可能沒有太大用途。

接下來你需要在這些節點上搭建分布式系統,並設計一個應用程式以進行測試 。我寫了一個簡單的測試:這是一個Clojure程式,它運行在叢集的外部,用多線 程類比五個隔離的用戶端。用戶端會並發地將N個整數加入到分布式系統中的某個 集合中,一個節點寫入0、5、10……,另一個節點寫入1、6、 11……等等。無論成功或失敗、每個用戶端都會將它的寫操作記錄 在日誌中。當所有寫操作都完成後,程式會等待叢集進行收斂,隨後檢查用戶端 的日誌是否與資料庫中的實際狀態相符。這是一種簡單的一致性檢查,但可以用 來測試多種不同的資料模型。

本樣本中的用戶端與配置自動化,包括類比分區與建立資料庫的指令碼都可以免 費下載。請單擊這裡以擷取代碼與說 明。

PostgreSQL

單節點的PostgreSQL執行個體是一個CP系統,它能夠為事務提供可串列的一致性, 其代價是當節點故障時便不可用。不過,這個分布式系統會選擇為伺服器進行妥 協,某個用戶端並不能保證一致性。

Postgres的提交協議是兩階段交易認可(2PC)的一個特例,在第一階段,用戶端 提交(或撤消)當前事務,並將該訊息發給伺服器。伺服器將檢查它的一致性約 束是否允許處理該事務,如果允許的話就處理該提交。它將該事務寫入儲存系統 之後,就會通知用戶端該提交已經處理完成了(或者在本例中也有可能失敗)。 現在用戶端與伺服器對該事務的執行結果意見一致。

而如果確認了該提交的訊息在到達用戶端之前就被切斷了,又會發生什麼情況 呢?此時用戶端就不知道該提交到底是成功了還是失敗了!2PC協議規定了節點必 須等待確認訊息到來,以判斷事務的結果。如果訊息沒有到達,2PC就不能正確地 完成。因此這不是一種分區容忍協議。真實的系統不可能無限制地等待,在某個 點上用戶端會產生逾時,這使得提交協議停留在一個中間狀態。

如果我人為造成這種分區的發生,JDBC Postgres用戶端就會拋出類似以下類 型的異常:

217 An I/O error occurred while sending to the backend.   Failure to execute query with SQL:   INSERT INTO "set_app" ("element") VALUES (?)  ::  [219]  PSQLException:  Message: An I/O error occured while sending to the backend.  SQLState: 08006   Error Code: 0  218 An I/O error occured while sending to the backend. 

我們或許會將其解讀為“寫操作217和218的事務失敗了”。但是當 測試應用去查詢資料庫,以尋找有哪些成功的寫操作事務時,它會發現這兩個 “失敗的”寫操作也出現在結果中:

1000 total950 acknowledged 952 survivors 2 unacknowledged writes found! ヽ(ー`)ノ (215 218) 0.95 ack rate 0.0 loss rate 0.002105263 unacknowledged but successful rate

在1000次寫操作中,有950次被成功地確認了,而且這950條寫記錄都出現在了 結果集中。但是,215與218這兩條寫操作也成功了,儘管它們拋出了異常!請注 意,這裡的異常並不確保這個寫操作是成功了還是失敗了:217號操作在發送時也 拋出了一個I/O錯誤,但因為用戶端的提交訊息在達到伺服器之前,串連就已經被 切斷,因此該事務沒有執行成功。

沒有任何方法能夠從用戶端可靠地區分這幾種情形。網路磁碟分割,或者說其實大 多數網路錯誤並不代表失敗,它只是意味著資訊的缺失。如果沒有一種分區容忍 的提交協議,例如擴充的3階段提交協議,是沒有辦法斷定這些寫操作的狀態的。

而如果將你的操作修改為等冪(idempotent)的,並且不斷地進行重試,就可 以處理這種不確定性。或者也可以將事務的ID作為事務的一部分,並在分區恢複 後去查詢該ID。

Redis

Redis是一個資料結構伺服器,它通常會部署在一個共用的堆之內。由於它運 行在一個單線程的伺服器內,因此它預設就提供了線性一致性,所有操作都會以 一個單一的、定義良好的順序進行執行。

Redis還提供了非同步式的主-從分發能力。某一台伺服器會被選為主節點,它能 夠接受寫操作,隨後將狀態的改變分發給各個從節點。在這一上下文中,非同步方 式意味著當主節點分發某個寫操作時,用戶端請求不會被阻塞,因為寫操作 “最終”會達到所有從節點。

為處理節點發現(discovery)、選擇主結點及容錯移轉等操作,Redis包含了 一個附加的系統:Redis哨兵(Sentinel)。哨兵節點會不斷交流它們訪問的各個 Redis伺服器的狀態,並且嘗試對節點進行升級與降級,以維持一個單一的權威主 節點。在這次測試中,我在所有5個節點上安裝了Redis和Redis哨兵。起初所有5 個用戶端都會從主節點n1以及從結點n2至n5上讀取資料,接下來我將n1與n2與其 它節點進行分區。

如果Redis是一個CP系統,那麼在分區發生時n1和n2就會變得不可用,而其它 重要組件(n3、n4、n5)中的某一個便會被選為主節點。但事實並非如此,實際 上寫操作依然會在n1上成功執行,幾秒鐘之後,哨兵節點會檢測到分區的發生, 並且將另一個節點(假設是n5)選為新的主節點。

在分區發生的這段時間,系統中存在著兩個主結點,系統的每個組件中各有一 個,並且兩者會獨立地接受寫操作。這是一種典型的腦分裂情境,並且違反了CP 中的C(一致性)。這種狀態下的寫(以及讀)操作不是可串列的,因為根據客戶 端所串連的節點的不同,它們所觀察到的資料庫狀態也不一樣。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.