前言

文章不含源码,只是一些官方资料的整理和个人理解

架构总览

这张图在大街小巷里都能看到,感觉是hbase架构中最详细最清晰的一张,稍微再补充几点。

1) Hlog是低版本hbase术语,现在称为WALs。

2) 1个region包含了多个store,1个store包含了1个colum family,这样就比较好理解

3) 1个store包含了多个storefile,1个sotrefile就是1个hfile文件

这在HDFS路径也能体现,大概长这样

table/region/column family/hfile

region

region就是一些连续的hfile集合,也就是说连续的hfile被存储在一个region目录下。

我们知道,hbase索引一个数据其实是通过遍历的方式,当然是经过优化的遍历,而region就起到了一个很大的作用。想象一下,如果你要在一堆文件中找到你要的内容,怎么样的文件结构才是更快。

·有序

假如你要找的文件有关键字a,那么如果所有文件是按关键字(hbase的rowkey)排序的,那么a就有迹可循,Hbase采用了lexicographic order(这个单词有点不想单词..)也就是字典排序(ASCII码),对每个rowkey从高位到地位排序。

·分块

Rowkey已经是排序的,但还是要遍历啊,万一有个rowkey是z开头的,不是要哭死。Hfile就出现了,一个hfile里有一段连续的rowkey,并且记录了所有rowkey的长度和整个hfile的rowkey是起始和终止。这样就方便了很多,遍历的时候只要看一个文件夹是否包含了该rowkey,而不用一个一个对比。(先忽略column family机制,bloom filter机制)

·进一步分块

但是hfile还是很多啊,要是把hfile容量扩大也不利用读。

最容易想到的就是把多个hfile统一管理,再做封装,这里就引申出了region。一些连续的hfile被一个region管理,region记录了rowkey的起始和终止等信息。这样遍历起来又快了很多。

region split

上面说的解决了遍历的性能问题,但是region也会变大,就像hfile会变大一样。这时候region split就出现了。

当region被认为需要split的时候(max size超过阈值),一系列操作就出现了。

1) region是否需要分割是否regionserver决定的,当需要的时候,通过zookeeper和master沟通一下

2) regionserver关闭该region,并且把memstore的相关数据flush到hfile。这时候有client来请求,则会抛出NotServingRegionException异常

3) 找到分割点,也就是midkey,查找流程是这样的。先找到该region中最大的一个hfile,然后找到这个hfile的midkey(在hfilev2版本以上,会在hile末记录midkey,否则需要找到data block数据/2的那个block的startkey作为midkey)

4) 准备子region的相关环境(路径啊,文件夹啊什么的,都是临时的),创建两个文件来指向父region(也就是待split的region)

5) 创建两个真正的子region(文件夹),并把那两个文件移过去

6) regionserver向hbase:meta表发起Put请求,把待分割的region设置为offline,并且增加子region的信息。在这过程中,客户端并不能真正看到子region(还不是独立的region),只是能知道有个父region在split。当put请求成功后,父region才会正真的split。(如果put请求失败了,那么由master分配新的regionserver来重新region split,在此之前会把上一次split失败的相关脏数据清除)

7) 打开子region,接收写操作。为之后无缝接入服务做准备

8) regionserver再向hbase:meta表添加相关信息。然后客户端再请求就能搜索到子region。当然由于region是新建的,所以之前的缓存都不可用。

9) regionserver通过zookeeper和master交互,让master知道有新region split好了。Master可以决定新region由哪个regionserver管理

10) 最后就是善后工作,由于新region实际上没有父region的数据,只有一些引用来指向父region。所以在子region compaction的时候,会重写这些数据。另外hbase的master还有一个GC task(不是jvm的GC),来定期轮询,查看是否还有引用父region,当没有的时候就删除父region

总结

整个流程虽然看上去很复杂,其实效率很高,region split的过程中是不可用的,但是这时间很短,因为不涉及大量的io,只有引用和交互。

master和regionserver之间的配合,master主要做协调,regionserver做实际的工作

Region compaction

其实用storefile compaction来表示更合适,compaction分为两种,compaction和major compaction。参考类`CompactionPolicy`,默认的实现是`ExploringCompactionPolicy`

Compaction

如果该列族下总hfile数量-正在合并的hfile数量 >= ` hbase.hstore.compaction.min`默认3,那么就会触发compaction,单次compaction的hfile数量上限是`hbase.hstore.compaction.max`默认10。compaction的定位是主要合并一些小的相邻的hfile,重写进一个新的hfile。重写的过程不包括数据的drop,filter,delete等移除操作,只是简单的把小文件合并成大文件。

Major Compaction

参考RatioBasedCompactionPolicy的实现,首先是计算major compaction的时间周期,默认周期是1周,通过配置`hbase.hregion.majorcompaction`。为了避免major compaction风暴(多个region同时major compaction导致hbase服务不可用),hbase还引用了时间偏差`hbase.hregion.majorcompaction.jitter`,默认是0.5,也就是说实际major compaction的时间是总周期上下浮动0.5个周期内的时间。如果需要合并hfiles中最小的文件修改时间戳比当前时间-合并周期小,那么视为可进行major compaction,但是如果只有一个hfile需要marjor compaction,那么hbase还会深入判断ttl和hfile的block本地化系数,从而获取最优解。

major compaction会把所有需要清除的数据都移除,最终合并成一个storefile。合并过程中服务还是可以使用,但是合并过程中会读取全量的数据,这样会大量的占用磁盘的IO,导致查询效率大幅下降,甚至不可用。

数据需要被移除一般有三种情况

1) 客户端显示的声明delete

2) 某些column family的version超过max version

3) 某些设置了TTL的column family

RegionServer和Region

官方建议一个RegionServer的Region数量控制在100个以内,但是这还受到RegionServer分配的内存大小,由于每个Region都有自己的memstore,而默认的memstore大小为128MB(hbase.hregion.memstore.flush.size),那么100个region直接就会使用10GB的内存

当全局MemStore的大小超过了该RegionServer内存的hbase.regionserver.global.memstore.upperLimit大小,默认40%的内存使用量。那么此时当前HRegionServer中所有HRegion中的MemStore都会Flush到HDFS中,Flush顺序是MemStore大小的倒序,直到总体的MemStore使用量低于RegionServer的hbase.regionserver.global.memstore.lowerLimit,默认38%的内存使用量。

参考资料

//hbase官网推荐的region split 博客

https://hortonworks.com/blog/apache-hbase-region-splitting-and-merging/

最新文章

  1. SOAP Webservice和RESTful Webservice
  2. 用nodejs搭建一个简单的服务器
  3. 【原】ios下比较完美的单例模式,已验证
  4. Bootstrap3.0学习第二十一轮(JavaScript插件——工具提示)
  5. echart 图表 在.net中生成图片的方法
  6. hdu 4612 Warm up 桥缩点
  7. 编写自己的TRACE函数
  8. PostgreSQL的 initdb 源代码分析之十
  9. js异步脚本
  10. 将汉字转化为拼音,正则表达式和得到汉字的Unicode编码
  11. traits编程技法
  12. Android之Activity生命周期简介
  13. 从运行原理及使用场景看Apache和Nginx
  14. android数据库升级的措辞
  15. 开发框架(WinForm)3
  16. Python学习之路-Day1-Python基础
  17. Java通配符解惑
  18. Android项目实战(四十五):Usb转串口通讯(CH34xUARTDriver)
  19. Javascript高级编程学习笔记(97)—— WebGL(3) WebGL上下文(1)
  20. BZOJ2223[Coci 2009]PATULJCI——主席树

热门文章

  1. K线数据库表结构
  2. Linux/Mac里复制终端Session(像SecureCRT一样)
  3. vue监听浏览器窗口大小变化
  4. LINUX内核分析20133201
  5. CentOS yum 安装node.js
  6. 移植nand驱动补缺:make mrproper与make clean以及make distclean,find/grep. makefile
  7. 生信-cufflinks输入输出文件分析
  8. SQL Server扩展属性的增、删、改、查
  9. LightOJ - 1074 Extended Traffic (SPFA+负环)
  10. Windows 配置安卓环境变量