架构图
主节点HMaster的作用:
- 管理众多从节点
- 用于分配region给从节点
- 负责元数据管理操作
从节点HRegionserver的作用:
- 管理众多从节点
- 用于分配region给从节点
- 负责元数据管理操作
Hbase集群中可以有多个Hmaster(一主多备)和多个HRegionserver组成。
一个HRegionserver由一个HLog(WAL预写日志)和多个Region组成,一个Region由Stroe模块组成,一个Store模块由一个Mem Store和多个StoreFile(HFile)组成。
StoreFile
保存实际数据的物理文件,StoreFile 以 HFile 的形式存储在 HDFS 上。每个 Store 会有一个或多个 StoreFile(HFile),数据在每个 StoreFile 中都是有序的。
MemStore
写缓存,由于 HFile 中的数据要求是有序的,所以数据是先存储在 MemStore 中,排好序后,等到达刷写时机才会刷写到 HFile,每次刷写都会形成一个新的 HFile。
WAL
由于数据要经 MemStore 排序后才能刷写到 HFile,但把数据保存在内存中会有很高的概率导致数据丢失,为了解决这个问题,数据会先写在一个叫做 Write-Ahead logfile 的文件中,然后再写入 MemStore 中。所以在系统出现故障的时候,数据可以通过这个日志文件重建。
写数据流程
- Client 先访问 zookeeper,获取 hbase:meta 表位于哪个Region Server。
- 访问对应的 Region Server,获取 hbase:meta 表,根据读请求的 namespace:table/rowkey, 查询出目标数据位于哪个 Region Server 中的哪个 Region 中。并将该 table 的 region 信息以及 meta 表的位置信息缓存在客户端的 meta cache,方便下次访问。
- 与目标Region Server 进行通讯;
- 将数据顺序写入(追加)到 WAL;
- 将数据写入对应的 MemStore,数据会在 MemStore 进行排序;
- 向客户端发送ack;
- 等达到 MemStore 的刷写时机后,将数据刷写到HFile。
MemStore 刷写时机:
- 当某个 memstroe 的大小达到了 hbase.hregion.memstore.flush.size(默认值 128M), 其所在 region 的所有 memstore 都会刷写。当 memstore 的大小达到了hbase.hregion.memstore.flush.size(默认值 128M)* hbase.hregion.memstore.block.multiplier(默认值 4) 时,会阻止继续往该 memstore 写数据。
- 到达自动刷写的时间,也会触发 memstore flush。自动刷新的时间间隔由该属性进行配置 hbase.regionserver.optionalcacheflushinterval(默认 1 小时)
注:实际先写入缓存,再向wal同步,若挂掉,回退缓存
读数据流程
- Client 先访问 zookeeper,获取 hbase:meta 表位于哪个Region Server。
- 访问对应的 Region Server,获取 hbase:meta 表,根据读请求的 namespace:table/rowkey, 查询出目标数据位于哪个 Region Server 中的哪个 Region 中。并将该 table 的 region 信息以及 meta 表的位置信息缓存在客户端的 meta cache,方便下次访问。
- 与目标Region Server 进行通讯;
- 分别在Block Cache(读缓存),MemStore 和 Store File(HFile)中查询目标数据,并将查到的所有数据进行合并。此处所有数据是指同一条数据的不同版本(time stamp)或者不同的类型(Put/Delete)。
- 将从文件中查询到的数据块(Block,HFile 数据存储单元,默认大小为 64KB)缓存到Block Cache。
- 将合并后的最终结果返回给客户端。
同时读磁盘和Memstore进行比较,磁盘有数据,磁盘数据(该)加载到blockCache,再来如果blockCatch有数据,不读磁盘内该文件数据
rowkey设计
- 生成随机数、hash、散列值
- 字符串反转(时间戳)
- 字符串拼接
Hfile的合并
Minor Compaction
Minor Compaction会将临近的若干个较小的 HFile 合并成一个较大的 HFile,并清理掉部分过期和删除的数据,有系统使用一组参数自动控制
Major Compaction
Major Compaction 会将一个 Store 下的所有的 HFile 合并成一个大 HFile,并且会清理掉所有过期和删除的数据,由参数 hbase.hregion.majorcompaction控制,默认 7 天。
Minor Compaction 控制机制:
参与到小合并的文件需要通过参数计算得到,有效的参数有 5 个
(1)hbase.hstore.compaction.ratio(默认 1.2F)合并文件选择算法中使用的比率。
(2)hbase.hstore.compaction.min(默认 3) 为 Minor Compaction 的最少文件个数。
(3)hbase.hstore.compaction.max(默认 10) 为 Minor Compaction 最大文件个数。
(4)hbase.hstore.compaction.min.size(默认 128M)为单个 Hfile 文件大小最小值,小于这
个数会被合并。
(5)hbase.hstore.compaction.max.size(默认 Long.MAX_VALUE)为单个 Hfile 文件大小最大
值,高于这个数不会被合并。
小合并机制为拉取整个 store 中的所有文件,做成一个集合。之后按照从旧到新的顺序遍历。
判断条件为:① 过小合并,过大不合并
② 文件大小/ hbase.hstore.compaction.ratio < (剩余文件大小和) 则参与压缩。所有把比值设
置过大,如 10 会最终合并为 1 个特别大的文件,相反设置为 0.4,会最终产生 4 个 storeFile。
不建议修改默认值
③ 满足压缩条件的文件个数达不到个数要求(3 <= count <= 10)则不压缩。
region的拆分
1.预分区
2.系统拆分
Region 的拆分是由 HRegionServer 完成的,在操作之前需要通过 ZK 汇报 master,修改
对应的 Meta 表信息添加两列 info:splitA 和 info:splitB 信息。之后需要操作 HDFS 上面对
应的文件,按照拆分后的 Region 范围进行标记区分,实际操作为创建文件引用,不会挪动
数据。刚完成拆分的时候,两个 Region 都由原先的 RegionServer 管理。之后汇报给 Master,
由 Master 将修改后的信息写入到Meta 表中。等待下一次触发负载均衡机制,才会修改 Region
的管理服务者,而数据要等到下一次压缩时,才会实际进行移动。
不管是否使用预分区,系统都会默认启动一套 Region 拆分规则。不同版本的拆分规则
有差别。系统拆分策略的父类为 RegionSplitPolicy。
0.94 版本之前 => ConstantSizeRegionSplitPolicy
( 1 ) 当 1 个 region 中 的 某 个 Store 下 所 有 StoreFile 的 总 大 小 超 过
hbase.hregion.max.filesize (10G),该 Region 就会进行拆分。
0.94 版本之后,2.0 版本之前 => IncreasingToUpperBoundRegionSplitPolicy
( 2 ) 当 1 个 region 中 的 某 个 Store 下 所 有 StoreFile 的 总 大 小 超 过
Min(initialSize*R^3 ,hbase.hregion.max.filesize"),该 Region 就会进行拆分。其中 initialSize 的
默认值为 2*hbase.hregion.memstore.flush.size,R 为当前 Region Server 中属于该 Table 的
Region 个数(0.94 版本之后)。
具体的切分策略为:
第一次 split:1^3 * 256 = 256MB
第二次 split:2^3 * 256 = 2048MB
第四次 split:4^3 * 256 = 16384MB > 10GB,因此取较小的值 10GB
后面每次 split 的 size 都是 10GB 了。
(3)Hbase 2.0 引入了新的 split 策略:如果当前 RegionServer 上该表只有一个 Region,
按照 2 * hbase.hregion.memstore.flush.size 分裂,否则按照 hbase.hregion.max.filesize 分裂。
这叫大道至简,学海抽丝。