和上一篇博文同樣,此次咱們依舊以 Riak 爲案例,來分析 CAP
理論在一個實際的分佈式數據庫中的做用。html
若是你還不熟悉 CAP
,能夠參考我以前的兩篇博客 理解 CAP 理論, 最終一致性.html)。node
此次咱們來看看,在 Riak 這樣的分佈式key-value數據庫中,CAP
理論是怎麼起做用的。數據庫
首先仍是讓咱們來明確幾個概念。服務器
N odes分佈式
須要"最終"包含正確的值的服務器節點總數(正確的冗餘數據拷貝數)。性能
W ritesspa
每次寫操做,咱們須要確保最少有多少節點被更新。也就是說,咱們在執行寫操做的時候,不須要等待 N 個節點都成功被寫入,
而只須要 W 個節點成功寫入,此次寫操做就返回成功,而其餘節點是在後臺進行同步。code
R eadshtm
每次讀操做,咱們須要確保最少讀到幾份冗餘數據。也就是說,咱們在執行讀操做的時候,須要讀到 R 個節點的數據纔算讀成功,不然讀取失敗。ip
爲何要這三個變量?其實這三個變量直接關係到了 Riak 的 CAP 特性。下面咱們就來一一說明:
以下圖所示:假設咱們的 N=3, 設置 W + R <= N(例如:R=2, W=1)。這樣咱們的系統能夠相對保證讀寫性能。
由於寫操做只須要一個節點寫入就返回成功。
然而這裏有機率發生這樣的狀況:就像圖中所示,我寫入的是node1(versionB),而後進行了一次讀操做。
剛好這時候新數據還沒有同步到node2, node3,而讀操做又是從node2,node3取的值。因爲這兩個節點的值都是 version A,
因此獲得的值即是 version A。
不過隨着時間的推移,node1 中的 versionB 會被同步到 node2 以及 node3 中。
這時候,再有讀操做,獲得的值即是最新值(versionB)了。
這就是所謂的 Eventual Consistency。整個系統有着較高的讀寫性能,但一致性有所犧牲。
若是咱們須要增強一致性,能夠經過調整 W, R, N 來實現。
接下來咱們會討論如何調整 W,R,N 的關係來平衡讀寫性能和一致性(即 A 和 C 的平衡)。
一種極端作法(下圖所示),咱們能夠設 W=N, R=1。其實這就是關係型數據庫的作法。
經過確保每次寫操做時,全部相關節點都被成功寫入,來確保一致性。這樣能夠保證一致性,可是犧牲了寫操做的性能。
還有一種極端作法,咱們能夠設W=1, R=N。這樣,不管你向哪一個node寫入了數據,都會被讀到。
而後你讀到的N個值也可能包含舊的值,只要有辦法分辨出哪一個是最新的值就能夠了
(Riak 是用一直叫向量鍾(Vector Clock)的技術來判斷的,咱們會在後面的博客中作介紹)
這樣能夠保證一致性,可是犧牲了讀操做的性能。
最後再給出一種被稱做 quorum
的作法。以下圖所示,能夠設置 W + R > N (例如 W=2, R=2)。這樣一樣能夠保證一致性。
然而性能的損失由寫操做和讀操做共同承擔。這種作法叫作 quorum
。