hbase 查询固定条数_HBase原理深入
HBase讀數(shù)據(jù)流程
HBase讀數(shù)據(jù)流程.pngHBase元數(shù)據(jù)信息.pngHBase讀操作
首先從zk中找到meta表的region信息,然后meta表中的數(shù)據(jù),meta表中存儲了用戶的region信息
根據(jù)要查詢的namespace、表名和rowkey信息,找到對應(yīng)的真正存儲要查詢的數(shù)據(jù)的region信息
找到這個region對應(yīng)的regionServer,然后發(fā)送請求
查找對應(yīng)的region
先從metastore查找數(shù)據(jù),如果沒有,再從BlockCache讀取。
HBase上的RegionServer的內(nèi)存分為兩個部分
一部分作為Memstore,主要用來寫
另一部分作為BlockCache,主要用來讀數(shù)據(jù)
如果BlockCache中也沒有找到,再到StoreFile上進(jìn)行讀取
從storeFile中讀取到數(shù)據(jù)之后,不是直接把結(jié)果數(shù)據(jù)返回給客戶端, 而是把數(shù)據(jù)先寫?入到BlockCache中,目的是為了加快后續(xù)的查詢;然后在返回結(jié)果給客戶端。
HBase寫數(shù)據(jù)流程
HBase寫數(shù)據(jù)流程.pngHBase寫操作
首先從zk找到meta表的region位置,然后讀取meta表中的數(shù)據(jù),meta表中存儲了用戶表的region信息
根據(jù)要查詢的namespace、表名和rowkey信息,找到對應(yīng)的真正存儲要查詢的數(shù)據(jù)的region信息
找到這個region對應(yīng)的regionServer,然后發(fā)送請求
把數(shù)據(jù)寫到HLog(write ahead log。WAL:預(yù)寫入日志)和memstore各一份(寫到Region里列族對應(yīng)的Store的內(nèi)存)
Memstore 達(dá)到閾值后把數(shù)據(jù)刷到磁盤,生產(chǎn)storeFile
刪除HLog中的歷史數(shù)據(jù)
HBase的flush(刷寫)及compact(合并)機(jī)制
Flush機(jī)制
當(dāng)memstore的大小超過這個值的時候會flush到磁盤,默認(rèn)是128M
<property>
<name>hbase.hregion.memstore.flush.sizename>
<value>134217728value>
property>當(dāng)memstore中的數(shù)據(jù)時間超過1小時,會flush到磁盤
<property>
<name>hbase.regionserver.optionalcacheflushintervalname
<value>3600000value>
property>Hregion的所有的memstore的大小(一個RegionServer會有多個Region,一個Region會有多個store,也就有多個memstore),所有的memstore的大小超過堆大小的一定比例會觸發(fā)flush到磁盤的操作,默認(rèn)是堆大小的40%
<property>
<name>hbase.regionserver.global.memstore.sizename>
<value>0.4value>
property>手動flush
flush?tableName
阻塞機(jī)制
以上介紹的是Store中memstore數(shù)據(jù)刷寫磁盤的標(biāo)準(zhǔn),但是Hbase中是周期性(定時,默認(rèn)是10S)的檢查是否滿足以上標(biāo)準(zhǔn),滿?則進(jìn)?刷寫,但是如果在下次檢查到來之前,數(shù)據(jù)瘋狂寫入Memstore中,會出現(xiàn)什什么問題呢?
會觸發(fā)阻塞機(jī)制,此時無法寫?數(shù)據(jù)到Memstore,數(shù)據(jù)無法寫入Hbase集群。
memstore中數(shù)據(jù)達(dá)到512MB
計算公式:hbase.hregion.memstore.flush.size*hbase.hregion.memstore.block.multiplier
hbase.hregion.memstore.flush.size刷寫的閥值,默認(rèn)是 134217728,即128MB
hbase.hregion.memstore.block.multiplier是一個倍數(shù),默認(rèn)是4。
RegionServer全部memstore達(dá)到規(guī)定值
hbase.regionserver.global.memstore.size.lower.limit是0.95
hbase.regionserver.global.memstore.size是0.4,
堆內(nèi)存總共是 16G,
觸發(fā)刷寫的閾值是:(0.95 * 0.4 * 16) = 6.08GB
觸發(fā)阻塞的閾值是:(0.4 * 16) = 6.4GB
當(dāng)發(fā)生阻塞的時候,無法寫入HBase,那么如何解決?
調(diào)大memstore的hbase.hregion.memstore.flush.size內(nèi)存大小設(shè)置
讓RegionServer占有JVM堆大小更多一些
Compact合并機(jī)制
合并的原因:減少文件的數(shù)量,提高查詢的時候掃描的性能
在HBase中主要存在兩種類型的Compact合并
minor compact ?合并
會將Store中多個HFile(StoreFile)合并成一個大的HFile(默認(rèn)最少3個,最多10個)
這個過程中,刪除和更新的數(shù)據(jù)僅只是做了標(biāo)記,并沒有物理移除,這種合并的觸發(fā)頻率很高。
minor compact?件選擇標(biāo)準(zhǔn)由以下?個參數(shù)共同決定:
<property>
????<name>hbase.hstore.compaction.minname>
????<value>3value>
property>
<property>
????<name>hbase.hstore.compaction.maxname>
????<value>10value>
property>
<property>
????<name>hbase.hstore.compaction.min.sizename>
????<value>134217728value>
property>
<property>
????<name>hbase.hstore.compaction.max.sizename>
????<value>9223372036854775807value>
property>觸發(fā)條件
memstore flush
在進(jìn)行memstore flush前后都會進(jìn)行判斷是否觸發(fā)compact
定期檢查線程
周期性檢查是否需要進(jìn)行compaction操作,由參數(shù):hbase.server.thread.wakefrequency決定,默認(rèn)值是10000 millseconds
major compact 大合并
合并Store中所有的HFile為一個HFile
這個過程有刪除標(biāo)記的數(shù)據(jù)會被真正移除,同時超過單元格maxVersion的版本記錄也會被刪除。合并頻率?較低,默認(rèn)7天執(zhí)??次,并且性能消耗非常大,建議?產(chǎn)關(guān)閉(設(shè)置為0),在應(yīng)用空閑時間手動觸發(fā)。?般可以是手動控制進(jìn)行合并,防?出現(xiàn)在業(yè)務(wù)高峰期。
major compaction觸發(fā)時間條件
<property>
????<name>hbase.hregion.majorcompactionname>
????<value>604800000value>
property>手動觸發(fā)
##使?major_compact命令
major_compact?tableName
Region拆分機(jī)制
Region中存儲的是?量的rowkey數(shù)據(jù) ,當(dāng)Region中的數(shù)據(jù)條數(shù)過多的時候,直接影響查詢效率.當(dāng)Region過大的時候.HBase會拆分Region , 這也是Hbase的?個優(yōu)點(diǎn)
Region拆分機(jī)制.png拆分策略
Hbase拆分策略一共有以下幾種:
ConstantSizeRegionSplitPolicy(0.9版本以前默認(rèn)的切分策略。)
當(dāng)region?小?于某個閾值(hbase.hregion.max.filesize=10G)之后就會觸發(fā)切分,一個region等分為2個region。
但是在生產(chǎn)線上這種切分策略卻有相當(dāng)大的弊端:切分策略對于大表和小表沒有明顯的區(qū)分。閾值(hbase.hregion.max.filesize)設(shè)置較大對大表?比較友好,但是小表就有可能不會觸發(fā)分裂,極端情況下可能就1個,這對業(yè)務(wù)來說并不是什么好事。如果設(shè)置較小則對?表友好,但一個大表就會在整個集群產(chǎn)?大量的region,這對于集群的管理、資源使用、failover來說都不是一件好事。
IncreasingToUpperBoundRegionSplitPolicy(0.94版本~2.0版本默認(rèn)切分策略)
切分策略稍微有點(diǎn)復(fù)雜,總體看和ConstantSizeRegionSplitPolicy思路相同,一個region?小?于設(shè)置閾值就會觸發(fā)切分。但是這個閾值并不像 ConstantSizeRegionSplitPolicy是一個固定的值,而是會在一定條件下不斷調(diào)整,調(diào)整規(guī)則和region所屬表在當(dāng)前regionserver上的region個數(shù)有關(guān)系.
region split的計算公式是:
regioncount^3 * 128M * 2,當(dāng)region達(dá)到該size的時候進(jìn)?split 例如:
第一次split:1^3 * 256 = 256MB
第二次split:2^3 * 256 = 2048MB
第三次split:3^3 * 256 = 6912MB
第四次split:4^3 * 256 = 16384MB > 10GB,因此取較?的值10GB 后面每次split的size都是10GB了
SteppingSplitPolicy(2.0版本默認(rèn)切分策略略)
這種切分策略的切分閾值?發(fā)生了變化,相比 IncreasingToUpperBoundRegionSplitPolicy 簡單了一些,依然和待分裂region所屬表在當(dāng)前 regionserver上的region個數(shù)有關(guān)系,如果region個數(shù)等于1,切分閾值為flush size(默認(rèn)128M) * 2,否則為MaxRegionFileSize(10G)。這種切分策略對于?集群中的大表、小表會?比 IncreasingToUpperBoundRegionSplitPolicy 更加友好,?表不不會再產(chǎn)??量的?region,?是適可?止。
KeyPrefixRegionSplitPolicy
根據(jù)rowKey的前綴對數(shù)據(jù)進(jìn)行分組,這里是指定rowKey的前多少位作為前綴,?如rowKey都是16位的,指定前5位是前綴,那么前5位相同的rowKey在進(jìn)?region split的時候會分到相同的region中。
DelimitedKeyPrefixRegionSplitPolicy
保證相同前綴的數(shù)據(jù)在同一個region中,例如rowKey的格式為:userid_eventtype_eventid,指定的delimiter為 _ ,則split的的時候會確保userid 相同的數(shù)據(jù)在同一個region中。
DisabledRegionSplitPolicy
不啟用?動拆分, 需要指定?動拆分
RegionSplitPolicy的應(yīng)?
Region拆分策略可以全局統(tǒng)一配置,也可以為單獨(dú)的表指定拆分策略。
通過hbase-site.xml全局統(tǒng)一配置(對hbase所有表生效)
<property><name>hbase.regionserver.region.split.policyname>
<value>org.apache.hadoop.hbase.regionserver.IncreasingToUpperBoundRegionSplitPolicyvalue>
property>
通過Java API為單獨(dú)的表指定Region拆分策略
HTableDescriptor?tableDesc?=?new?HTableDescriptor("test1");?tableDesc.setValue(HTableDescriptor.SPLIT_POLICY,?IncreasingToUpperBoundRegionSplitPolicy.class.getName());?tableDesc.addFamily(new?HColumnDescriptor(Bytes.toBytes("cf1")));admin.createTable(tableDesc);
通過HBase Shell為單個表指定Region拆分策略
create?'test2',?{METADATA?=>?{'SPLIT_POLICY'?=>'org.apache.hadoop.hbase.regionserver.IncreasingToUpperBoundRegionSplitPolicy'}},{NAME?=>?'cf1'}
HBase表的預(yù)分區(qū)
為什么要預(yù)分區(qū)
當(dāng)?個table剛被創(chuàng)建的時候,Hbase默認(rèn)的分配?個region給table。也就是說這個時候,所有的讀寫請求都會訪問到同一個regionServer的同一個region中,這個時候就達(dá)不到負(fù)載均衡的效果了,集群中的其他regionServer就可能會處于比較空閑的狀態(tài)。解決這個問題可以用pre-splitting,在創(chuàng)建table的時候就配置好,生成多個 region。
增加數(shù)據(jù)讀寫效率
負(fù)載均衡,防?數(shù)據(jù)傾斜
?便集群容災(zāi)調(diào)度region
每?個region維護(hù)著startRow與endRowKey,如果加入的數(shù)據(jù)符合某個region維護(hù)的rowKey范圍,則該數(shù)據(jù)交給這個region維護(hù)
手動指定預(yù)分區(qū)
create?'person','info1','info2',SPLITS?=>?['1000','2000','3000']也可以把分區(qū)規(guī)則創(chuàng)建于文件中
?vim?split.txt文件內(nèi)容
?aaa?bbb
?ccc
?ddd
執(zhí)?
?create?'student','info',SPLITS_FILE?=>?'/root/hbase/split.txt'Region合并
Region合并說明
Region的合并不是為了性能,而是為了出于維護(hù)的目的
如何進(jìn)行Region的合并
通過Merge類冷合并Region
需要先關(guān)閉集群
需求:需要把Student表中的2個Region數(shù)據(jù)進(jìn)行合并
這?通過org.apache.hadoop.hbase.util.Merge類來實(shí)現(xiàn),不需要進(jìn)入hbase shell,直接執(zhí)?(需要先關(guān)閉hbase集群):
hbase?org.apache.hadoop.hbase.util.Merge?student?\?student,,1595256696737.fc3eff4765709e66a8524d3c3ab42d59.?\?student,aaa,1595256696737.1d53d6c1ce0c1bed269b16b6514131d0.
通過online_merge熱合并Region
不需要關(guān)閉集群
與冷合并不同的是,online_merge的傳參是Region的hash值,而Region的hash值就是Region名稱的最后那段在兩個.之間的字符串部分。
需求:需要把lagou_s表中的2個region數(shù)據(jù)進(jìn)行合并:?student,,1587392159085.9ca8689901008946793b8d5fa5898e06.?\?student,aaa,1587392159085.601d5741608cedb677634f8f7257e000.
需要進(jìn)?入hbase?shell:
merge_region?'c8bc666507d9e45523aebaffa88ffdd6','02a9dfdf6ff42ae9f0524a3d8f4c7777'
成功后在觀察頁面
總結(jié)
以上是生活随笔為你收集整理的hbase 查询固定条数_HBase原理深入的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 华夏小羊肖恩亲子信用卡年费多少?怎么免年
- 下一篇: 2021 icme_重磅 | 2021年