Hbase中的Column Family(转载)
1. 概述
HBase是一幫家伙看了Google發(fā)布的一片名為“BigTable”的論文以后,猶如醍醐灌頂,進而“山寨”出來的一套系統(tǒng)。
由此可見:
1. 幾乎所有的HBase中的理念,都可以從BigTable論文中得到解釋。原文是英語的,而且還有不少數(shù)學概念,看了有點兒懵,建議網(wǎng)上找找學習筆記看看,差不多也就可以入門了。
2. Google確實牛X。
3. 老外也愛山寨~
?
第一次看HBase, 可能看到以下描述會懵:“基于列存儲”,“稀疏MAP”,“RowKey”,“ColumnFamily”。
其實沒那么高深,我們需要分兩步來理解HBase, 就能夠理解為什么HBase能夠“快速地”“分布式地”處理“大量數(shù)據(jù)”了。
1.內(nèi)存結(jié)構(gòu)
2.文件存儲結(jié)構(gòu)
?
2. 名詞概念以及內(nèi)存結(jié)構(gòu)
假設我們有一張表(其中只有一條數(shù)據(jù)):
| RowKey | ColumnFamily : CF1 | ColumnFamily : CF2 | TimeStamp | ||
| Column: C11 | Column: C12 | Column: C21 | Column: C22 | ||
| “com.google” | “C11 good” | “C12 good” | “C12 bad” | “C12 bad” | T1 |
?
?
?
?
1) RowKey: 行鍵,可理解成MySQL中的主鍵列。
2) Column: 列,可理解成MySQL列。
3) ColumnFamily: 列族, HBase引入的概念:
4) TimeStamp:在每次跟新數(shù)據(jù)時,用以標識一行數(shù)據(jù)的不同版本(事實上,TimeStamp是與列綁定的。)
?
那我們?yōu)楹螘玫紿Base的讀寫高性能呢?其實所有數(shù)據(jù)庫操作如何得到高性能,答案幾乎都是一致的,就是做索引。
HBase的設計拋棄了傳統(tǒng)RDBMS的行式數(shù)據(jù)模型,把索引和數(shù)據(jù)模型原生的集成在了一起。
以上圖的表為例,表數(shù)據(jù)在HBase內(nèi)部用Map實現(xiàn),我們把它寫成JSon的Object表述,即:
{"com.google": {CF1: {C11:{T1: good}C12:{T1: good}CF2: {C21:{T1: bad}C22:{T1: bad}}} }由于Map本身可以通過B+樹來實現(xiàn),所以隨機訪問的速度大大加快(我們需要想象一下,表中有很多行的情況)。
現(xiàn)在我們在原來的表上修改一下(將Column: C22改為”good”):
| RowKey | ColumnFamily : CF1 | ColumnFamily : CF2 | TimeStamp | ||
| Column: C11 | Column: C12 | Column: C21 | Column: C22 | ||
| “com.google” | “C11 good” | “C12 good” | “C12 bad” | “C12 bad” | T1 |
| “com.google” | “C11 good” | “C12 good” | “C12 bad” | “C12 good” | T2 |
?
?
?
?
?
于是MAP變?yōu)榱?#xff1a;
?
{"com.google": {CF1: {C11:{T1: good}C12:{T1: good}CF2: {C21:{T1: bad}C22:{T1: badT2:good}}} }事實上,我們只需要在C22的object再加一個屬性即可。如果我們把這個MAP翻譯成表形狀,也可以表示為:
| RowKey | ColumnFamily : CF1 | ColumnFamily : CF2 | TimeStamp | ||
| Column: C11 | Column: C12 | Column: C21 | Column: C22 | ||
| “com.google” | “C11 good” | “C12 good” | “C12 bad” | “C12 bad” | T1 |
| ? | ? | ? | ? | “C12 good” | T2 |
?
?
?
?
?
我們發(fā)現(xiàn),這個表里很多列是沒有value的。想象一下,如果再加入一行RowKey不同的數(shù)據(jù),其中Column:C11內(nèi)容為空,就可以在Json中省略該屬性了。
好了,扯了這么多,就是為了說明HBase是“稀疏的高階MAP”。
為了查詢效率,HBase內(nèi)部對RowKey做了排序,以保證類似的或者相同的RowKey都集中在一起,于是HBase就變成了一張“稀疏的,有序的,高階的MAP”。有沒有覺得這樣的表述很高冷? :)
?
?數(shù)據(jù)在 MySQL 中的排布示例
| 1 | 張 | 三 | 111 | 20160719 |
| 2 | 李 | 四 | 222 | 20160720 |
那么數(shù)據(jù)在 HBase 中的排布會是什么樣子呢?(這只是邏輯上的排布)。
數(shù)據(jù)在 HBase 中的排布(邏輯上)
| 1 | info{'姓': '張','名':'三'} pwd{'密碼': '111'} |
| 2 | Info{'姓': '李','名':'四'} pwd{'密碼': '222'} |
從上面示例表中,我們可以看出,在 HBase 中首先會有 Column Family 的概念,簡稱為 CF。CF 一般用于將相關(guān)的列(Column)組合起來。在物理上 HBase 其實是按 CF 存儲的,只是按照 Row-key 將相關(guān) CF 中的列關(guān)聯(lián)起來。
?
3. 文件存儲結(jié)構(gòu)與進程模型
如上所述,HBase是一張“稀疏的,有序的,高階的MAP”。
通常來說,MAP可以用B+樹來實現(xiàn)。B+樹對查詢性能而言表現(xiàn)良好,但是對插入數(shù)據(jù)有些力不從心,尤其對于插入的數(shù)據(jù)需要持久化到磁盤的情況而言。
我們對RowKey做了排序,為了保證查詢效率,我們希望將連續(xù)RowKey的數(shù)值保存在連續(xù)的磁道上,以避免大量的磁盤隨機尋道。所以在插入數(shù)據(jù)時,對于B+樹而言,就面臨著大量的文件搬移工作。
HBase使用了LSM樹實現(xiàn)了MAP,簡單說來,就是將插入/修改操作緩存在內(nèi)存中,當內(nèi)存中積累足夠的數(shù)據(jù)后,再以塊的形式刷入到磁盤上。
?
HBase的進程模型:
?
Region: 基于RowKey的分區(qū),可理解成MySQL的水平切分。
每個Region Server就是Hadoop集群中一臺機器上的一個進程。
比如我們的有1-300號的RowKey, 那么1-100號RowKey的行被分配到Region Server 1上,同樣,101-200號分配到Region Server 2上, 201-300號分配到Region Server 3上。
在內(nèi)存模型中,我們說RowKey保證了相鄰RowKey的記錄被連續(xù)地寫入了磁盤。在這里,我們發(fā)現(xiàn),RowKey決定了行操作(增,刪,改,查)會被交與哪臺Region Server操作。
讓我們假設一下,如果我們的RowKey以記錄的TimeStamp起始,從內(nèi)存模型上說,這很合理,因為我們可能面臨大量的用戶流水記錄查詢,查詢的條件會設置一個時間片段,我們希望一次性從磁盤中讀取這些流水記錄,從而避免頻繁的磁盤尋道操作。
但是再另一方面,用戶的流水記錄查詢會很頻繁的出現(xiàn)“截至到至今”的查詢條件,依照我們上面的進程模型,Region Server 3一定會被分配到(因為最近的記錄排在最后),這樣就可能造成Region Server 3的“過熱”,而Region Server 1“過冷”的情況。
?
文件存儲模型:
在HDFS中,每張表對應一個目錄,在表目錄下,每個Region對應一個目錄,在Region目錄下,每個Store對應一個目錄(一個Store對應一個ColumFamily)。結(jié)構(gòu)如下:
HBase|---Table|---XXXX(Region的hash)| || ----ColumnFamily| || ---文件|---YYYYY(另一個Region的hash)我們的新發(fā)現(xiàn)是,不同的ColumnFamily對應不同的Store, 并且被寫入了不同的目錄, 這意味著:
1. 通過將一張表分解成了不同的ColumnFamily,HBase可以從磁盤一次讀取更少的內(nèi)容(IO操作往往是計算機系統(tǒng)中最慢的一環(huán))。
2. 我們不應該將需要一次查詢出的列,分解在不同的ColumnFamily中,否則以為著HBase不得不讀取兩個文件來滿足查詢要求。
?
另外,一個ColumnFamily中的每一列是連續(xù)存儲的。即如果一個ColumnFamily中存在C1,C2兩列,一段具有100行記錄的存儲格式是:
C1(1),C2(1),C1(2),C2(2),C1(3),C2(3).............C1(100),C2(100)
與其說HBase是基于列的數(shù)據(jù)庫,更不如說HBase是基于“列族”的數(shù)據(jù)庫。
?
4 理解:
基于以上的模型,大致的理解是:
1. RowKey決定了行操作任務進入RegionServer的數(shù)量,我們應該盡量的讓一次操作調(diào)用更多的Region Server,已達到分布式的目的。
2. RowKey決定了查詢讀取連續(xù)磁盤塊的數(shù)量,最理想的情況是一次查詢,在每個Region Server上,只讀取一個磁盤塊。
3. ColumnFamily決定了一次查詢需要讀取的文件數(shù)(不同的文件不僅意味著分散的磁盤塊,還意味著多次的文件打開關(guān)閉操作)。我們應盡量將希望查詢的結(jié)果集合并到一個ColumnFamily中。同時盡量去除該ColumnFamily中不需要的列。
4. HBase官方建議盡量的減少ColumnFamily的數(shù)量。
?
再瞎總結(jié)一下:
1. RowKey由查詢條件決定。
2. ColumnFamily由查詢結(jié)果決定。
?
Reference:
[1]HBase概念及表格設計
[2]HBase 深入淺出
?
總結(jié)
以上是生活随笔為你收集整理的Hbase中的Column Family(转载)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ZooKeeper available
- 下一篇: NIFI使用过程中的invalid co