一.HBase特點:
1.弱視圖,HBase是一種高效的映射嵌套,用戶可以在運行時定義列,每一行都有屬于自己的列。
2.非標準化數(shù)據(jù)。
二.HBase表組成
1.行健,按字典順序存儲。
2.列簇,一組列的集合
3.單元格,列和行的交集是一個單元格,單元格是版本化的(默認使用時間戳),最新的版本在最前邊,默認保三個版本。單元格中的數(shù)據(jù)以二進制字節(jié)數(shù)組存儲。
三.列簇
1.列簇必須在創(chuàng)建表的時候定義。
2.每個列簇中的列數(shù)是沒有限制的。
3.同一列簇下的所有列會保存在一起。一個HFile文件保存一個列簇的數(shù)據(jù)。
4.列在列簇中是有序的,按照字典順序排列。
5.列可以在運行時動態(tài)創(chuàng)建。
6.列只有在插入數(shù)據(jù)后才會存在,空值不保存,不占存儲空間。
四.HBase存儲設(shè)置
1.壓縮格式,默認無壓縮,可以使用GZ、LZO、SNAPPY
2.HBase默認塊大小是64K,不是64兆,因為HBase需要支持隨機訪問,一旦在查詢的時候找到行健所在的塊,就會對應(yīng)塊的單元格數(shù)據(jù)取出,對64k大小的塊進行掃描的速度明顯快與64M。
3.內(nèi)存模型:默認false,如果設(shè)置為true,HBase會嘗試將整個列簇保存在內(nèi)存中。
4.塊緩存,默認true,HBase使用塊緩存將最近使用的塊加載到內(nèi)存中。塊緩存使用最近沒有使用(LRU)的原則刪除塊數(shù)據(jù)。
5.布隆過濾,是一種空間高效的數(shù)據(jù)結(jié)構(gòu),可以設(shè)置為ROW,使用行級的布隆過濾,ROWCOL使用行健與列標識級別的布隆過濾。
五.HBase組件
架構(gòu)圖(官方圖)

1.Zookeeper
主要職責(zé):支持遠程組件之間的松散耦合消息機制,組件之間通過心跳機制協(xié)調(diào)他們的狀態(tài)和健康信息。
2.Master
集群環(huán)境中可以同時存在多個主節(jié)點,但是同一時間只有一個扮演主節(jié)點的角色,其他節(jié)點作為備用節(jié)點,如果主節(jié)點與zk的租約過期,剩下的備用節(jié)點重新發(fā)起競爭,由zk選舉主節(jié)點。
功能:執(zhí)行集群管理操作,跟蹤數(shù)據(jù)位于哪個節(jié)點上(行健鑒別),控制負載均衡和故障切換,主節(jié)點不直接獲取RegionServer信息,通過zk獲取各RegionServer運行狀態(tài)。
3.RegionServer(分區(qū)服務(wù)器)
主要負責(zé)管理多個分區(qū),數(shù)據(jù)實際存儲在分區(qū)中,每一個RegionServer有一個WAL文件(預(yù)寫日志)和塊緩存,預(yù)寫日志文件存儲在hdfs,防止丟失。該RegionServer上的所有分區(qū)共享WAL和塊緩存.
4.WAL
功能:確保數(shù)據(jù)不丟失,如果發(fā)生故障,可以使用WAL恢復(fù)數(shù)據(jù)。
WAL中保存了分區(qū)服務(wù)器還沒有寫入HFile的所有操作。寫入WAL之后再寫入MemStore,當(dāng)MemStore的大小達到預(yù)設(shè)的值時,將數(shù)據(jù)寫入HFile固化到磁盤。如果想提高寫入性能可以關(guān)閉WAL,但是會有數(shù)據(jù)丟失的風(fēng)險。
5.塊緩存
是一種內(nèi)存結(jié)構(gòu),遵循LRU(最近沒有使用)回收規(guī)則,默認對表是開啟的。通過SCAN和GET獲取的數(shù)據(jù)都會加載到緩存。0.96版本之后支持使用JAVA NIO實現(xiàn)的堆外緩存,這個優(yōu)化大大減小了RegionServer的GC壓力。
6.分區(qū)
一個RegionServer上有多個分區(qū),每一個分區(qū)對應(yīng)一張表,管理表中一定范圍行健內(nèi)的行數(shù)據(jù),分區(qū)的行健范圍不必是連續(xù)的,分區(qū)對于表中不同列簇是分開存儲的,一個HFile存儲一個列簇的數(shù)據(jù)。
7.MemStore
當(dāng)HBase有更新操作時,先寫入WAL再寫入MemStore(內(nèi)存結(jié)構(gòu)),預(yù)定義MemStore大小配置hbase.hregion.memstore.flush.size。每一次持久化操作都會針對分區(qū)中的每一個列簇創(chuàng)建一個HFile文件,當(dāng)用戶讀取數(shù)據(jù)時先從MemStore中讀取數(shù)據(jù),如果沒有在MemStore中找到對應(yīng)的值才會嘗試從HFile文件中讀取。
注意:MemStore的持久化過程是阻塞的,此時不能提供服務(wù)。
早期的MemStore使用堆內(nèi)存實現(xiàn),會產(chǎn)生大量的堆內(nèi)存碎片,并導(dǎo)致周期行的FullGC,F(xiàn)ullGC會導(dǎo)致程序暫停。
8.HFile文件
最終保存HBase數(shù)據(jù)的文件(存儲于HDFS),一個HFile文件屬于一張表的一個列簇,數(shù)據(jù)以行健和列的字典順序排列,同時單元格內(nèi)的數(shù)據(jù)是以版本號降序排列。多個RegionServer的MemStore多次持久化的HFile文件,他們之間是無序的,HBase會通過部分壓縮和全量壓縮進行合并。當(dāng)HFile文件的數(shù)量達到一定的閾值,就會啟動部分壓縮,將多個HFile文件合并為一個大的HFile文件。全量壓縮會在每天的固定時間段進行(系統(tǒng)活躍度低的時間)。合并的過程會對數(shù)據(jù)重新排序,保證合并后的文件數(shù)據(jù)依然是有序的。
9.兩個重要的表-Root-.META.
-Root-保存.META.的路徑,它指向.META.在集群的哪個節(jié)點上。是唯一不會被拆分的表。
.META.保存集群中每個分區(qū)的元數(shù)據(jù),關(guān)鍵的類HRegionInfo,包括表的信息,表的起始行健值和終止行健值。

六.客戶端與HBase建立連接的過程
A.Client與ZK集群建立連接,從ZK集群獲取-Root-表位置信息。
B.Client連接-Root-表,并得到.META.表的位置信息。
C.Client連接.META.表并下載分區(qū)列表和他們的位置。
D.Client使用從.META.表下載的信息直接連接RegionServer中的分區(qū)操作數(shù)據(jù),在這過程中Clien會進行一系列的查詢操作。
E.Client會將-Root- .META.周期性的下載到本地,當(dāng)Client連接RegionServer后發(fā)現(xiàn).META.表提供的行健范圍不在分區(qū)中才會重新刷新本地目錄表緩存。

七.分區(qū)與壓縮
如果在創(chuàng)建表是沒有設(shè)置預(yù)分區(qū),剛創(chuàng)建表時只有一個分區(qū),直到該分區(qū)的大小達到habse.hregion.max.filesize屬性值時默認10G,該分區(qū)會再次分區(qū),注意此時的分區(qū)是邏輯分區(qū),只記錄分區(qū)的行健。分區(qū)大小會繼續(xù)增長,只有在全量壓縮的時候才會把邏輯分區(qū)轉(zhuǎn)為物理分區(qū),將原始數(shù)據(jù)文件拆開到其他分區(qū)HDFS路徑下的不同文件中。原始分區(qū)將在物理上分成兩個分區(qū),并且這兩個分區(qū)屬于不同的兩臺RegionServer。
壓縮是分區(qū)中HFile文件合并的過程,減少HFile的數(shù)量能夠提高HBase的性能。因為能夠減少scan和get讀取的文件數(shù)。壓縮分兩種:部分和全量。
部分壓縮,會把多個HFile文件壓縮成一個,部分壓縮的過程,Client仍然可以向MemStore寫數(shù)據(jù),但是不執(zhí)行MemStore的持久化,如果MemStore被寫滿,此時暫停對外服務(wù),與該分區(qū)交互的Client處于阻塞狀態(tài),直到壓縮過程執(zhí)行完畢,恢復(fù)操作。
全量壓縮,將一個分區(qū)內(nèi)所有的HFile文件合并成一個文件,在這個過程所有的刪除操作和版本過期的單元格都會被移除。全量壓縮默認每天執(zhí)行一次。(提示:HBase的刪除操作并不會在執(zhí)行完刪除命令后就立即刪除數(shù)據(jù),而是先給該數(shù)據(jù)打上被刪除的標簽,在全量壓縮的過程中才會被真正的刪除)