HBase中數據的多版本特性潛在的意外


HBase做為KeyValue結構存儲,在存儲上是依照RowKey的字典序進行排序,對於很多應用而言這可能遠遠不夠,好在HBase的數據可以存儲多個版本,並且版本可以排序,其理論上最大的版本數目Integer.MAX_VALUE,這在一定程度上簡化應用端的設計 

舉個例子,假設現在有一個應用,對用戶的每次登錄信息(如:時間+IP)進行,並要求可以快速獲取指定用戶的最近登錄信息,如果選用HBase存儲則可以設計為:RowKey為用戶ID,value為IP地址,並指定timestamp為登錄時間,依照版本的保留特性,可以很容易地保存用戶近一月、近一年的登錄信息。 

看起來上面的設計很不錯,畢竟用戶啥都不需要操作,HBASE可以很容易為你保留近一段時間內的數據 

但是,如果一知半解,很可能會發生一些你意料之外的現象 

1.先后插入兩條數據,他們擁有相同的RowKey,列,以及timestamp,不同的value 
實際結果:只能獲取到第2次插入的數據,而不是兩個版本 

2.先插入一條數據,版本為t1,然后刪除版本t1,再插入一條數據,版本仍為t1 
實際結果:讀取版本為t1的數據時為空 

3.先刪除版本小於t1的數據,再插入一條數據,版本為t2,並且t2<t1 
實際結果:讀取版本為t2的數據時為空 

出現這樣現象的原因可由KeyValue的大小計較 和 HBase的插入刪除邏輯解釋 

a.KeyValue的大小比較規則,優先級從大到小依次為RowKey cf+cq timestamp type, 
具體點比如說,在比較2個KeyValue時,先比較RowKey的大小('a' < 'b'),相同的情況下比較cf+cq的大小('cf1:q1'<'cf2:q1'<'cf2:q2'),如果還是相同的話就比較時間戳(3042211081<3042211080,注意 我沒寫錯,你沒看錯,時間戳的long值越大,表示數據越新,在從小到大的隊列中越靠前),如果上述仍然還相同則比較TYPE('DeleteFamily' < 'DeleteColumn' < 'Delete' < Put) 


b.HBase的插入和刪除都是是向HBase提交一條KeyValue,而真正的物理刪除發生在compact時,所以,在客戶端,雖然相同的版本插入和刪除有先后順序,但是在服務端上,這是不可見的,相同的版本號,delete類型的KV永遠都排在put前,而讀到delete的kv后,就直接返回了 

如果要避免23現象出現,則需要在插入前做compact操作,這樣才能得到想要的結果 

4.HBase設計為版本數最多為Integer.MAX_VALUE,但是如果你真插入了接近該數的版本后,那可能有很大的風險在等着你 
首先,compact時很有可能就out of memory 
其次,單個rowkey的region再大也是不會split的


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM