從功能上講:HBase主要是解決分佈式文件系統HDFS不能隨機讀寫而設計的,HBase是架設在HDFS之上的,因此HBase能夠存儲海量的數據,HBase又能夠支持隨機讀寫,因此HBase是一個支持海量數據隨機讀寫的分佈式存儲系統。
從架構上講:HBase中由zookeeper集羣、一個HMaster以及若干個HRegionServer組成,zookeeper主要是負責存儲HBase集羣中的元數據信息(包括但不限於HMaster的位置、HRegionServer的信息、Table等元數據信息),HMaster負責管理HRegionServer,HRegionServer負責管理HRegion,HBase中的table就是由HRegion組成的
從數據模型上講:HBase中的數據是以表的形式組織起來的,每張表都有本身屬於的namespace(你能夠把namespace看做Mysql中的數據庫),表默認的話是建立在default這個namespace中。HBase中的表實際上是一個相似於三層Map結構的模型,一個Table中包含不少的rowKey,每個rowkey就是對應着一行(row)數據;每一行數據包含了若干個列(column),每個列由一個column family(列蔟)和column qualifier(列名)組成,固然column qualifier能夠爲空;每個列包含了若干個版本的數據值,這個版本默認是數據插入時的服務器時間戳,版本數默認是1個,固然版本以及版本的數量是能夠設置的。
HBase中的數據是以表的形式組織起來的,每張表都有本身屬於的namespace(你能夠把namespace看做Mysql中的數據庫),表默認的話是建立在default這個namespace中。HBase中的表實際上是一個相似於三層Map結構的模型,以下圖:
一個Table中包含不少的rowKey,每個rowkey就是對應着一行(row)數據;每一行數據包含了若干個列(column),每個列由一個column family(列蔟)和column qualifier(列名)組成,固然column qualifier能夠爲空;每個列包含了若干個版本的數據值,這個版本默認是數據插入時的服務器時間戳,版本數默認是1個,固然版本以及版本的數量是能夠設置的。
(1) 一個Table中包含不少的rowKey,每個rowkey就是對應着一行(row)數據;每一行數據包含了若干個列(column),每個列由一個column family(列蔟)和column qualifier(列名)組成,column family不能爲空,column qualifier能夠爲空、
(2) 三層map:第一層map中的每一對Key-value 稱之爲row
第二層Map中的每一對key-value稱之爲column
第三層map中的每一對key-value稱之爲version——> value (版本,以時間戳)
namespace
更改設置version(1-6)
相比傳統數據庫,列式存儲空值不佔用空間,存儲的更加合理
使用hbase shell建立一張表test,而後對這張表進行增刪改查:
先建立一個新的namespace:
create_namespace ‘new_ns’
在new_ns中建立表:
create ‘new_ns:test’,‘f’, ‘e’ //test表中有2個column family
增長數據:
put ‘new_ns:test’, ‘rowkey-1’, ‘f:a’, ‘value1’
put ‘new_ns:test’, ‘rowkey-1’, ‘e’, ‘value2’
查詢一行或者一列的數據:
get ‘new_ns:test’, ‘rowkey-1’
get ‘new_ns:test’, ‘rowkey-1’, {COLUMN => ‘f:a’}
更新一列的值:
put ‘new_ns:test’, ‘rowkey-1’, ‘f:a’, ‘value3’
刪除一列或者一行的數據:
delete ‘new_ns:test’, ‘rowkey-1’, ‘f:a’
deleteall ‘new_ns:test’, ‘rowkey-1’
查看錶中有多少行數據:
count ‘new_ns:test’
清空表的數據:
truncate ‘new_ns:test’
查看錶結構:
desc‘new_ns:test’
修改表的結構:
disable ‘new_ns:test’
alter ‘new_ns:test’,{NAME=‘f’,TTL=‘15552000’}
enable ‘new_ns:test’
刪除表:
disable ‘new_ns:test’ ----在刪除以前須要disable
drop ‘new_ns:test’
描述下HBase的架構?
Hbase數據模型—— VERSION & TTL (Time To Live)
create 'new_ns:test',{NAME => 'f'},{NAME => 'e', VERSIONS => 3},{NAME => 'x'} 搜索是顯示最近3列,默認get最近一列
get 'new_ns:test',{COLUMN => 'e',VERSION => 10} 依然顯示最近三列
create 'new_ns:test',{NAME => 'f'},{NAME => 'e', VERSIONS => 1},{NAME => 'x', TTL => 5} 搜索時顯示最近5秒鐘內的全部數據,時間已過,column family對應的值所有清楚
alter new_ns:test',{NAME => 'x', TTL => 15} 更改屬性(涉及更改底層數據,更新較慢)
HBase也是遵照主從架構的技術,由一個主HMaster和若干個從HRegionServer組成。HBase中的一張表的數據由若干個HRegion組成,也就是說每個HRegion負責管理一張表中的一段數據,HRegion都是分佈式的存在於HRegionServer中(也就是說一個HRegionServer是管理多個HRegion的進程),因此說HRegion是HBase表中數據分佈式存儲的單位。那麼一個HRegion中又是由若干個column family的數據組成(HRegion對應的表有幾個column family,那麼HRegion中就管理幾個column family的數據);在HRegion中每一個column family數據由一個store管理,每一個store包含了一個memory store和若干個HFile組成,HFile的數據最終都會落地到HDFS文件中,因此說HBase依賴HDFS,存在HBase中的數據最終都會落地到HDFS中。
在HBase中還有一部分元數據信息,好比HMaster的狀態信息、HRegionServer的狀態信息以及HRegion的狀態信息等,這些信息都是存儲在zookeeper集羣中,zookeeper集羣在HBase中處於一個分佈式協調服務的角色,客戶端要鏈接HBase集羣的話,也是直接鏈接zookeeper集羣便可,客戶端能夠在zookeeper中找到須要和HBase的哪個進程通信。給出以下的架構圖:
單個值是怎樣存儲在HBase的表中的?
組織結構: 一個table對應多個Region,一個region對應多個Column Family,一張表有多少個Column Family,一個Region則對應多少個Column Family,Column Family裏面有一個Store,一個Store裏面含有一個MemoryStore和多個HFile。
Table-> Region的關係:
一個Table有多個Region,每個Region達到指定的數據量後(默認是10G),進行Region切分。Hbase最基本的存儲單元是Region,分佈式的存儲在全部HRegionServer上
每個Region負責管理和存儲一個Table中的某段數據。
每個table的RowKey是按照字符串的天然順序升序排列的 可使數據均勻分佈
Region-> Column Family的關係:
一個region對應多個Column Family,一張表有多少個Column Family,一個Region則對應多少個Column Family,Column Family數據存儲的基本單元
一個Region負責管理和存儲Table中全部的Column Family數據
一個Region負責管理和存儲一個或者多個Column Family的數據
三、Column Family -> Store的關係:
一個Column Family對應着一個Store
一個Store中含有一個MemoryStore和若干個HFile 數據先存儲在MemoryStore,達到必定的容量後在存儲在HFile中
四、HFile -> Block的關係:
一個HFile含有若干個不一樣類型的Dtata Block 及其餘元數據信息 即 Meta data
Block的大小一般爲8K到1MB,默認的大小是64KB
Block的類型有:Data Blocks、Index Blocks、Bloom filter Blocks以及Trailer block
五、Block -> KeyValue的關係:
一個Block包含一個magic數字和若干個KeyValue的數據
若干個 key value合計達到64kb組成一個block
put數據根據Rowkey 的排序放在相應的block中去,一個put操做值是存儲在table下面的對應的某一個Region下面的對應的CF下面的Hfile下面的block中的KeyValue,每個block在HFile中都是有索引信息的。請求獲取數據可經過索引信息拿到值所在的block信息,只須要掃描64kb的block就可拿到相應的值,進而達到高校的數據效果,進而支持高效的隨機讀寫。
HFile
答: HBase依賴HDFS,存在HBase中的數據最終都會落地到HDFS中,HBase中的數據在HDFS中就是以HFile這種格式的文件組織起來的。一個HFile包含了若干個不一樣類型的Block,每個Block的大小一般爲8K到1M(默認是64K);Block的類型有Data Blocks、Index Blocks、Bloom filter Blocks以及Trailer block,一個Data Block包含一個magic數字和若干個KeyValue的數據。Index Blocks是記錄每個Data Block的數據位置(就是索引信息)用於隨機讀寫
查看HFile內容:hbase org.apache.hadoop.hbase.io.hfile.HFile -f hfile_name
Block Encoder與Block Compressors
Prefix RowKey的存儲按升序排列,處理相對容易,只存儲不容部位,達到空間省略
diff 相同的數據不在存儲,進而達到空間節省
timestamp存儲時間差
diff
二、Fast Diff
若是你的rowkey很長,而且有不少的Column的話,則推薦使用Fast Diff,實現比Diff更快
Block Compressors
(一、none
(二、Snappy
(三、LZO
(四、LZ4
(五、GZ
默認 不壓縮
一、若是rowkey很長的話或者這個column family含有不少的column的話,則使用Block Encoder
推薦使用Fast Diff
二、若是value很大的話,則須要使用Block Compressors
三、對於訪問不頻繁的數據(code data),使用GZ壓縮器,由於GZ須要更多的cpu資源,可是有很好的壓縮率
四、對於訪問頻繁的數據(hot data),使用Snappy或者LZO壓縮器,由於Snappy或者LZO不須要更多的cpu資源,可是壓縮率沒有GZ高
五、大部分的場景下默認使用Snappy或者LZO就好,由於他們提供了更好的性能Snappy比LZO表現還稍微好點
create 'test_encoder_compress', {NAME => 'c', COMPRESSION => 'SNAPPY', DATA_BLOCK_ENCODING => 'FAST_DIFF'}, {NAME => 'l'}
create 'test_encoder_compress', {NAME => 'c', COMPRESSION => 'GZ', DATA_BLOCK_ENCODING => 'FAST_DIFF'}, {NAME => 'l'}
Bloom Filter
create 'webtable',{NAME => 'c', COMPRESSION => 'GZ', DATA_BLOCK_ENCODING => 'FAST_DIFF'}, {NAME => 'l', BLOOMFILTER => 'ROW'}
Bloom Filter取值: NONE, ROW(默認), ROWCOL
ROW:
根據KeyValue中的row來過濾storefile
舉例:假設有2個storefile文件sf1和sf2,
sf1包含kv1(r1 cf:q1 v)、kv2(r2 cf:q1 v)
sf2包含kv3(r3 cf:q1 v)、kv4(r4 cf:q1 v)
若是設置了CF屬性中的bloomfilter爲ROW,那麼get(r1)時就會過濾sf2,get(r3)就會過濾sf1
ROWCOL:
根據KeyValue中的row+qualifier來過濾storefile
舉例:假設有2個storefile文件sf1和sf2,
sf1包含kv1(r1 cf:q1 v)、kv2(r2 cf:q1 v)
sf2包含kv3(r1 cf:q2 v)、kv4(r2 cf:q2 v)
若是設置了CF屬性中的bloomfilter爲ROW,不管get(r1,q1)仍是get(r1,q2),都會讀取sf1+sf2;而若是設置了CF屬性中的bloomfilter爲ROWCOL,那麼get(r1,q1)就會過濾sf2,get(r1,q2)就會過濾sf1
HBase的讀寫緩存機制
寫緩存機制: Client====>hbase:meta===>RS===>HRegion===>WAL(穩定性和高可用性)===>Store===>MemoryStore===>HFile
全部的數據先寫入到Memory Store中,若是Memory Store所佔的內存符合下面的規則的話,則會將數據flush到磁盤中:
(1)、當一個Region中全部MemoryStore內存之和大於hbase.hregion.memstore.flush.size(默認大小是:134217728字節(128M))的時候,這個MemoryStore所在的Region中的全部MemoryStore都會寫到磁盤
(Hbase中的刪除並非真正的刪除,僅僅只是打上標記delecolum,在查詢時會過濾掉其標記數據,在數據壓實是會真正的刪除數據)
(2)、當一個HRegionServer中全部的MemoryStore加在一塊兒的大小大於hbase.regionserver.global.memstore.upperLimit默認大小是堆內存的40%,那麼這個HRegionServer中的全部的Region中的內存數據都會flush到磁盤中,當全部的內存使用達到
問題: 防止內存不穩定,提升可靠性
引用WAL機制 (Write Ahead Log 預寫日誌)
數據先寫道HDFS中的HLog中去,寫完後,在把數據put到MemoryStore中去
LogStner :用於同步緩存在RegionServer上的HLog到HDFS
rollWriter (1)用於滾動日誌,使得日誌文件數量以及文件大小不會太大,(2)MemoryStore中的文件已經持久化到HFile中去,清理掉HLog中的數據
數據恢復: recovered.edits 在HDFS中每一個region中都有一個 recovered.edits 自動回覆
(HLog默認開啓狀態,但消耗性能)
讀緩存機制:
Client(獲取對應RS所在的機器)===>hbase:meta===>RS===>HRegion===>Store===>MemoryStore(查看是否有相應數據)===>BlockCache(全部的Region共用一個BlockCache)===>HFile(讀到的數據快放在BlockCache中)
三種緩存過時策略:(內存容量必定的狀況下,內存滿了,清理數據算法)
一、FIFO -> 按照「先進先出」的原理來淘汰數據
二、LRU(Least recently used, 最近最少使用) -> 根據數據的歷史訪問記錄來進行淘汰數據,其核心思想是「若是數據最近被訪問過,那麼未來被訪問的概率也更高」
三、LFU(Least frequently used, 最近不常使用) -> 根據數據的歷史訪問頻率來淘汰數據,
其核心思想是「若是數據過去被訪問屢次,那麼未來被訪問的頻率也更高」
LruBlockCache中的三種Block priority:
一、Single access priority : 當一個Block第一次從HDFS中加載到內存中就是這個級別
二、Multi access priority : 當一個Block再次被訪問的時候就會變成這個級別
三、In-memory access priority : 當一個cf被設置爲In Memory的時候,則無論這個cf的block被訪問了多少次都不會從內存中淘汰,好比hbase:meta表中的cf,數據量小,常常訪問
HColumnDescriptor.setInMemory(true);
hbase(main):003:0> create 't', {NAME => 'f', IN_MEMORY => 'true'}
讀緩存策略包含兩種,一種是LruBlockCache,一種是BucketCache,其中默認是使用LruBlockCache
除了緩存須要讀取的block以外,還須要緩存以下的數據:
一、hbase:meta
二、HFile Indexes
三、Keys
四、Bloom Filters
LruBlockCache是使用LRU的算法實現的緩存策略
若是要使用BucketCache的話,須要配置開啓,BucketCache通常和LruBlockCache配合使用,配合使用的方式有兩種:
(1)、LruBlockCache用於緩存Index和Bloom這種META block數據,而BucketCache用於緩存真的數據
(2)、BucketCache做爲LruBlockCache的二級緩存使用hbase.regionserver.global.memstore.lowerLimit的時候就不會flush了
HBase中的compaction機制的
隨着時間的推移,Store中小的HFile愈來愈多,使得性能降低,這個時候就須要Compaction了。Compaction就是將小的HFile合併壓縮成一個大的HFile文件。Compaction分爲Minor compactions和Major compactions。
Minor compactions(局部壓縮):進行局部的壓縮,選擇一個Store中的小量的HFile進行合併成一個大的HFile文件
Major compactions(全局壓縮):合併一個表的全部Store中的HFiles,使得一個Store只有一個HFile。
一、Major Compaction還會真的刪除須要刪除的數據
二、Major Compaction還會真的刪除多餘版本的數據
三、默認是每7天會自動執行一次Major Compaction,將hbase.hregion.majorcompaction(默認是604800000 milliseconds,即7天)設置爲0的話,則表示禁止自動壓縮
執行Major Compaction的時候會使得HBase整個集羣都很是慢,由於Major Compaction須要大量的資源
防止熱點寫,在建立表的時候預切分紅4個region(3個切分點),進而解決熱點問題,根據rowkey的類型設計
太多的region
一、snapshots time out
二、compaction storms
三、客戶端的操做會超時(好比flush)
四、bulk load會超時(可能會拋出RegionTooBusyException)
形成太多region的緣由
一、爲每個Region的file size配置太小
二、不合理的對region進行了切分或者預切分
merge_region 'ENCODED_REGIONNAME','ENCODED_REGIONNAME'
merge_region 'ENCODED_REGIONNAME','ENCODED_REGIONNAME',true
Balancing
保持Region能夠均勻的分佈在每個RegionServer上
HMaster每隔:
hbase.balancer.period(默認是300000ms即5分鐘)
會進行一次Balance
Snapshot
在hbase-site.xml中配置以下參數,而後開啓snapshot功能
<property>
<name>hbase.snapshot.enabled</name>
<value>true</value>
</property>