HBase的regionServer

RegionServer核心模块

RegionServer后面简称rs,是比较核心的模块,数据写入读取的基础组件。rs包含HLog,MemStore,HFile和BlockCache。

1. RS内部结构

在这里插入图片描述
HLog用来保证数据写入的可靠性,BlockCache读缓存,一个strore是一个列族,memstore是写缓存,数据达到阈值直接落盘HFile, HFile按照rowkey排序,文件之间异步会进行多路归并(LSM结构)。

1.1 HLog

所有写操作先追加写入HLog再写入memstore。rs挂了,memstore是内存里面的concurrentSkipMap,数据直接就没了,HLog是落在HDFS的,可以用来数据恢复。

在这里插入图片描述
Hlog是多个region共享的,日志每个单元是行级更新单元,HLogKey+WALEdit。HLogKey由表名,region,sequenceId,时间等信息组成
在这里插入图片描述
HLog生命周期:构建 -> 滚动新建->(mem flush后)失效移到oldWAL-> oldWAL下面文件过了TTL删除。

sequenceID干啥用的?

每个region的操作都顺序自增sequenceID,存在了HLogKey里面,sequenceID操作flush到hfile后会有标记,还没flush的操作序号最小的变成oldestUnflushedSequenceId,当一个Hlog里面所有的region,sequceID都小于相应的oldestUnflushedSequenceId,说明这个HLog可以删掉了。同理rs挂了,每个region从相应的oldestUnflushedSequenceId开始恢复

1.2 Memstore

rs里面每个列族一个memstore,memstore刷写的这种lsm结构有如下优点

  • 随机io写入变成顺序io写入(写HLog) + 内存写入,写入性能好
  • HFile排序在memstore完成,直接刷写
  • memstore缓存最新写入数据,直接内存读取的概率更大
  • memstore刷写前可以灵活处理KV,比如只保留一版数据,memstore里的老版本直接干掉

memstore高效读写,用concurrentSkipMap,在O(logN)时间复杂度完成增删查。底层采用CAS原子操作,提升性能。

memstore的GC问题,多个region的memtore共用rs的内存,比如下图region 1落盘以后产生的白色部分会继续写入,长时间后,条带越来越窄,甚至无法分配足够内存出来给大的对象,触发Full GC
在这里插入图片描述
这里memstore使用了顺序化内存分配,内存数据分块等使得碎片更加粗粒度。
每个memstore申请一个2M的chunk数组同时维护偏移量,kv来了就放进去同时偏移量移动kv.length,不够用了就申请下一个chunk,每个2MB都是由一个memstore里面的对象填充,这个据官方实验降低了full GC的频率。
在这里插入图片描述
chunk循环利用也可以避免jvm回收chunk(kafka生产者的内存池也是这个思路),因此

  1. 创建chunkpool管理未使用的chunk,防止回收
  2. chunk没有使用就进入pool
  3. chunkpool有一定大小限制,如果还有余力就会分配新增的chunk需求

chunk大小默认是2MB,开启的。chunkpool需要自己开启。

1.3 HFile

在这里插入图片描述

  • scanned block : 顺序扫描的地方,存储数据的地方,leaf index block是索引书叶子节点,bloomblock是布隆过滤器
  • non-scanned block : 顺序扫描不会扫到的地方
  • load on open : 打开hfile时候加载到内存,各种元数据
  • trailer : 记录了偏移值

每种block都有blockheader和blockdata

block有8种
在这里插入图片描述

1.3.1 trailer block

这个部分似曾相识,orc结构也是这样。这种块大小是固定的。加载后解析出hfile的压缩算法,kv数量等信息,load-on-open部分的偏移量并根据偏移量加载。
在这里插入图片描述

1.3.2 Data Block

在这里插入图片描述
rowkey结构前面说过了,hbase排序的依据。从这可以看出,rowkey,列族,列等在每条数据都占用了位置,因此越短越好。

1.3.3 bloomblock

lsm特性,hbase写性能好,读差点,因此每个hfile都整一个布隆过滤器,加载到内存,滤过一些无结果rowkey查询。新版本hbase把布隆过滤器页拆分了,多个bloom block 按照 bloom index block进行拆分

在这里插入图片描述
bloom index block结构,先根据rowkey二分查找定位相应bloom block,再根据offset和szie搞到bloom block。 bloom index block的元信息包括hash函数的信息。

1.3.4 HFile的多级索引

在这里插入图片描述
随着数据量增多,hfile的索引会由一层变为二层三层。

在这里插入图片描述
上图最根上的是root index clock,Mid开头的记录MidKey用以切分HFile。index entry里面有index的第一个key

在这里插入图片描述
上图Nonroot index clock,entry偏移量记了,所以可以用二分法找index entry

hbase hfile -m   /hbase/data/default/extra_info/1fe15081622f29d8050e9852e946d480/info/84f397d181aa45dea740f733a94c4e1c
Java HotSpot(TM) 64-Bit Server VM warning: Using incremental CMS is deprecated and will likely be removed in a future release
22/02/22 21:22:12 WARN impl.MetricsConfig: Cannot locate configuration: tried hadoop-metrics2-hbase.properties,hadoop-metrics2.properties
22/02/22 21:22:12 INFO impl.MetricsSystemImpl: Scheduled Metric snapshot period at 10 second(s).
22/02/22 21:22:12 INFO impl.MetricsSystemImpl: HBase metrics system started
22/02/22 21:22:12 INFO metrics.MetricRegistries: Loaded MetricRegistries class org.apache.hadoop.hbase.metrics.impl.MetricRegistriesImpl
Block index size as per heapsize: 229024
reader=/hbase/data/default/extra_info/1fe15081622f29d8050e9852e946d480/info/84f397d181aa45dea740f733a94c4e1c,
    compression=none,
    cacheConf=CacheConfig:disabled,
    firstKey=Optional[001OI202010144774496580667441152/info:create_time/1639475327647/Put/seqid=0],
    lastKey=Optional[002OI202110305906839144627429376/info:user_name/1639475328280/Put/seqid=0],
    avgKeyLen=57,
    avgValueLen=10,
    entries=1565507,
    length=120660499
Trailer:
    fileinfoOffset=120655695,
    loadOnOpenDataOffset=120546138,
    dataIndexCount=1833,
    metaIndexCount=0,
    totalUncomressedBytes=120514235,
    entryCount=1565507,
    compressionCodec=NONE,
    uncompressedDataIndexSize=109459,
    numDataIndexLevels=1,
    firstDataBlockOffset=0,
    lastDataBlockOffset=120486953,
    comparatorClassName=org.apache.hadoop.hbase.CellComparatorImpl,
    encryptionKey=NONE,
    majorVersion=3,
    minorVersion=3
Fileinfo:
    BLOOM_FILTER_TYPE = ROW
    DELETE_FAMILY_COUNT = 0
    EARLIEST_PUT_TS = 1639475327646
    KEY_VALUE_VERSION = 1
    LAST_BLOOM_KEY = 002OI202110305906839144627429376
    MAJOR_COMPACTION_KEY = true
    MAX_MEMSTORE_TS_KEY = 0
    MAX_SEQ_ID_KEY = 858
    TIMERANGE = 1639475327646....1639475331337
    hfile.AVG_KEY_LEN = 57
    hfile.AVG_VALUE_LEN = 10
    hfile.CREATE_TIME_TS = 1639933791744
    hfile.LASTKEY = 002OI202110305906839144627429376/info:user_name/1639475328280/Put/vlen=0/mvcc=0
Mid-key: Optional[001OI202109225792116//LATEST_TIMESTAMP/Maximum/seqid=0]
Bloom filter:
    BloomSize: 270336
    No of Keys in bloom: 223644
    Max Keys for bloom: 225443
    Percentage filled: 99%
    Number of chunks: 3
    Comparator: ByteArrayComparator

avgKeyLen和avgValueLen代表kv长度,由于block(64KB内部)是顺序读,因此kv长度很小block就会装很多影响性能,这种情况要把blocksize设小点。

1.4 blockcache

提升读性能一般是将热点数据缓存。hbase读缓存blockcache,每个re一个blockcache,每次读先去blockcache找,没有去hfile找,找得到数据所在的block缓存起来。有三种:默认LRUBlockCache,SlabCache,BucketCache

  • LRUBlockCache
    ConcurrentHashMap,key是BlockKey,v 是block。总量达到阈值就会淘汰是用最少的block。HBase采用多层缓存设计。建表时候可以指定列簇in_memory,但是要谨慎,如果太大了会影响元数据(hbase:meta,hbase:namespace都在内存中)。每层使用最少的block都会被淘汰。JVM自身的内存管理会产生碎片。

  • slabcache和BucketCache
    都是自己管理block,是用新block覆盖旧的,省得JVM自己去回收。但是slabcache是固定两种大小,LRUBlockCache是十几种大小的bucket而且可以互相借用空间。

hbase现在是LRUBlockCache + BucketCache, 前者放index block和bloom block,后者放datablock

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值