1 HBase整体架构
1.1 HMaster
1.2 HRegionServer
2 HBase 客户端读数据流程分析
3 HBase 客户端写数据流程分析
4 HBase服务端读数据流程分析
5 HBase服务端写数据流程分析
6 HBase服务端删除和increase操作
7 Region分裂和合并问题分析
8 HBase主备集群数据同步分析
分享的目的
更进一步地深入掌握HBase的内核架构
1 HBase整体架构
整体架构图:
1.1 HMaster
HMaster没有单点问题,HBase中可以启动多个HMaster,通过Zookeeper的Master Election机制保证总有一个Master运行,HMaster在功能上主要负责Table和Region的管理工作:
- 管理用户对Table的增、删、改、查操作(admin操作);
- 管理HRegionServer的负载均衡,调整Region分布;
- 在Region 合并分裂后,负责新的Region重新分配;
- 在HRegionServer停机后,负责失效HRegionServer 上的Regions迁移;
- HMaster是保证HBase高可靠的因素之一;
- 线上环境 ,HMaster是般由两到三台组成,普通(24G)的虚拟机;
1.2 HRegionServer
- HRegionServer是存储实际Region,响应客户端写入的IO,并负责存储数据到HDFS中,是HBase最核心的部分;
2.理论上HRegionServer是可以无限扩容的,这也是为什么说HBase是一个存储海量数据的数据库; - 在生产环境中,通常HRegionServer和HDFS部署在相同的机器上,并且最好要在同一个大交换机下面的端口;
- HRegionServer机器的配置要求: CPU内核数越多、内存越大、硬盘越大越好,当然regionServer的JVM堆内存不是越大越好,通常建议不要超过32G,过大,会有严重的Full GC问题,而且在64位的JVM中,堆大小超过32G,指针不能做压缩;
- 一台HRegionServer上有多个HRegion, 一个HRegion上有多个Hstore,一个family对应一个HStore ,一个Hstore上有多个StoreFile和一个MemStore ,HBase用LSM树来组织这些StoreFile和MemStore, 因为LSM树这种数据结构只适合写,不太适合读, 而B+树适合读,不太适合写 ,因此这才是HBase是一种适合写多读少的数据库的根本原因, 而mysql关系型数据库适合读多写少的应用场景。下面是LSM树和B+树的数据结构:
2 HBase 客户端读数据流程分析
流程图
第一次读写数据, 需要定位相关Region所在的HRegionServer机器:
1.HBase客户端先根据HBase的zk上的相关结点的内容定位到.Meta表所在的HRegionServer服务器的主机,并在客户端本地做相关的缓存;
- HBase客户端和-Meta表所在的HRegionServer服务器通过rpc通信,获取相关的rowKey记录所在Region信息(包括该region所在的HRegionServer的机器名和IP), 并在客户端本地做相关的缓存,以后就不用再查找;
第二或第二次以后读写数据
通过查找客户端本地的缓存,直接和相关的HRegionServer进行通信,进行相关的数据读操作;
3 HBase 客户端写数据流程分析
流程图
- 如果autoFlush为true, 默认也为true, 如果单个写Put不是特别大的情况下,没是步骤4;如果单 个写Put特别大,还是会有步骤4;
- 如果客户端批量写,很容易出现客户端缓存超出的现象,还是会有步骤4, 如果一次提交的特别多,还是建议适当设置hbase.client.write.buffer的大小,建议不超过5M;
- 如果可以接受一部分数据丢失的可能,为了提高写入的吞吐量,可以在写入时在HTable上设置autoFlush 为false
HBase服务端读写据流程分析
1. 服务端核心类:
org.apache.hadoop.hbase.regionserver.HRegion
2. HBase源码模块名称:
hbase-server
4 服务端读数据流程分析
以get(final Get get)为例进行分析
代码层面如下两个主要的方法:
scanner = getScanner(scan);
scanner.next(results);
HBase regionServer读取数据主要有两个步骤:
1. 根据Get对象生成相关的RegionScanner对象, 在这个过程中可以充分利用布隆过滤器和时间戳, RegionScanner对象主要包括多个StoreScanner,一个StoreScanner下面包含多个StoreFileScanner和一个MemStoreScanner,当然每个StoreFile下面有多个HFile;
2. 调用next方法, 即扫描StoreFile和和MemStore, 依次查找每一个每符合要求的cell(当然在查找的过程中会有相关的缓存,在这里提一下,阿里HBase团队出一种针对SSD存储的BucketCache),并填充结果集;
5 服务端写数据流程分析
- 检查该region 写的状态是不是只能读,如果是只能读,就抛出异常结束;
检查该region 资源, 主要包含两个方面
2.1 检查该region是不是.meta Region, 如果是.meta Region ,就直接返回结束; 2.2 检查该region当前所有的memStore的大小,是不是超过了已经配置的刷写大小的2倍,如果超过 这个值,就把memStore的数据全部刷到HDFS中, 然后抛出RegionTooBusyException 的异常, 这个刷写的大小由blockingMemStoreSize 控制,而blockingMemStoreSize由 hbase.hregion.memstore.flush.size(默认值是128M)和hbase.region.memstore.block.multiplier(默 认值为2)的乘积确定,即 blockingMemStoreSize默认值为256M;
- 如果步骤2没检查通过,就进入下面写入主流程:
注意: 如果一次put的数据比较 多,3的步骤要反复执行多次,并且每次循环都要先开始执行依次步骤1和
步骤2的检查操作。
重要: 在刷日志 这步骤中,需要根据建表时是否设置 同步写入WAL,以及WAL同步到HDFS中要求,会
有很大的不同,默认是写一次操作,WAL要刷一次HDFS, 这是最安全的,但写入性能不是很
高,设置 成异步刷盘(ASYNC_WAL)比较好性能最好(默认1s一次),这样丢失的数据最少,性能可
以接受,常见的设置有(SKIP_WAL, ASYNC_WAL, SYNC_WAL, FSYNC_WAL, 建表的时候设
置), 线上环境建议用默认值比较 好,刷日志的时候只写到HDFS,不会写到硬盘上, 而且性能也
非常好,毕竟 Hlog是顺序文件 ,在HDFS中是append操作;
- 在Put, Delete, Increase过程中如果设置了setWriteToWAL(false), 就不会写WAL , 不过这样做非常危险;
- 在memStore刷写到HDFS时: 先向后台异步任务 提交一个任务 ,唤醒后台的异步任务 ,如果新memStore所在region符合分裂的要求 ,就执行分裂操作;
6 HBase服务端删除和increase操作
delete过程和put过程一样,只是在写的过程中添加相关的墓杯标记
increase操作在服务端主要有三个步骤:
1. 读取原来列的数据到内存中;
2. 修改读到内存中的数据;
3. 重新数据写到memStore和WAL中;
7 Region分裂和合并问题分析
7.1 Region分裂
当一个region里的StoreFile增长到大于配置的参数:hbase.hregion.max.filesize的大小,也可以在创建HBase表的时候指定这个参数,region会被一分为二。这个过程一般在2-3S内完成,对写数据的影响有短暂的暂停, 由于zookeeper全程记录分裂过程 ,因些分裂服务器失败的时候,其它服务器是可以知道这个region的状态 ,分裂在高并发写的情况下,影响非常大,如何减少在写入过程中region的分裂,是利用好HBase的关键所在,整个分裂是的流程如下:
- region所在regionServer创建splits目录;
- 关闭要分裂的region的读写请求;
- 在splits目录中创建所需要的文件结构;
- 移动两个新region文件 目录到目录 表中,并更新.META表;
- 异步复制父region中的数据到两个子region中(最主要的消耗时间);
- 复制完成后、打开两个新产生的region,并上线,可以接收新的读写请求;
- 异步任务把定时把原来被分裂的region从.META表中清除掉,并从文件系统中删除该region所占
用的空间;
- 分割点的确定: Region中StoreFile最大文件中的内部中点
- 执行Region分裂的时间是: memStore刷到HDFS的时候,后台线程异步执行,所在类名为MemStoreFlusher
7.2 Region合并
随着MemStore不断有数据写入,当MemStore的大小超过配置或默认大小的时候,HBase会把
MemStore中的数据刷新到HDFS中,生成新的StoreFile文件 ,当一个region中包含的StoreFile文 件 数目超过配置地的阈值,后台合并任务,会把这些文件 合并成数量更少,体积更大的文件
当这个过程持续到这些文件 中最大的StoreFile文件 超过配置最大存储文件 大小时,此时会触发
一个region拆分操作,减少读取过程中的IO
Region合并分为两种,minor合并和major合并:
3.1 Minor合并: 是把最后生成的几个小的StoreFile文件 合并一个更大的StoreFile, 默认同时合并的文 件数为10, 主要控制参数如下; hbase.hstore.compaction.min 最小合并文件 数量大小, 默认为3 hbase.hstore.compaction.max 最大合并文件 数量大小, 默认为10 hbase.hstore.compaction.max.size 最大合并文件 的大小 , 默认值 为Long.MAX_VALUE hbase.hstore.compaction.min.size 最小合并文件 的大小, 默认值是memStore刷写的大 小, 它是一个阈值, 它包含所有小于限制的文件 ,直到达到每次压缩允许的总文件数量 3.2 Major合并: 是把整个Store中所有StoreFile文件 合并成一个单独的StoreFile文件 后台定时任务定期检查, 这个检查周期是由下面这两人个参数决定 hbase.server.thread.wakefrequency * hbase.server.thread.wakefrequency.multiplier(默认值为1000)
8 HBase主备集群数据同步分析
更进一步深入了解掌握HBase;