【HBase】HBase入门详解(四)

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

(图片来源于网络,侵删)


一、Master、RegionServer的上下线以及Region的管理

Master上线

1) 从Zookeeper上获取唯一一个代表Active Master的锁,用来阻止其他Master成为真正的Master
2) 扫描Zookeeper上的/hbase/rs节点,获取当前可用的Region server列表
3) 和每个RegionServer通信,获得当前已分配的Region和RegionServer的对应关系
4) 扫描.MATA.表数据,计算得到当前还未分配的Region,将他们放入待分配Region列表

Master下线

1) 由于Master只维护表和Region的元数据,不参与表数据IO的过程,Master下线导致所有元数据的修改被冻结(无法创建删除表、无法修改表的schema、无法进行Region的负载均衡、无法处理Region上下线、无法进行Region的合并,唯一例外的是Region的split可以正常进行,因为只有RegionServer参与),表的数据读写还可以正常进行。因此Master下线短时间内对整个hbase集群没有影响
2) Master下线,启用Zookeeper的选举机制,确定新的Master,新的Master执行上线流程

RegionServer上线

1) Master使用Zookeeper来跟踪RegionServer的状态
2) 当某个RegionServer启动时,会首先在Zookeeper上的/hbase/rs目录下建立代表自己的znode
3) 由于Master订阅了/hbase/rs目录上的变更消息,当/hbase/rs目录下的文件出现新增或删除操作时,Master可以得到来自Zookeeper的实时通知
4) 因此一旦RegionServer上线,Master能马上得到消息

RegionServer下线
精简版:

1) 当RegionServer下线时,它和Zookeeper的会话断开
2) Zookeeper从而自动释放代表这台RegionServer的文件上的独占锁
3) Zookeeper通知Master该RegionServer下线
4) Master将该RegionServer上的Region分配给其他还活着的RegionServer

完整版:

1) 当RegionServer下线时,它和Zookeeper的会话断开
2) Zookeeper从而自动释放代表这台RegionServer的文件上的独占锁
3) 而Master不断轮询Server目录下文件的锁状态,如果Master发现某个RegionServer丢失自己的的独占锁,或者Master连续几次和RegionServer通信都无法成功,Master就尝试去获取代表这个RegionServer的读写锁;一旦获取成功,就可以确定RegionServer和Zookeeper之间的网络断开或RegionServer挂了。无论哪种情况发生,RegionServer都无法继续为它的Region提供服务,此时Master会删除Server目录下代表这台RegionServer的文件,并将这台RegionServer的Region分配给其他还活着的节点
4) 如果网络短暂出现问题导致RegionServer丢失它的锁,RegionServer重新连接到Zookeeper之后,只要代表它的文件还在,它就会不断尝试这个文件上的锁,一旦获取到,就可以继续提供服务

Region管理

1) 任何时刻,一个Region只能分配给一个RegionServer
2) Master记录了当前有哪些可用的RegionServer,以及当前哪些Region分配给了哪些
Region server,哪些Region还没有分配
3) 当需要分配的新的Region,并且有一个RegionServer上有可用空间时,Master就给这个
RegionServer发送一个装载请求,把Region分配给这个RegionServer,RegionServer得到请求后,就开始对此Region提供服务


二、Memstore

Memstore 概述

Memstore是HBase框架中非常重要的组成部分之一,是HBase能够实现高性能随机读写至关重要的一环。深入理解Memstore的工作原理、运行机制以及相关配置,对hbase集群管理、性能调优都有着非常重要的帮助

HBase中,Region是集群节点上最小的数据服务单元,用户数据表由一个或多个Region组成。在Region中每个ColumnFamily的数据组成一个Store。每个Store由一个Memstore和多个HFile组成,如下图所示:

在这里插入图片描述
之前我们提到,HBase是基于LSM-Tree模型的,所有的数据更新插入操作都首先写入Memstore中(同时会顺序写到日志HLog中),达到指定大小之后再将这些修改操作批量写入磁盘,生成一个新的HFile文件,这种设计可以极大地提升HBase的写入性能;另外,HBase为了方便按照RowKey进行检索,要求HFile中数据都按照RowKey进行排序,Memstore数据在flush为HFile之前会进行一次排序,将数据有序化;还有,根据局部性原理,新写入的数据会更大概率被读取,因此HBase在读取数据的时候首先检查请求的数据是否在Memstore,写缓存未命中的话再到读缓存中查找,读缓存还未命中才会到HFile文件中查找,最终返回merged的一个结果给用户。

可见,Memstore无论是对HBase的写入性能还是读取性能都至关重要。其中flush操作又是Memstore最核心的操作,接下来重点针对Memstore的flush操作进行深入地解析:首先分析HBase在哪些场景下会触发flush,然后结合源代码分析整个flush的操作流程,最后再重点整理总结和flush相关的配置参数,这些参数对于性能调优、问题定位都非常重要。

Memstore Flush触发条件

HBase会在如下几种情况下触发flush操作,需要注意的是MemStore的最小flush单元是HRegion而不是单个MemStore。可想而知,如果一个HRegion中Memstore过多,每次flush的开销必然会很大,因此我们也建议在进行表设计的时候尽量减少ColumnFamily的个数

  1. Memstore级别限制:当Region中任意一个MemStore的大小达到了上限(hbase.hregion.memstore.flush.size,默认128MB),会触发Memstore刷新
  2. Region级别限制:当Region中所有Memstore的大小总和达到了上限(hbase.hregion.memstore.block.multiplier * hbase.hregion.memstore.flush.size,默认 2* 128M = 256M),会触发memstore刷新
  3. Region Server级别限制:当一个Region Server中所有Memstore的大小总和达到了上限(hbase.regionserver.global.memstore.upperLimit * hbase_heapsize,默认 40%的JVM内存使用量),会触发部分Memstore刷新。Flush顺序是按照Memstore由大到小执行,先Flush Memstore最大的Region,再执行次大的,直至总体Memstore内存使用量低于阈值(hbase.regionserver.global.memstore.lowerLimit * hbase_heapsize,默认 38%的JVM内存使用量)
  4. 当一个Region Server中HLog数量达到上限(可通过参数hbase.regionserver.maxlogs配置)时,系统会选取最早的一个 HLog对应的一个或多个Region进行flush
  5. HBase定期刷新Memstore:默认周期为1小时,确保Memstore不会长时间没有持久化。为避免所有的MemStore在同一时间都进行flush导致的问题,定期的flush操作有20000左右的随机延时
  6. 手动执行flush:用户可以通过shell命令 flush ‘tablename’或者flush ‘region name’分别对一个表或者一个Region进行flush
Memstore Flush流程

为了减少flush过程对读写的影响,HBase采用了类似于两阶段提交的方式,将整个flush过程分为三个阶段:

  1. prepare阶段:遍历当前Region中的所有Memstore,将Memstore中当前数据集kvset做一个快照snapshot,然后再新建一个新的kvset。后期的所有写入操作都会写入新的kvset中,而整个flush阶段读操作会首先分别遍历kvset和snapshot,如果查找不到再会到HFile中查找。prepare阶段需要加一把updateLock对写请求阻塞,结束之后会释放该锁。因为此阶段没有任何费时操作,因此持锁时间很短。
  2. flush阶段:遍历所有Memstore,将prepare阶段生成的snapshot持久化为临时文件,临时文件会统一放到目录.tmp下。这个过程因为涉及到磁盘IO操作,因此相对比较耗时。
  3. commit阶段:遍历所有的Memstore,将flush阶段生成的临时文件移到指定的ColumnFamily目录下,针对HFile生成对应的storefile和Reader,把storefile添加到HStore的storefiles列表中,最后再清空prepare阶段生成的snapshot

Memstore 总结

Memstore 中的数据是排序的,当MemStore累计到一定阈值时
就会创建一个新的MemStore,并且将老的MemStore 添加到flush队列
flush时会将内存中不在版本范围内的数据全部删掉,然后再持久化到形成一个storeFile文件
然后后续的数据会写入一个新的storefile文件

三、StoreFile

StoreFile简介

1) 一个Region由多个Store组成,一个Store对应一个ColumnFamily(列族)
Store包括位于内存中的MemStore和位于磁盘的StoreFile;写操作先写入MemStore,当Memstore中的数据达到某个阈值,HRegionserver会启动flashcache进程写入StoreFile,每次写入形成单独的一个StoreFile
2)当StoreFile文件的数量增长到一定阈值后,系统会进行合并(minor、major compaction),在合并过程中会进行版本合并和删除工作(majar),形成更大的StoreFile
3)当一个Region所有StoreFile的大小和数量超过一定阈值后,会把当前的Region分割为两个,并由HMaster分配到相应的HRegionserver服务器,实现负载均衡
4)客户端检索数据,先在MemStore找,找不到再找StoreFile

StoreFile以HFile格式保存在HDFS上
在这里插入图片描述

1)首先HFile文件是不定长的,长度固定的只有其中的两块:Trailer和FileInfo。正如图中所示的,Trailer中有指针指向其他数据块的起始点
2)File Info中记录了文件的一些Meta信息,例如:AVG_KEY_LEN, AVG_VALUE_LEN, LAST_KEY, COMPARATOR, MAX_SEQ_ID_KEY等
3)Data Index和Meta Index块记录了每个Data块和Meta块的起始点
4)Data Block是HBase I/O的基本单元,为了提高效率,HRegionServer中有基于LRU的Block Cache机制。每个Data块的大小可以在创建一个Table的时候通过参数指定,大号的Block有利于顺序Scan,小号Block利于随机查询。 每个Data块除了开头的Magic以外就是一个个KeyValue对拼接而成, Magic内容就是一些随机数字,目的是防止数据损坏
5)HFile里面的每个KeyValue对就是一个简单的byte数组。但是这个byte数组里面包含了很多项,并且有固定的结构。我们来看看里面的具体结构:
在这里插入图片描述
开始是两个固定长度的数值,分别表示Key的长度和Value的长度。紧接着是Key,开始是固定长度的数值,表示RowKey的长度,紧接着是 RowKey,然后是固定长度的数值,表示Family的长度,然后是Family,接着是Qualifier(限定符),然后是两个固定长度的数值,表示Time Stamp和Key Type(Put/Delete)。Value部分没有这么复杂的结构,就是纯粹的二进制数据了

  • HFILE结构

解释1(较为清晰)
  • ① Data Block 段–保存表中的数据,这部分可以被压缩
  • ② Meta Block 段 (可选的)–保存用户自定义的kv对,可以被压缩
  • ③ File Info 段–Hfile的元信息,不被压缩,用户也可以在这一部分添加自己的元信息
  • ④ Data Block Index 段–Data Block的索引。每条索引的key是被索引的block的第一条记录的key
  • ⑤ Meta Block Index段 (可选的)–Meta Block的索引
  • ⑥ Trailer–这一段是定长的。保存了每一段的偏移量,读取一个HFile时,会首先 读取Trailer,Trailer保存了每个段的起始位置(段的Magic Number用来做安全check),然后,DataBlock Index会被读取到内存中,这样,当检索某个key时,不需要扫描整个HFile,而只需从内存中找到key所在的block,通过一次磁盘io将整个 block读取到内存中,再找到需要的key。DataBlock Index采用LRU机制淘汰
  • ⑦ HFile的Data Block,Meta Block通常采用压缩方式存储,压缩之后可以大大减少网络IO和磁盘IO,随之而来的开销当然是需要花费cpu进行压缩和解压缩。
    目标Hfile的压缩支持两种方式:Gzip,Lzo

解释2(较为简洁明了)
  • ① Data(数据块):保存表中的数据(KeyValue的形式),这部分可以被压缩。
  • ② Meta (元数据块):存储用户自定义KeyValue
  • ③ File Info:定长;记录了文件的一些元信息,例如:AVG_KEY_LEN,AVG_VALUE_LEN, LAST_KEY, COMPARATOR, MAX_SEQ_ID_KEY等
  • ④ Data Index(数据块索引):记录了每个Data块的起始索引
  • ⑤ Meta Index(元数据块索引):记录了每个Meta块的起始索引
  • ⑥ Trailer:定长;用于指向其他数据块的起始点。

StoreFile 总结

当一个Store中的StoreFile达到一定的阈值后,就会
进行一次合并(major compact),将对同一个key的修改合并到一起
形成一个大的StoreFile,当StoreFile大小达到一定的阈值后,又会对
StoreFile进行Split,等分成两个StoreFile


四、HLog

HLog简介

1)HLog(WAL意为 Write ahead log)记录数据的所有变更,与HDFS的editsLog类似,用于数据的容错和恢复

2)HLog是一个实现Write Ahead Log的类,在每次用户操作写入MemStore的同时,也会写一份数据到HLog文件中,HLog文件定期(默认1小时、或)会滚动出新的,并删除旧的文件(已持久化到StoreFile中的数据)。当HRegionServer意外终止后,HMaster会通过Zookeeper感知到,HMaster首先会处理遗留的 HLog文件,将其中不同Region的Log数据进行拆分,分别放到相应region的目录下,然后再将失效的region重新分配,领取到这些region的HRegionServer在Load Region的过程中,会发现有历史HLog需要处理,因此会Replay HLog中的数据到MemStore中,然后flush到StoreFiles,完成数据恢复

3)每个Region Server维护一个Hlog,而不是每个Region一个。这样不同region(来自不同table)的日志会混在一起,这样做的目的是不断追加单个文件相对于同时写多个文件而言,可以减少磁盘寻址次数,因此可以提高对table的写性能。带来的麻烦是,如果一台region server下线,为了恢复其上的region,需要将region server上的log进行拆分,然后分发到其它region server上进行恢复

4)HLog文件就是一个普通的Hadoop Sequence File

  • 4.1)HLog Sequence File 的Key是HLogKey对象,HLogKey中记录了写入数据的归属信息,除了table和region名字外,同时还包括 sequence number和timestamp,timestamp是”写入时间”,sequence number的起始值为0,或者是最近一次存入文件系统中sequence number
  • 4.2)HLog Sequece File的Value是HBase的KeyValue对象,即对应HFile中的KeyValue
WAL持久化等级

HBase中可以通过设置WAL的持久化等级决定是否开启WAL机制、以及HLog的落盘方式。WAL的持久化等级分为如下四个等级:

1)SKIP_WAL:只写缓存,不写HLog日志。这种方式因为只写内存,因此可以极大的提升写入性能,但是数据有丢失的风险。在实际应用过程中并不建议设置此等级,除非确认不要求数据的可靠性

2)ASYNC_WAL:异步将数据写入HLog日志中

3)SYNC_WAL:同步将数据写入日志文件中,需要注意的是数据只是被写入文件系统中,并没有真正落盘

4)FSYNC_WAL:同步将数据写入日志文件并强制落盘。最严格的日志写入等级,可以保证数据不会丢失,但是性能相对比较差

5)USER_DEFAULT:默认如果用户没有指定持久化等级,HBase使用SYNC_WAL等级持久化数据

用户可以通过客户端设置WAL持久化等级,代码:put.setDurability(Durability. SYNC_WAL )


都看到这里了,点赞评论一下吧!!!

在这里插入图片描述

发布了119 篇原创文章 · 获赞 441 · 访问量 33万+

猜你喜欢

转载自blog.csdn.net/qq_43733123/article/details/105621057