1. 程式人生 > >Nosql 理解篇+實戰篇 五 NoSQL一致性解決方案

Nosql 理解篇+實戰篇 五 NoSQL一致性解決方案

 五 NoSQL一致性解決方案

                   更新一致性,讀取一致性,放寬一致性約束,放寬永續性約束,CAP定理,仲裁

    先來一個案例

Tom和jarry在同一家公司上班,有一天,他們發現公司網頁顯示的電話有誤,於是進入後臺系統同時修改電話。我們假定他們輸入的電話號碼格式稍有差別,那麼,他們提交的新號碼就會略有不同,此時將產生“寫衝突”問題:兩人在同一時刻更新同一條資料。

         1 更新一致性。

在併發環境下維護資料一致性是一件麻煩事。通常,我們將其分為“悲觀方式”和“樂

         觀方式”。

悲觀方式:避免在更新時發生衝突,採取“寫入鎖”,這樣,在某個值修改之前,必

須先獲得“寫入鎖”,系統確保某一時刻只有一個客戶能夠獲得這把鎖。如果tom和jarry想同時獲得者“寫入鎖”,那麼只有Jarry(若伺服器按照首字母順序執行序列)能獲取該鎖,而tom看了jarry修改後的資料,再來決定是否繼續更新它。

樂觀方式:在任意客戶執行操作前,都要先測試資料的當前值和其上一次讀入的值

是否相同。在這種情況下,Jarry的更新能夠成功執行,而tom的將操作失敗。Tom得知失敗後,他可以再次查詢該資料,以決定是否要繼續修改。

         當然,上面所說的這兩種模式都有一個先決條件,那就是更新操作的順序必須一致。在單伺服器環境中,這顯然成立,它必須完成一個操作,才能處理下一個。然而,當伺服器數量不止一個(對等複製),那麼兩個節點就可能按照不同的次序更新操作,這樣照成的結果是,每個節點最終儲存的電話號碼不一致。

所以,樂觀方式2:將兩份更新資料都儲存起來,並標出它們存在衝突。更svn或者git相同,在處理衝突時,該方式遵循與版本控制系統相同的步驟。必須以某種方式將兩個衝突的更新操作“合併”提交。        

         2 讀取一致性

                  在傳統的關係型資料庫中,我們常常採用事務來保證資料庫操作的唯一性。

         有種常見的說法是”NoSQL“資料庫不支援事務。事實上,對不同的NoSQL來說,其對事務支援能力並不一樣。例如圖資料庫一樣支援ACID事務

         面向聚合的資料庫通常支援”原子跟新“,但僅限於單一聚合內部。

         結合之前所說的”主從式分佈模型“和”對等式分佈模型“在任意時刻中,節點中都可能存在”複製不一致“,然而只要不再繼續執行其他更新操作,那麼上一次更新操作的結果最終將會分佈到全部節點中去。過期的資料通常成為”陳舊“資料。

         對於讀取一致性的問題,我們通常用”會話一致性“來解決。會話一致性通常有兩種實現方式,其一為:”黏性會話“,也就是繫結到某個節點的會話,只要某個節點能具備照原樣讀出所寫內容的一致性,那麼與之繫結的會話就都能具備這種效能。它的缺點是降低”負載均衡“效能。另一種會話一致性的方式為,”版本戳“。

3 放寬一致性約束

         一致性是個好東西,在涉及系統時我們總是在避免出現不一致的現象。然而,要真正做到這一點,通常需要放棄系統中的其他一些特性,然而那些特性卻是必不可少的。

權衡利弊,用“容忍度“來對應各個領域的不一致性。

         CPA定理:給定一致性(Consistency),可用性(Availability),分割槽耐受性(Partition tolerance)這三個屬性,我們只能同時滿足其中兩個屬性。

         可用性:如果客戶可以同叢集中的某個節點通行,那麼該節點就必然能夠處理讀取及寫入操作。

分割槽耐受性(腦裂):如果發生通訊故障,導致整個叢集被分割成多個無法互相通訊的分割槽時,叢集仍然可用。

單伺服器系統顯然是種”CA系統“,也就是說,具備一致性與可用性,但卻不具備分割槽耐受性。

我們之所以要探討“CAP定理”,是因為在權衡分散式資料庫的“一致性”時,經常會提到並且“濫用它”,然而,與其考慮如何權衡“一致性”和“可用性”,不如思考怎麼樣在一致性和延遲之間取捨。在討論分散式系統的“一致性”問題時,通常可以概括的說:參與互動操作的節點越多,“一致性”就越好。然而問題是,每新增一個節點,都會使互動操作的響應時間變長。“可用性”可以視為能夠忍受的最大延遲時間,一旦延遲過高,我們就會放棄操作。並且認為資料不可用,這樣一來,就和”CAP定理”對“可用性”所下的定義相當吻合了。

四仲裁

一致性與永續性之間的取捨,並不是一個非此即彼的議題。處理請求所涉及的節點越多,避免不一致問題的能力就越強。這自然引出一個問題,要想保持強一致性,需要使用多少個節點才行。

假設某份資料需要複製到三個節點中,為了保持強一致性,不需要所有節點確認寫入操作,只需要其中兩個節點(也就是超過半數的節點)確認就可以了。在這種情況下,如果發生兩個相互衝突的寫入操作,那麼只有其中一個操作能為超過半數的節點所認可,這就是“寫入仲裁”,如果用稍微正規一些的方式說那就是W>N/2。這個不等式的意思是,參與寫入操作的節點數,必須超過副本節點數的一半。副本個數又稱為“複製因子”。

與寫入仲裁相似,還有讀取仲裁。也就是說想要保證能夠讀取到最新的資料,必須與多少個節點聯絡才行?讀取仲裁要複雜一些,因為它取決於確認寫入操作所需的節點數。

現在考慮“複製因子”為3的情況。假設寫入操作需要兩個節點來確認(W=2),那麼我們至少得聯絡兩個節點,才能保證獲取到最新的資料。然而,加入某些寫入操作只被一個節點所確認(W=1)那麼,我們必須和三個節點都通訊一遍,才能確保取到最新資料。在這種情況下,由於寫入操作沒有獲得足夠的節點支援率,說以可能會產生更新衝突。但是,只要從足夠數量的節點中讀出資料,就一定能偵測出此類衝突。因此,即便在寫入操作不具備強一致性的情況下,也可以實現出具有強一致性的讀取操作來。

執行讀取操作是所需聯絡的節點數(R),確認與寫入操作時所需徵詢的節點數(W)以及複製因子(N)這三者之間的關係,可以用一個不等式來表述。那就是,只有當R+W>N是,才能保證讀取操作的強一致性。

上述兩個不等式都適用於“對等式分佈模型”。如果使用“主從式分佈模型”,那麼只需向主節點中寫入資料,就可以避免“寫入衝突”了。