這種方式在es等分布式系統中也有體現,可以設定主shard提交即返回成功,或者需要replica shard提交成功再返回。
提到分布式架構就一定繞不開「一致性」問題,而「一致性」其實又包含了資料一致性和事務一致性兩種情況,本文主要討論資料一致性(事務一致性指acid)。
複製是導致出現資料一致性問題的唯一原因。
如果只用一台資料庫來處理所有的寫入和讀取請求,就一定不存在資料一致性的問題。 但在中大型專案中,我們卻經常需要將乙份資料儲存在超過一台資料庫中(即複製),原因有三:
1、即使一部分資料庫出現故障,系統也能正常工作(高可用)
2、使資料與使用者在地理上接近(降低延遲)
3、擴充套件可以處理讀請求的機器數量(可擴充套件性、提高讀取吞吐量)
本文假設資料集非常小,每台機器的空間都足夠儲存整個資料集,否則將會引入乙個新的話題「分割槽」。本文假設使用單領導者的主從複製演算法,即只有一台資料庫可以處理寫請求(稱為領導者或主庫),所有資料庫都可以處理讀請求(除主庫外其他都是追隨者或從庫)。
其實只有兩類資料一致性,強一致性與弱一致性。強一致性也叫做線性一致性,除此以外,所有其他的一致性都是弱一致性的特殊情況。所謂強一致性,即複製是同步的,弱一致性,即複製是非同步的。
使用者更新**頭像,在某個時間點,使用者向主庫傳送更新請求,不久之後主庫就收到了請求。在某個時刻,主庫又會將資料變更**給自己的從庫。最後,主庫通知使用者更新成功。
如果在返回「更新成功」並使新頭像對其他使用者可見之前,主庫需要等待從庫的確認,確保從庫已經收到寫入操作,那麼複製是同步的,即強一致性。如果主庫寫入成功後,不等待從庫的響應,直接返回「更新成功」,則複製是非同步的,即弱一致性。
強一致性可以保證從庫有與主庫一致的資料。如果主庫突然宕機,我們仍可以保證資料完整。但如果從庫宕機或網路阻塞,主庫就無法完成寫入操作。
在實踐中,我們通常使乙個從庫是同步的,而其他的則是非同步的。如果這個同步的從庫出現問題,則使另乙個非同步從庫同步。這可以確保永遠有兩個節點擁有完整資料:主庫和同步從庫。 這種配置稱為半同步。
開篇提到,容忍節點故障只是需要複製的乙個原因。另兩個原因是可擴充套件性和降低延遲。
單領導者的主從複製演算法要求所有寫入都由單個節點處理,但唯讀查詢可以由任何節點處理。對於讀多寫少的場景,我們往往建立很多從庫,並將讀請求分散到所有的從庫上去。這樣能減小主庫的負載,並允許向最近的節點傳送讀請求。當然這只適用於非同步複製——如果嘗試同步複製,則單個節點故障將使整個系統無法寫入。
當使用者從非同步從庫讀取時,如果此非同步從庫落後,他可能會看到過時的資訊。這種不一致只是乙個暫時的狀態——如果等待一段時間,從庫最終會趕上並與主庫保持一致。這稱為最終一致性。
最終兩個字用得很微妙,因為從寫入主庫到反映至從庫之間的延遲,可能僅僅是幾分之一秒,也可能是幾個小時。
手機刷虎撲的時候經常遇到,回覆某人的帖子然後想馬上檢視,但我剛提交的回覆可能尚未到達從庫,看起來好像是剛提交的資料丟失了,很不爽。
在這種情況下,我們需要讀寫一致性,也稱為讀己之寫一致性。它可以保證,如果使用者重新整理頁面,他們總會看到自己剛提交的任何更新。它不會對其他使用者的寫入做出承諾,其他使用者的更新可能稍等才會看到,但它保證使用者自己提交的資料能馬上被自己看到。
如何實現讀寫一致性?
最簡單的方案,對於某些特定的內容,都從主庫讀。舉個例子,知乎個人主頁資訊只能由使用者本人編輯,而不能由其他人編輯。因此,永遠從主庫讀取使用者自己的個人主頁,從從庫讀取其他使用者的個人主頁。
如果應用中的大部分內容都可能被使用者編輯,那這種方法就沒用了。在這種情況下可以使用其他標準來決定是否從主庫讀取,例如可以記錄每個使用者最後一次寫入主庫的時間,一分鐘內都從主庫讀,同時監控從庫的最後同步時間,任何超過一分鐘沒有更新的從庫不響應查詢。
還有一種更好的方法是,客戶端可以在本地記住最近一次寫入的時間戳,發起請求時帶著此時間戳。從庫提供任何查詢服務前,需確保該時間戳前的變更都已經同步到了本從庫中。如果當前從庫不夠新,則可以從另乙個從庫讀,或者等待從庫追趕上來。
使用者從某從庫查詢到了一條記錄,再次重新整理後發現此記錄不見了,就像遇到時光倒流。如果使用者從不同從庫進行多次讀取,就可能發生這種情況。
單調讀可以保證這種異常不會發生。單調讀意味著如果乙個使用者進行多次讀取時,絕對不會遇到時光倒流,即如果先前讀取到較新的資料,後續讀取不會得到更舊的資料。單調讀比強一致性更弱,比最終一致性更強。
實現單調讀取的一種方式是確保每個使用者總是從同乙個節點進行讀取(不同的使用者可以從不同的節點讀取),比如可以基於使用者id的雜湊值來選擇節點,而不是隨機選擇節點。
在本文中闡述因果一致性可能並不是乙個很好的時機,因為它往往發生在分割槽(也稱為分片)的分布式資料庫中。
分割槽後,每個節點並不包含全部資料。不同的節點獨立執行,因此不存在全域性寫入順序。如果使用者a提交乙個問題,使用者b提交了回答。問題寫入了節點a,回答寫入了節點b。因為同步延遲,發起查詢的使用者可能會先看到回答,再看到問題。
為了防止這種異常,需要另一種型別的保證:因果一致性。 即如果一系列寫入按某個邏輯順序發生,那麼任何人讀取這些寫入時,會看見它們以正確的邏輯順序出現。
這是乙個聽起來簡單,實際卻很難解決的問題。一種方案是應用保證將問題和對應的回答寫入相同的分割槽。但並不是所有的資料都能如此輕易地判斷因果依賴關係。如果有興趣可以搜尋向量時鐘深入此問題。
CAP原理與最終一致性 強一致性 透析
在足球比賽裡,乙個球員在一場比賽中進三個球,稱之為帽子戲法 hat trick 在分布式資料系統中,也有乙個帽子原理 cap theorem 不過此帽子非彼帽子。cap原理中,有三個要素 cap原理指的是,這三個要素最多只能同時實現兩點,不可能三者兼顧。因此在進行分布式架構設計時,必須做出取捨。而對...
最終一致性方案
訊息傳送一致性 微服務架構下,需要通過網路進行通訊,就自然引入了資料傳輸的不確定性,也就是cap原理中的p 分割槽容錯,而這裡的訊息傳送一致性是可靠訊息的保證。生成訊息的業務動作與訊息傳送的一致 e.g 如果業務操作成功,那麼由這個業務操作所產生的訊息一定會成功投遞出去,否則就丟失訊息 如上圖,保證...
資料庫的強一致性和弱一致性
強一致性可以理解為在任意時刻,所有節點中的資料是一樣的。同一時間點,你在節點a中獲取到key1的值與在節點b中獲取到key1的值應該都是一樣的 弱一致性 相當於非同步 系統並不保證續程序或者執行緒的訪問都會返回最新的更新過的值。系統在資料寫入成功之後,不承諾立即可以讀到最新寫入的值,也不會具體的承諾...