Hbase架構與原理
Hbase架構與原理 | 辛修燦Blog
Hbase架構與原理
HBase是一個分散式的、面向列的開源資料庫,該技術來源於 Fay Chang所撰寫的Google論文「Bigtable:一個結構化數據的分散式存儲系統」。就像Bigtable利用了Google文件系統(File System)所提供的分散式數據存儲一樣,HBase在Hadoop之上提供了類似於Bigtable的能力。HBase是Apache的Hadoop項目的子項目。HBase不同於一般的關係資料庫,它是一個適合於非結構化數據存儲的資料庫。另一個不同的是HBase基於列的而不是基於行的模式。
1、Hadoop生太圈
hadoop所有應用都是構建於hdfs(它提供高可靠的底層存儲支持,幾乎已經成為分散式文件存儲系統事實上的工業標準)之上的分散式列存儲系統,主要用于海量結構化數據存儲。通過Hadoop生態圈,可以看到HBase的身影,可見HBase在Hadoop的生態圈是扮演這一個重要的角色那就是 實時、分散式、高維數據 的數據存儲;
2、HBase簡介
– HBase – Hadoop Database,是一個高可靠性、高性能、面向列、可伸縮、 實時讀寫的分散式資料庫
– 利用Hadoop HDFS作為其文件存儲系統,利用Hadoop MapReduce來處理HBase中的海量數據,利用Zookeeper作為其分散式協同服務– 主要用來存儲非結構化和半結構化的鬆散數據(列存NoSQL資料庫)
Hbase特性:
- 強一致性讀寫: HBase 不是 「最終一致性(eventually consistent)」 數據存儲這讓它很適合高速計數聚合類任務。
- 自動分片(Automatic sharding):HBase表通過region分布在集群中。數據增長時,region會自動分割並重新分布。
- RegionServer 自動故障轉移
- Hadoop/HDFS 集成: HBase 支持本機外HDFS 作為它的分散式文件系統。
- MapReduce: HBase 通過MapReduce支持大並發處理, HBase 可以同時做源和目標.
- Java 客戶端 API: HBase 支持易於使用的 Java API 進行編程訪問.
- Thrift/REST API:HBase 也支持Thrift和 REST 作為非Java 前端.
- Block Cache 和 Bloom Filters: 對於大容量查詢優化, HBase支持 Block Cache 和 Bloom Filters。
- 運維管理: HBase提供內置網頁用於運維視角和JMX 度量.
3、HBase數據模型
以關係型數據的思維下會感覺,上面的表格是一個5列4行的數據表格,但是在HBase中這種理解是錯誤的,其實在HBase中上面的表格只是一行數據;
Row Key:
- 決定一行數據的唯一標識
- RowKey是按照字典順序排序的。
- Row key最多只能存儲64k的位元組數據。
Column Family列族(CF1、CF2、CF3) & qualifier列:
- HBase表中的每個列都歸屬於某個列族,列族必須作為表模式(schema) 定義的一部分預先給出。如create 『test』, 『course』;
- 列名以列族作為前綴,每個「列族」都可以有多個列成員(column,每個列族中可以存放幾千~上千萬個列);如 CF1:q1, CF2:qw,新的列族成員(列)可以隨後按需、動態加入,Family下面可以有多個Qualifier,所以可以簡單的理解為,HBase中的列是二級列,也就是說Family是第一級列,Qualifier是第二級列。兩個是父子關係。
- 許可權控制、存儲以及調優都是在列族層面進行的;
- HBase把同一列族裡面的數據存儲在同一目錄下,由幾個文件保存。
- 目前為止HBase的列族能能夠很好處理最多不超過3個列族。
Timestamp時間戳:
- 在HBase每個cell存儲單元對同一份數據有多個版本,根據唯一的時間戳來區分每個版本之間的差異,不同版本的數據按照時間倒序排序,最新的數據版本排在最前面。
- 時間戳的類型是64位整型。
- 時間戳可以由HBase(在數據寫入時自動)賦值,此時時間戳是精確到毫 秒的當前系統時間。
- 時間戳也可以由客戶顯式賦值,如果應用程序要避免數據版本衝突, 就必須自己生成具有唯一性的時間戳。
Cell單元格:
- 由行和列的坐標交叉決定;
- 單元格是有版本的(由時間戳來作為版本);
- 單元格的內容是未解析的位元組數組(Byte[]),cell中的數據是沒有類型的,全部是位元組碼形式存貯。
- 由{row key,column(= +),version}唯一確定的單元。
4、HBase體系架構
Client
- 包含訪問HBase的介面並維護cache來加快對HBase的訪問
Zookeeper
- 保證任何時候,集群中只有一個master
- 存貯所有Region的定址入口。
- 實時監控Region server的上線和下線信息。並實時通知Master
- 存儲HBase的schema和table元數據
Master
- 為Region server分配region
- 負責Region server的負載均衡
- 發現失效的Region server並重新分配其上的region
- 管理用戶對table的增刪改操作
RegionServer
- Region server維護region,處理對這些region的IO請求
- Region server負責切分在運行過程中變得過大的region
HLog(WAL log):
- HLog文件就是一個普通的Hadoop Sequence File,Sequence File 的Key是HLogKey對象,HLogKey中記錄了寫入數據的歸屬信息,除了table和 region名字外,同時還包括sequence number和timestamp,timestamp是」 寫入時間」,sequence number的起始值為0,或者是最近一次存入文件系 統中sequence number。
- HLog SequeceFile的Value是HBase的KeyValue對象,即對應HFile中的 KeyValue
Region
- HBase自動把表水平劃分成多個區域(region),每個region會保存一個表裡面某段連續的數據;每個表一開始只有一個region,隨著數據不斷插入表,region不斷增大,當增大到一個閥值的時候,region就會等分會 兩個新的region(裂變);
- 當table中的行不斷增多,就會有越來越多的region。這樣一張完整的表 被保存在多個Regionserver上。
Memstore 與 storefile
- 一個region由多個store組成,一個store對應一個CF(列族)
- store包括位於內存中的memstore和位於磁碟的storefile寫操作先寫入memstore,當memstore中的數據達到某個閾值,hregionserver會啟動flashcache進程寫入storefile,每次寫入形成單獨的一個storefile
- 當storefile文件的數量增長到一定閾值後,系統會進行合併(minor、 major compaction),在合併過程中會進行版本合併和刪除工作 (majar),形成更大的storefile。
- 當一個region所有storefile的大小和超過一定閾值後,會把當前的region分割為兩個,並由hmaster分配到相應的regionserver伺服器,實現負載均衡。
- 客戶端檢索數據,先在memstore找,找不到再找storefile
- HRegion是HBase中分散式存儲和負載均衡的最小單元。最小單元就表示不同的HRegion可以分布在不同的HRegion server上。
- HRegion由一個或者多個Store組成,每個store保存一個columns family。
- 每個Strore又由一個memStore和0至多個StoreFile組成。
5.Hbase優化
1.預先分區
默認情況下,在創建 HBase 表的時候會自動創建一個 Region 分區,當導入數據的時候,所有的 HBase 客戶端都向這一個 Region 寫數據,直到這個 Region 足夠大了才進行切分。一種可以加快批量寫入速度的方法是通過預先創建一些空的 Regions,這樣當數據寫入 HBase 時,會按照 Region 分區情況,在集群內做數據的負載均衡。
2.Rowkey優化
HBase 中 Rowkey 是按照字典序存儲,因此,設計 Rowkey 時,要充分利用排序特點,將經常一起讀取的數據存儲到一塊,將最近可能會被訪問的數據放在一塊。
此外,Rowkey 若是遞增的生成,建議不要使用正序直接寫入 Rowkey,而是採用 reverse 的方式反轉Rowkey,使得 Rowkey 大致均衡分布,這樣設計有個好處是能將 RegionServer 的負載均衡,否則容易產生所有新數據都在一個 RegionServer 上堆積的現象,這一點還可以結合 table 的預切分一起設計。
3.減少列族數量
不要在一張表裡定義太多的 ColumnFamily。目前 Hbase 並不能很好的處理超過 2~3 個 ColumnFamily 的表。因為某個 ColumnFamily 在 flush 的時候,它鄰近的 ColumnFamily 也會因關聯效應被觸發 flush,最終導致系統產生更多的 I/O。
4.緩存策略
創建表的時候,可以通過 HColumnDescriptor.setInMemory(true) 將表放到 RegionServer 的緩存中,保證在讀取的時候被 cache 命中。
5.設置存儲生命期
創建表的時候,可以通過 HColumnDescriptor.setTimeToLive(int timeToLive) 設置表中數據的存儲生命期,過期數據將自動被刪除。
6.硬碟配置
每台 RegionServer 管理 10~1000 個 Regions,每個 Region 在 1~2G,則每台 Server 最少要 10G,最大要1000*2G=2TB,考慮 3 備份,則要 6TB。方案一是用 3 塊 2TB 硬碟,二是用 12 塊 500G 硬碟,帶寬足夠時,後者能提供更大的吞吐率,更細粒度的冗餘備份,更快速的單盤故障恢復。
7.分配合適的內存給RegionServer服務
在不影響其他服務的情況下,越大越好。例如在 HBase 的 conf 目錄下的 hbase-env.sh 的最後添加 export HBASE_REGIONSERVER_OPTS="-Xmx16000m$HBASE_REGIONSERVER_OPTS」
其中 16000m 為分配給 RegionServer 的內存大小。
8.寫數據的備份數
備份數與讀性能成正比,與寫性能成反比,且備份數影響高可用性。有兩種配置方式,一種是將 hdfs-site.xml拷貝到 hbase 的 conf 目錄下,然後在其中添加或修改配置項 dfs.replication 的值為要設置的備份數,這種修改對所有的 HBase 用戶表都生效,另外一種方式,是改寫 HBase 代碼,讓 HBase 支持針對列族設置備份數,在創建表時,設置列族備份數,默認為 3,此種備份數只對設置的列族生效。
9.WAL(預寫日誌)
可設置開關,表示 HBase 在寫數據前用不用先寫日誌,默認是打開,關掉會提高性能,但是如果系統出現故障(負責插入的 RegionServer 掛掉),數據可能會丟失。配置 WAL 在調用 JavaAPI 寫入時,設置 Put 實例的WAL,調用 Put.setWriteToWAL(boolean)。
10. 批量寫
HBase 的 Put 支持單條插入,也支持批量插入,一般來說批量寫更快,節省來回的網路開銷。在客戶端調用JavaAPI 時,先將批量的 Put 放入一個 Put 列表,然後調用 HTable 的 Put(Put 列表) 函數來批量寫。
11. 客戶端一次從伺服器拉取的數量
通過配置一次拉去的較大的數據量可以減少客戶端獲取數據的時間,但是它會佔用客戶端內存。有三個地方可進行配置:
1)在 HBase 的 conf 配置文件中進行配置 hbase.client.scanner.caching;
2)通過調用HTable.setScannerCaching(intscannerCaching) 進行配置;
3)通過調用Scan.setCaching(intcaching) 進行配置。三者的優先順序越來越高。
12. RegionServer的請求處理I/O線程數
較少的 IO 線程適用於處理單次請求內存消耗較高的 Big Put 場景 (大容量單次 Put 或設置了較大 cache 的Scan,均屬於 Big Put) 或 ReigonServer 的內存比較緊張的場景。
較多的 IO 線程,適用於單次請求內存消耗低,TPS 要求 (每秒事務處理量 (TransactionPerSecond)) 非常高的場景。設置該值的時候,以監控內存為主要參考。
在 hbase-site.xml 配置文件中配置項為 hbase.regionserver.handler.count。
13. Region的大小設置
配置項為 hbase.hregion.max.filesize,所屬配置文件為 hbase-site.xml.,默認大小 256M。
在當前 ReigonServer 上單個 Reigon 的最大存儲空間,單個 Region 超過該值時,這個 Region 會被自動 split成更小的 Region。小 Region 對 split 和 compaction 友好,因為拆分 Region 或 compact 小 Region 里的StoreFile 速度很快,內存佔用低。缺點是 split 和 compaction 會很頻繁,特別是數量較多的小 Region 不停地split, compaction,會導致集群響應時間波動很大,Region 數量太多不僅給管理上帶來麻煩,甚至會引發一些Hbase 的 bug。一般 512M 以下的都算小 Region。大 Region 則不太適合經常 split 和 compaction,因為做一次 compact 和 split 會產生較長時間的停頓,對應用的讀寫性能衝擊非常大。
此外,大 Region 意味著較大的 StoreFile,compaction 時對內存也是一個挑戰。如果你的應用場景中,某個時間點的訪問量較低,那麼在此時做 compact 和 split,既能順利完成 split 和 compaction,又能保證絕大多數時間平穩的讀寫性能。compaction 是無法避免的,split 可以從自動調整為手動。只要通過將這個參數值調大到某個很難達到的值,比如 100G,就可以間接禁用自動 split(RegionServer 不會對未到達 100G 的 Region 做split)。再配合 RegionSplitter 這個工具,在需要 split 時,手動 split。手動 split 在靈活性和穩定性上比起自動split 要高很多,而且管理成本增加不多,比較推薦 online 實時系統使用。內存方面,小 Region 在設置memstore 的大小值上比較靈活,大 Region 則過大過小都不行,過大會導致 flush 時 app 的 IO wait 增高,過小則因 StoreFile 過多影響讀性能。
14.操作系統參數
Linux系統最大可打開文件數一般默認的參數值是1024,如果你不進行修改並發量上來的時候會出現「Too Many Open Files」的錯誤,導致整個HBase不可運行,你可以用ulimit -n 命令進行修改,或者修改/etc/security/limits.conf和/proc/sys/fs/file-max 的參數,具體如何修改可以去Google 關鍵字 「linux limits.conf 」
15.Jvm配置
修改 hbase-env.sh 文件中的配置參數,根據你的機器硬體和當前操作系統的JVM(32/64位)配置適當的參數
HBASE_HEAPSIZE 4000 HBase使用的 JVM 堆的大小
HBASE_OPTS "‐server ‐XX:+UseConcMarkSweepGC"JVM GC 選項
HBASE_MANAGES_ZKfalse 是否使用Zookeeper進行分散式管理
16. 持久化
重啟操作系統後HBase中數據全無,你可以不做任何修改的情況下,創建一張表,寫一條數據進行,然後將機器重啟,重啟後你再進入HBase的shell中使用 list 命令查看當前所存在的表,一個都沒有了。是不是很杯具?沒有關係你可以在hbase/conf/hbase-default.xml中設置hbase.rootdir的值,來設置文件的保存位置指定一個文件夾,例如:file:///you/hbase-data/path,你建立的HBase中的表和數據就直接寫到了你的磁碟上,同樣你也可以指定你的分散式文件系統HDFS的路徑例如:hdfs://NAMENODE_SERVER:PORT/HBASE_ROOTDIR,這樣就寫到了你的分散式文件系統上了。
17. 緩衝區大小
hbase.client.write.buffer
這個參數可以設置寫入數據緩衝區的大小,當客戶端和伺服器端傳輸數據,伺服器為了提高系統運行性能開闢一個寫的緩衝區來處理它,這個參數設置如果設置的大了,將會對系統的內存有一定的要求,直接影響系統的性能。
18. 掃描目錄表
hbase.master.meta.thread.rescanfrequency
定義多長時間HMaster對系統表 root 和 meta 掃描一次,這個參數可以設置的長一些,降低系統的能耗。
19. split/compaction時間間隔
hbase.regionserver.thread.splitcompactcheckfrequency
這個參數是表示多久去RegionServer伺服器運行一次split/compaction的時間間隔,當然split之前會先進行一個compact操作.這個compact操作可能是minorcompact也可能是major compact.compact後,會從所有的Store下的所有StoreFile文件最大的那個取midkey.這個midkey可能並不處於全部數據的mid中.一個row-key的下面的數據可能會跨不同的HRegion。
20. 緩存在JVM堆中分配的百分比
hfile.block.cache.size
指定HFile/StoreFile 緩存在JVM堆中分配的百分比,默認值是0.2,意思就是20%,而如果你設置成0,就表示對該選項屏蔽。
21. ZooKeeper客戶端同時訪問的並發連接數
hbase.zookeeper.property.maxClientCnxns
這項配置的選項就是從zookeeper中來的,表示ZooKeeper客戶端同時訪問的並發連接數,ZooKeeper對於HBase來說就是一個入口這個參數的值可以適當放大些。
22. memstores佔用堆的大小參數配置
hbase.regionserver.global.memstore.upperLimit
在RegionServer中所有memstores佔用堆的大小參數配置,默認值是0.4,表示40%,如果設置為0,就是對選項進行屏蔽。
23. Memstore中緩存寫入大小
hbase.hregion.memstore.flush.size
Memstore中緩存的內容超過配置的範圍後將會寫到磁碟上,例如:刪除操作是先寫入MemStore里做個標記,指示那個value, column 或 family等下是要刪除的,HBase會定期對存儲文件做一個major compaction,在那時HBase會把MemStore刷入一個新的HFile存儲文件中。如果在一定時間範圍內沒有做major compaction,而Memstore中超出的範圍就寫入磁碟上了。
推薦閱讀:
※大數據之 Hadoop 的資料庫 HBase 的架構的詳細講解
※怎麼看hadoop的源碼,求大神指教?
※5-Hbase Rowkey設計
※mongodb,redis,hbase 三者都是nosql資料庫,他們的最大區別和不同定位是什麼?
※region HFile DataNode 三者的區別與關係?
TAG:HBase |