HBase數據模型剖析


出處:http://wuyudong.com/1987.html

HBase 進行數據建模的方式和你熟悉的關系型數據庫有些不同。關系型數據庫圍繞表、列和數據類型——數據的形態使用嚴格的規則。遵守這些嚴格規則的數據稱為結構化數據。HBase 設計上沒有嚴格形態的數據。數據記錄可能包含不一致的列、不確定大小等。這種數據稱為半結構化數據(semistructured data)。

在邏輯模型里針對結構化或半結構化數據的導向影響了數據系統物理模型的設計。關系型數據庫假定表中的記錄都是結構化的和高度有規律的。因此,在物理實現時,利用這一點相應優化硬盤上的存放格式和內存里的結構。同樣,HBase 也會利用所存儲數據是半結構化的特點。隨着系統發展,物理模型上的不同也會影響邏輯模型。因為這種雙向緊密的聯系,優化數據系統必須深入理解邏輯模型和物理模型。

除了面向半結構化數據的特點外,HBase 還有另外一個重要考慮因素——可擴展性。在半結構化邏輯模型里數據構成是松耦合的,這一點有利於物理分散存放。HBase 的物理模型設計上適合於物理分散存放,這一點也影響了邏輯模型。此外,這種物理模型設計迫使HBase 放棄了一些關系型數據庫具有的特性。特別是,HBase 不能實施關系約束(constraint)並且不支持多行事務(multirow transaction)。這種關系影響了下面幾個主題。

邏輯模型:有序映射的映射集合

HBase 中使用的邏輯數據模型有許多有效的描述。圖2-6 把這個模型解釋為鍵值數據庫。我們考慮的一種描述是有序映射的映射(sorted map of maps)。你大概熟悉編程語言里的映射集合或者字典結構。可以把HBase 看做這種結構的無限的、實體化的、嵌套的版本。

我們先來思考映射的映射這個概念。HBase 使用坐標系統來識別單元里的數據:[行鍵,列族,列限定符,時間版本]。例如,從users 表里取出Mark 的記錄

20160318162026

理解映射的映射的概念時,把這些坐標從里往外看。你可以想象,開始以時間版本為鍵、數據為值建立單元映射,往上一層以列限定符為鍵、單元映射為值建立列族映射,最后以行鍵為鍵列族映射為值建立表映射。這個龐然大物用Java 描述是這樣的:Map<RowKey, Map<ColumnFamily, Map<ColumnQualifier, Map<Version,Data>>>>。不算漂亮,但是簡單易懂。

注意我們說映射的映射是有序的。上述例子只顯示了一條記錄,即使如此也可以看到順序。注意password 單元有兩個時間版本。最新時間版本排在稍晚時間版本之前。HBase 按照時間戳降序排列各時間版本,所以最新數據總是在最前面。這種物理設計明顯導致可以快速訪問最新時間版本。其他的映射鍵按照升序排列。現在的例子看不到這一點,讓我們插入幾行記錄看看是什么樣子:

wu@ubuntu:~/opt/twitbase$ java -cp target/twitbase-1.0.0.jar HBaseIA.TwitBase.UsersTool add HMS_Surprise "Patrick O'Brian" aubrey@sea.com abc123

Successfully added user <User: HMS_Surprise, Patrick O'Brian, aubrey@sea.com, 0>

wu@ubuntu:~/opt/twitbase$ java -cp target/twitbase-1.0.0.jar HBaseIA.TwitBase.UsersTool add GrandpaD "Fyodor Dostoyevsky" fyodor@brothers.net abc123

Successfully added user <User: GrandpaD, Fyodor Dostoyevsky, fyodor@brothers.net, 0>

wu@ubuntu:~/opt/twitbase$ java -cp target/twitbase-1.0.0.jar HBaseIA.TwitBase.UsersTool add SirDoyle "Sir Arthur Conan Doyle" art@TheQueensMen.co.uk abc123

Successfully added user <User: SirDoyle, Sir Arthur Conan Doyle, art@TheQueensMen.co.uk, 0>

現在再次列出Users 表的內容,可以看到:

wu@ubuntu:~/opt/twitbase$ java -cp target/twitbase-1.0.0.jar HBaseIA.TwitBase.UsersTool list

16/03/18 01:31:51 INFO TwitBase.UsersTool: Found 4 users.
<User: GrandpaD, Fyodor Dostoyevsky, fyodor@brothers.net, 0>
<User: HMS_Surprise, Patrick O'Brian, aubrey@sea.com, 0>
<User: SirDoyle, Sir Arthur Conan Doyle, art@TheQueensMen.co.uk, 0>
<User: TheRealMT, Mark Twain, samul@clemens.org, 0>

實踐中,設計HBase 表模式時這種排序設計是一個關鍵考慮因素。這是另外一個物理數據模型影響邏輯模型的地方。掌握這些細節可以幫助你在設計模式時利用這個特性。

物理模型:面向列族

就像關系型數據庫一樣,HBase 中的表由行和列組成。HBase 中列按照列族分組。這種分組表現在映射的映射邏輯模型中是其中一個層次。列族也表現在物理模型中。每個列族在硬盤上有自己的HFile 集合。這種物理上的隔離允許在列族底層HFile 層面上分別進行管理。進一步考慮到合並,每個列族的HFile 都是獨立管理的。

HBase 的記錄按照鍵值對存儲在HFile 里。HFile 自身是二進制文件,不是直接可讀的。存儲在硬盤上HFile 里的Mark 用戶數據如圖2-8 所示。注意,在HFile 里Mark 這一行使用了多條記錄。每個列限定符和時間版本有自己的記錄。另外,文件里沒有空記錄(null)。如果沒有數據,HBase 不會存儲任何東西。因此列族的存儲是面向列的,就像其他列式數據庫一樣。一行中一個列族的數據不一定存放在同一個HFile 里。Mark 的info數據可能分散在多個HFile 里。唯一的要求是,一行中列族的數據需要物理存放在一起。

"TheRealMT"  , "info" , "email" ,          1329088321289 ,     "samuel@clemens.org"
"TheRealMT"  , "info" , "name"            1329088321289 ,     "Mark Twain"
"TheRealMT"  , "info",  "password" ,   1329088818321 ,     "abc123",
"TheRealMT"  , "info" , "password",    1329088321289 ,     "Langhorne"

如果users 表有了另一個列族,並且Mark 在那些列里有數據。Mark 的行也會在那些HFile 里有數據。每個列族使用自己的HFile 意味着,當執行讀操作時HBase 不需要讀出一行中所有的數據,只需要讀取用到列族的數據。面向列意味着當檢索指定單元時,HBase 不需要讀占位符(placeholder)記錄。這兩個物理細節有利於稀疏數據集合的高效存儲和快速讀取。

讓我們增加另外一個列族到users 表,以存儲TwitBase 網站上的活動,這會生成多個HFile。讓HBase 管理整行的一整套工具如圖所示。HBase 稱這種機制為region,我們在后面會討論。

20160318171023

在圖中可以看到,訪問不同列族的數據涉及完全不同的MemStore 和HFile。列族activity 數據的增長並不影響列族info 的性能。


免責聲明!

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



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