參考:http://www.rigongyizu.com/hbase-row-lock-and-multiversion-concurrency-control/ 算法
MVCC (Multiversion Concurrency Control),即多版本併發控制技術,它使得大部分支持行鎖的事務引擎,再也不單純的使用行鎖來進行數據庫的併發控制,取而代之的是,把數據庫的行鎖與行的多個版本結合起來,只須要很小的開銷,就能夠實現非鎖定讀,從而大大提升數據庫系統的併發性能。 數據庫
HBase正是經過行鎖+MVCC保證了高效的併發讀寫。 apache
HBase系統自己只能保證單行的ACID特性。ACID的含義是: 併發
傳統的關係型數據庫通常都提供了跨越全部數據的ACID特性;爲了性能考慮,HBase只提供了基於單行的ACID。 mvc
下面是一個hbase併發寫的例子。 性能
原始數據以下
優化
從Apache HBase Write Path一文能夠知道hbase寫數據是分爲兩步:
1. 寫Write-Ahead-Log(WAL)文件
2. 寫MemStore:將每一個cell[(row,column)對]的數據寫到內存中的memstore ui
假定對寫沒有采起併發控制,並考慮如下的順序: spa
最終獲得的結果是: blog
這樣就獲得了不一致的結果。顯然咱們須要對併發寫操做進行同步。
最簡單的方式是提供一個基於行的獨佔鎖來保證對同一行寫的獨立性。因此寫的順序是:
儘管對併發寫加了鎖,可是對於讀呢?見下面的例子:
若是在上面的圖中紅線所示的地方進行讀操做,最終獲得的結果是:
可見須要對讀和寫也進行併發控制,否則會獲得不一致的數據。最簡單的方案就是讀和寫公用一把鎖。這樣雖然保證了ACID特性,可是讀寫操做同時搶佔鎖會互相影響各自的性能。
HBase採用了MVCC算法來避免讀操做去獲取行鎖。
對於寫操做:
對於讀操做:
在採用MVCC後的數據執行圖:
注意到採用MVCC算法後,每一次寫操做都有一個寫序號(即w1步),每一個cell數據寫memstore操做都有一個寫序號(w2,例如:「Cloudera [wn=1]」)),而且每次寫操做完成也是基於這個寫序號(w3)。
若是在「Restaurant [wn=2]」 這步以後,「Waiter [wn=2]」這步以前,開始一個讀操做。根據規則r1和r2,讀的序號爲1。根據規則3,讀操做以序號1讀到的值是:
這樣就實現了以無鎖的方式讀取到一致的數據了。
從新總結下MVCC算法下寫操做的執行流程:
本文是基於HBase 0.92. 在HBase 0.94中會有些優化策略,好比 HBASE-5541 提到的。
英文原文:https://blogs.apache.org/hbase/entry/apache_hbase_internals_locking_and