Sparkhbase

Hbase——运行原理

2023-03-22  本文已影响0人  小波同学

一、Hbase的架构

架构角色

数据存储角色

每个RegionServer 可以服务多个Region,每个RegionServer中有多个Store、1个WAL,和1个BlockCache,每个Store对应一个列族,包含MemStore 和 StoreFile.

二、hbase 写数据流程

说明:写入数据时,逻辑顺序是先写入到WAL(HLog),再写入memStore,但实际源码流程如下:使用事务回滚机制来确保WAL和memStore同步写入。

MemStore刷写(flush)

自动触发机制:HBase 2.0之前参数

第一种触发条件:(Region级别Flush)

<!-- 单个region里memstore的缓存大小,超过那么整个HRegion就会flush,默认128M -->  
<property>  
    <name>hbase.hregion.memstore.flush.size</name>  
    <value>134217728</value>  
    <description>  
        Memstore will be flushed to disk if size of the memstore  
        exceeds this number of bytes. Value is checked by a thread that runs  
        every hbase.server.thread.wakefrequency.  
    </description>  
</property>

<!-- 当一个HRegion上的memstore的大小满足hbase.hregion.memstore.block.multiplier *   
hbase.hregion.memstore.flush.size, 这个HRegion会执行flush操作并阻塞对该HRegion的写入 -->  
<property>  
    <name>hbase.hregion.memstore.block.multiplier</name> 
    <value>4</value>  
    <description>  
        Block updates if memstore has hbase.hregion.memstore.block.multiplier  
        times hbase.hregion.memstore.flush.size bytes. Useful preventing  
        runaway memstore during spikes in update traffic. Without an  
        upper-bound, memstore fills such that when it flushes the  
        resultant flush files take a long time to compact or split, or  
        worse, we OOME.  
    </description>  
</property>

第二种触发条件:(RegionServer级别Flush)

<!-- regionServer的全局memstore的大小,超过该大小会触发flush到磁盘的操作,默认是堆大小的40%,而且regionserver级别的   
flush会阻塞客户端读写。如果RegionServer的堆内存设置为2G,则memstore总内存大小为 2 * 0.4 = 0.8G-->  
<property>  
    <name>hbase.regionserver.global.memstore.size</name>  
    <value></value>  
    <description>Maximum size of all memstores in a region server before  
        new  
        updates are blocked and flushes are forced. Defaults to 40% of heap (0.4).  
        Updates are blocked and flushes are forced until size of all  
        memstores  
        in a region server hits  
        hbase.regionserver.global.memstore.size.lower.limit.  
        The default value in this configuration has been intentionally left  
        emtpy in order to  
        honor the old hbase.regionserver.global.memstore.upperLimit property if  
        present.  
    </description>  
</property> 

<!--可以理解为一个安全的设置,有时候集群的“写负载”非常高,写入量一直超过flush的量,这时,我们就希望memstore不要超过一定的安全设置。   
    在这种情况下,写操作就要被阻塞一直到memstore恢复到一个“可管理”的大小, 这个大小就是默认值是堆大小 * 0.4 * 0.95,也就是当regionserver级别   
    的flush操作发送后,会阻塞客户端写,一直阻塞到整个regionserver级别的memstore的大小为 堆大小 * 0.4 *0.95为止 -->  
<property>  
    <name>hbase.regionserver.global.memstore.size.lower.limit</name>  
    <value></value>  
    <description>Maximum size of all memstores in a region server before  
        flushes are forced.  
        Defaults to 95% of hbase.regionserver.global.memstore.size (0.95).  
        A 100% value for this value causes the minimum possible flushing to  
        occur when updates are  
        blocked due to memstore limiting.  
        The default value in this configuration has been intentionally left  
        emtpy in order to  
        honor the old hbase.regionserver.global.memstore.lowerLimit property if  
        present.  
    </description>  
</property>

第三种触发条件:(RegionServer级别Flush)

第四种触发条件:(Region级别Flush)

#region的memstore的触发
#判断如果某个region中的某个memstore达到这个阈值,那么触发flush,flush这个region的所有memstore
hbase.hregion.memstore.flush.size=128M

#region的触发级别:如果没有memstore达到128,但是所有memstore的大小加在一起大于等于128*4
#触发整个region的flush
hbase.hregion.memstore.block.multiplier=4

#regionserver的触发级别:所有region所占用的memstore达到阈值,就会触发整个regionserver中memstore的溢写
#从memstore占用最多的Regin开始flush
hbase.regionserver.global.memstore.size=0.4 --RegionServer中Memstore的总大小

#低于水位后停止
hbase.regionserver.global.memstore.size.upper.limit=0.99
hbase.regionserver.global.memstore.size.lower.limit = 0.4*0.95 =0.38

自动触发机制:HBase 2.0之后

#设置了一个flush的最小阈值
#memstore的判断发生了改变:max("hbase.hregion.memstore.flush.size / column_family_number",hbase.hregion.percolumnfamilyflush.size.lower.bound.min)
#如果memstore高于上面这个结果,就会被flush,如果低于这个值,就不flush,如果整个region所有的memstore都低于,全部flush
#水位线 = max(128 / 列族个数,16),列族一般给3个 ~ 42M
#如果memstore的空间大于42,就flush,如果小于就不flush;如果都小于,全部flush

举例:3个列族,3个memstore, 90/30/30   90会被Flush

举例:3个列族,3个memstore, 30/30/30   全部flush

hbase.hregion.percolumnfamilyflush.size.lower.bound.min=16M

# 2.x中多了一种机制:In-Memory-compact,如果开启了【不为none】,会在内存中对需要flush的数据进行合并
#合并后再进行flush,将多个小文件在内存中合并后再flush
hbase.hregion.compacting.memstore.type=none|basic|eager|adaptive

关于相关参数的说明和调整建议:

如: 列族      CF1      CF2      CF3
                              100M      1K        5K
全局Flush时,对于CF2和CF3会生成2个小文件。但是也可以使用多个列族,尽量保证数据均匀就好。

三、hbase 读数据流程

细节


Block Cache

HBase 在实现中提供了两种缓存结构 MemStore(写缓存) 和 BlockCache(读缓存)。写缓存前面说过不再重复。

重点

读数据时不要理解为先从 MemStore 中读取,读不到再读 BlockCache 中,还读不到再从HFile中读取,然后将数据写入到 BlockCache 中。因为如果人为设置导致磁盘数据new,内存数据old。你读取的时候会出错的!

结论

HBase 把磁盘跟内存数据一起读,然后把磁盘数据放到 BlockCache中,BlockCache 是磁盘数据的缓存。HBase 是个读比写慢的工具。

四、StoreFile合并(Compaction)

# 2.0版本之前,只有StoreFile文件的合并
磁盘中合并:minor compaction、major compaction
  
# 2.0版本开始,内存中的数据也可以先合并后Flush
内存中合并:In-memory compaction
磁盘中合并:minor compaction、major compaction

Minor Compaction :轻量级

minor compact文件选择标准由以下几个参数共同决定

<!--待合并文件数据必须大于等于下面这个值-->
<property>
    <name>hbase.hstore.compaction.min</name>
    <value>3</value>
</property>
<!--待合并文件数据必须小于等于下面这个值-->
<property>
    <name>hbase.hstore.compaction.max</name>
    <value>10</value>
</property>
<!--默认值为128m,
表示文件大小小于该值的store file 一定会加入到minor compaction的store file中
-->
<property>
    <name>hbase.hstore.compaction.min.size</name>
    <value>134217728</value>
</property>
<!--默认值为LONG.MAX_VALUE,
表示文件大小大于该值的store file 一定会被minor compaction排除-->
<property>
    <name>hbase.hstore.compaction.max.size</name>
    <value>9223372036854775807</value>
</property>

Major Compaction :重量级合并

In-memory compaction

禁用自动合并,使用手动处理:

Compact all regions in a table:
hbase> major_compact 't1'
hbase> major_compact 'ns1:t1'

Compact an entire region:
hbase> major_compact 'r1'
          
Compact a single column family within a region:
hbase> major_compact 'r1', 'c1'

Compaction 触发时机:

概括的说,HBase 会在三种情况下检查是否要触发 Compaction,分别是 MemStore Flush、后台线程周期性检查、手动触发。

Compaction 核心参数:

hbase.hstore.compaction.min

hbase.hstore.compaction.max

hbase.regionserver.thread.compaction.throttle

hbase.regionserver.thread.compaction.large/small

hbase.hstore.blockingStoreFiles

<!-- 每个store阻塞更新请求的阀值,表示如果当前hstore中文件数大于该值,系统将会强制执行compaction操作进行文件合并, 
    合并的过程会阻塞整个hstore的写入,这样有个好处是避免compaction操作赶不上Hfile文件的生成速率 -->  
<property>  
    <name>hbase.hstore.blockingStoreFiles</name>  
    <value>10</value>  
    <description>  
        If more than this number of StoreFiles in any one Store  
        (one StoreFile is written per flush of MemStore) then updates are  
        blocked for this HRegion until a compaction is completed, or  
        until hbase.hstore.blockingWaitTime has been exceeded.  
    </description>  
</property>

默认值 10,表示一个 Store 中 HFile 文件数量达到该值就会阻塞写入,等待 Compaction 的完成。一般建议调大点,比如设置为 100,避免出现阻塞更新的情况,阻塞日志如下:

too many store files; delaying flush up to 90000ms

生产环境建议认真根据实际业务量做好集群规模评估,如果小集群遇到了持续写入过快的场景,合理扩展集群也非常重要。

五、数据切分(Split)

默认情况下,每个 Table 起初只有一个 Region,随着数据的不断写入,Region 会自动进行拆分。刚拆分时,两个子 Region 都位于当前的 Region Server,但处于负载均衡的考虑,HMaster 有可能会将某个 Region 转移给其他的 Region Server。

Region Split 时机

数据切分会造成数据倾斜(region 大小分布不均),带来热点数据问题。所以建表时进行预分区来尽量避免这种问题。

关闭自动分裂,手动执行

split 'tableName'
split 'namespace:tableName'

split 'regionName' # format: 'tableName,startKey,id'

split 'tableName', 'splitKey'

split 'regionName', 'splitKey'

六、被删除数据(打了 Delete 标记的数据)的清除时机

被删除数据会在两种操作中被清除:

为什么 Flush 不清除 Delete 标记?
因为 Flush 只能清除 memStore 中的数据,还要留着 Delete 标记供 major compact 合并时去清除其他 StoreFile 中的数据。

七、Hbase优化

RowKey设计

内存优化

压缩机制

布隆过滤

环境优化

参考:
https://www.cnblogs.com/wdh01/p/16283244.html

https://blog.csdn.net/qq_33208851/article/details/105223419

https://blog.csdn.net/weixin_44133605/article/details/124635627

https://www.cnblogs.com/baran/p/15629009.html

https://www.cnblogs.com/sx66/p/13425465.html

https://blog.csdn.net/zfw_666666/article/details/126627977

https://blog.csdn.net/llAl_lAll/article/details/122260638

https://blog.csdn.net/weixin_48370579/article/details/125802173

https://www.cnblogs.com/jing-yi/p/15534775.html

https://blog.csdn.net/nmsLLCSDN/article/details/124088245

上一篇下一篇

猜你喜欢

热点阅读