1. 缘起
线上HBASE集群在每次重启之后,都会出现访问延迟增大的现象。通过Ganglia查看HABSE相关监控指标和推测,最后发现是数据的本地化特性被破坏导致。
如下图,在HBASE重启之后,regionserver的percentFilesLocal指标出现下降。
2. 分析
由于HBASE建立在HDFS的基础之上,regionserver通过datanode读取数据。如果regionserver读取的数据正好是同宿的datanode负责管理,则是最理想的情况,即Short Circuit Local Reads。
随着时间的推移,HBASE的compact机制会将regionserver管理的region所对应的HDFS文件移动到同宿的datanode上进行管理,这提高了Short Circuit Local Reads的概率。
当HBASE发生重启的时候,region会重新随机分配给各个regionserver,这导致重启之后regionserver和region的对应关系发生改变,也就是region和其对应的HDFS文件的同宿关系被打破。于是regionserver不得不跨网络读取数据,因此数据访问延迟增大。
当然随着时间的推移,由于compact机制的存在,region和其对应的HDFS文件会重新分布于同一机器,访问延迟会慢慢恢复到重启前的水平。
可见,如果想要避免重启导致的访问延迟短期内增大的问题,最直接的方式是保证重启前后region的分布情况不变。
通过上面的分析可知:HDFS的balancer通过移动block也会打破数据本地化特性,所以HBASE集群不要开启HDFS的balancer。
3. 解决
HBASE自带了graceful_stop.sh脚本,可以实现regionserver重启前后所管理的region保持不变。
1 | sh graceful_stop.sh --restart --reload --debug --maxthreads 10 <regionserver> |
但是这个脚本默认不支持并发,只能一台一台重启,在集群规模较大时,效率比较低。
我对这个脚本进行了修改,增加了批量重启的功能,可以分批次滚动重启regionserver。详见https://github.com/winway/hbase-rolling-restart
使用滚动重启后,regionserver的percentFilesLocal指标如下:
4. 收尾
通过解决这个问题,我们了解了数据本地化特性的概念和影响,那么可不可以量化一个region、一个table、一个regionserver以及集群整体的数据本地化特性。答案是可以的,大致思路如下:
- 通过scan “hbase:meta”,获取regionserver和region的对应关系
- 通过hdfs fsck /hbase/data/default/ -blocks -files -racks获取所有region对应的HDFS文件的block的分布情况
- 针对每个region计算所有的block中,有多少block分布在本地
详见https://github.com/winway/hbase-rolling-restart/blob/master/hbase_locality.sh