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