HBase基本结构(一) HBase体系结构与RegionServer核心模块

395 阅读6分钟

(1) HBase体系结构与RegionServer核心模块

1. HBase逻辑视图

2. HBase体系结构

2.1. HLog

2.1.1. HLog文件结构

| 1. 每个RegionServer拥有一个或多个HLog。(默认一个,1.1版本可开启MultiWAL功能,允许多个HLog) 2. 每个HLog多个Region共享。 3. 日志单元WALEntry表示一次行级更新的最小追加单元,由HLogKey和WALEdit两部分组成。 4. WALEdit表示一个事务中的更新集合。 0.94之前版本中,如果一个事务对一行rowR三列c1,c2,c3分别做了修改,那么HLog会有3个对应的日志片段,无法保证行级事务的原子性,假如RegionServer更新c2列之后发生宕机,那么一行记录中只有部分数据写入成功: 0.94之后版本,将一个行级事务的写入操作表示为一条记录,其中WALEdit会被序列化为格式<-1, # of edits,,,>:

2.1.2. HLog生命周期

2.2. MemStore

2.2.1. MemStore Flush产生内存条带

| 1. 不同Region的数据在JVM Heap中是混合存储的。 2. Region1执行flush后,该内存被释放,变成Free Space,继续为写入MemStore的数据分配空间,进而分割成更小的条带。 3. 随着MemStore中数据的不断写入并flush,整个JVM将会产生大量越来越小的内存条带,即内存碎片。 4. 随着内存碎片越来越小,最后甚至分配不出来足够大的内存给写入对象,此时会触发JVM执行Full GC合并这些内存碎片。

2.2.2. MSLAB(MemStore本地分配缓存)

| 1. 在RegionServer JVM启动参数中加上-xx:PrintFLASStatistics=1,打印每次GC前后内存碎片的统计信息,统计维度: Free Space – 老年代当前空闲的总内存容量 Max Chunk Size(重点) - 老年代中最大的内存碎片所占的内存容量大小 Num Chunks - 老年代中总的内存碎片数

2.3. HFile

2.3.1. HFile V2逻辑结构图

2.3.2. HFile V2物理结构图

2.3.3. HFile Block

2.3.4. Trailer Block

2.3.5. Data Block

2.3.6. Bloom Index Block

| 一次GET请求,根据布隆过滤器进行过滤查找,步骤: 1)根据待查Key在Bloom Index Block所有的索引项中根据BlockKey进行二分查找,定位对应的Bloom Index Entry; 2)根据Bloom Index Entry中BlockOffset及BlockOndiskSize加载对应的位数组; 3)对Key进行Hash映射,查看位数组相应位置是否为1,不是则表示不存在该Key,否则只是有可能存在该Key。

2.3.7. HFile文件索引

2.3.8. Root Index Block & NoneRoot Index Block

2.3.9. 查看HFile元数据


\# 查看HFile元数据

\# hbase hfile -m -f
/hbase/data/default/mytable/c606b6c02a3f6b51192988432afe38bc/colfam1/e40c31de97ff47aeb27d84a4ca59f7c8

2020-05-20 14:20:59,865 INFO [main] hfile.CacheConfig: Created cacheConfig:

CacheConfig:disabled

Block index size as per heapsize: 392

reader=/hbase/data/default/mytable/c606b6c02a3f6b51192988432afe38bc/colfam1/e40c31de97ff47aeb27d84a4ca59f7c8,

compression=none,

cacheConf=CacheConfig:disabled,

firstKey=r/colfam1:q/1565781611071/Put, \#
在scan时可通过startkey和stopkey优化性能

lastKey=r2/colfam1:q2/1565781667630/Put,

avgKeyLen=22, \#
文件中所有KeyValue的平均Key长度;如果相对较小,可将Block适当调小(如32KB),避免Block内有太多KeyValue数,导致顺序扫描定位KeyValue时会增大块内延迟时间。

avgValueLen=1,

entries=3,

length=4975

Trailer:

fileinfoOffset=289,

loadOnOpenDataOffset=181,

dataIndexCount=1,

metaIndexCount=0,

totalUncomressedBytes=4884,

entryCount=3,

compressionCodec=NONE,

uncompressedDataIndexSize=34,

numDataIndexLevels=1,

firstDataBlockOffset=0,

lastDataBlockOffset=0,

comparatorClassName=org.apache.hadoop.hbase.KeyValue\$KeyComparator,

encryptionKey=NONE,

majorVersion=3,

minorVersion=0

Fileinfo:

BLOOM_FILTER_TYPE = ROW

DELETE_FAMILY_COUNT = 0

EARLIEST_PUT_TS = 1565781611071

KEY_VALUE_VERSION = 1

LAST_BLOOM_KEY = r2

MAJOR_COMPACTION_KEY = false

MAX_MEMSTORE_TS_KEY = 8

MAX_SEQ_ID_KEY = 10

TIMERANGE = 1565781603186....1565781667630

hfile.AVG_KEY_LEN = 22

hfile.AVG_VALUE_LEN = 1

hfile.CREATE_TIME_TS = 1565785277850

hfile.LASTKEY = r2/colfam1:q2/1565781667630/Put/vlen=0/mvcc=0

\# Hfile V3存储cell标签数据

MAX_TAGS_LEN = 22 \# 单个cell中存储标签的最大字节数

TAGS_COMPRESSED = true \# 是否针对标签进行压缩处理

Mid-key: \\x00\\x01r\\x07colfam1q\\x00\\x00\\x01l\\x8F\\xDBR?\\x04

Bloom filter:

BloomSize: 8

No of Keys in bloom: 3

Max Keys for bloom: 6

Percentage filled: 50%

Number of chunks: 1

Comparator: RawBytesComparator

Delete Family Bloom filter:

Not present

2.4. BucketCache

2.4.1. BucketCache内存结构

2.4.2. BucketCache标签

| BucketSize大小总比Block本身大1KB,是因为Block不是固定大小,总会比64K更大一些; 默认标签:(4+1)K, (8+1)K, (16+1)K, (48+1)K, (56+1)K, (64+1)K, (96+1)K,…(512+1)K; 启动HBase时,系统先从小到大遍历一次所有size标签,为每类标签分配一个Bucket,最后所有剩余的Bucket都分配最大的size标签,默认分配(512+1)K。 Bucket的size标签可以动态调整:64KB的Block比较多,65K的Bucket用完后,其它size标签的完全空闲的Bucket可以转换成65K的Bucket,但是会至少保留一个该size的Bucket。

2.4.3. BucketCache中Block缓存写入及读取流程

2.4.4. HDFS文件检索Block

| HDFS Block为128M: HDFS主要存储大文件,当数据量大到一定程度,如果Block太小会导致Block元数据(Block所在DN位置、文件与Block之间对应关系等)非常庞大。 HDFS元数据都存储在NN上,大量元数据容易让NN成为整个集群的瓶颈。 因此,HDFS Block从最初的64M增加到128M。 HBase Block为64K: HBase的缓存策略是缓存整个Block,如果Block设置太大会导致缓存很容易被耗尽,尤其对于很多随机读业务,设置Block太大会让缓存效率低下。 |