天天看點

HBase資料模型剖析

hbase

進行資料模組化的方式和你熟悉的關系型資料庫有些不同。關系型資料庫圍繞表、列和資料類型——資料的形态使用嚴格的規則。遵守這些嚴格規則的資料稱為結構化

資料。hbase 設計上沒有嚴格形态的資料。資料記錄可能包含不一緻的列、不确定大小等。這種資料稱為半結構化資料(semistructured

data)。

在邏輯模型裡針對結構化或半結構化資料的導向影響了資料系統實體模型的設計。關系型資料庫假定表中的記錄都是結構化的和高度有規律的。是以,在實體

實作時,利用這一點相應優化硬碟上的存放格式和記憶體裡的結構。同樣,hbase

也會利用所存儲資料是半結構化的特點。随着系統發展,實體模型上的不同也會影響邏輯模型。因為這種雙向緊密的聯系,優化資料系統必須深入了解邏輯模型和物

理模型。

除了面向半結構化資料的特點外,hbase

還有另外一個重要考慮因素——可擴充性。在半結構化邏輯模型裡資料構成是松耦合的,這一點有利于實體分散存放。hbase

的實體模型設計上适合于實體分散存放,這一點也影響了邏輯模型。此外,這種實體模型設計迫使hbase

放棄了一些關系型資料庫具有的特性。特别是,hbase 不能實施關系限制(constraint)并且不支援多行事務(multirow

transaction)。這種關系影響了下面幾個主題。

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

hbase 中使用的邏輯資料模型有許多有效的描述。圖2-6 把這個模型解釋為鍵值資料庫。我們考慮的一種描述是有序映射的映射(sorted

map of maps)。你大概熟悉程式設計語言裡的映射集合或者字典結構。可以把hbase 看做這種結構的無限的、實體化的、嵌套的版本。

我們先來思考映射的映射這個概念。hbase 使用坐标系統來識别單元裡的資料:[行鍵,列族,列限定符,時間版本]。例如,從users 表裡取出mark 的記錄

HBase資料模型剖析

了解映射的映射的概念時,把這些坐标從裡往外看。你可以想象,開始以時間版本為鍵、資料為值建立單元映射,往上一層以列限定符為鍵、單元映射為值建

立列族映射,最後以行鍵為鍵列族映射為值建立表映射。這個龐然大物用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"

[email protected] abc123

successfully added user <user: hms_surprise, patrick o'brian, [email protected], 0>

hbaseia.twitbase.userstool add grandpad "fyodor dostoyevsky"

[email protected] abc123

successfully added user <user: grandpad, fyodor dostoyevsky, [email protected], 0>

hbaseia.twitbase.userstool add sirdoyle "sir arthur conan doyle"

[email protected] abc123

successfully added user <user: sirdoyle, sir arthur conan doyle, [email protected], 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, [email protected], 0>

<user: hms_surprise, patrick o'brian, [email protected], 0>

<user: sirdoyle, sir arthur conan doyle, [email protected], 0>

<user: therealmt, mark twain, [email protected], 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 ,     "[email protected]"

"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,我們在後面會讨論。

HBase資料模型剖析

在圖中可以看到,通路不同列族的資料涉及完全不同的memstore 和hfile。列族activity 資料的增長并不影響列族info 的性能。