浅谈HBase建表预分区的重要性
背景
最近在处理一些现网问题时,发现好几例因为建表或者rowkey设计不合理导致的性能问题。这类问题往往在测试环境因为压力不够或者数据量过小,不易被发现。但是一旦部署到生产环境再去解决,代价往往会非常大。
根据向HBase用户的进一步了解,往往存在如下误解:
- 我之前使用MySql没听说要做什么预分区;
- HBase对region有自动分裂的能力,为什么要做预分区?
几个概念
-
region:将一张HBase的表按照rowkey的区间划分成多个小表,region可以理解为这里的小表。不同region的rowkey区间是不重复的,region是RegionServer分布式管理和负载均衡的基本单元;
-
split:region分裂,顾名思义就是将一个region分裂成两个子region,子region的rowkey区间刚好与父region的区间重叠;
-
compaction:HFile合并。将region下的多个HFile合并成一个HFile,用于提升查询的性能。
回归正题
解释完region的概念后,其实误解1就很好理解了。HBase是一个分布式的KV数据库,想要提升表的读写能力,那肯定是要充分利用各数据节点来提升总的吞吐量。如果表未进行预分区,也就意味着一开始只有一个region,读写压力就则集中在某一个数据节点(不考虑region replica),其余数据节点则处于空闲状态。
针对误解2,HBase的region的确有自动split(分裂)的能力,但是region的分裂其实是包含两个阶段:
阶段一:daughter region的创建和上线以及父region的下线。因为该阶段结束后,daughter region就能正常访问,所以很多HBase用户往往觉得该解决就表示region分离结束;
阶段二:HFile compaction,为了确保daughter region尽快上线提供服务,阶段一只是生成了reference file指向父region的hfile,存量数据的查询还得访问父region的HFile,所以daughter region上线后,会触发HFile compaction任务,将父region的HFile按照新的region区间重写到daughter region。
所以region的split一定会触发HFile的合并,而HFile的合并的流程可以简单理解为读取父region的HFile然后写到daughter region,该过程对磁盘IO对消耗是比较严重的。
另外,只有父region的所有HFile都重写到daughter region后,新的region才允许进行下一次分裂。这里就会存在另外一个问题,如果表未做预分,当面对大量写入时,可能因为compaction未完成而无法及时进行新的分裂操作,导致region存放大量的数据。
如果在建表时提前做好预分,则可以很好的避免上述问题。
多问一句
既然建表预分区能提升读写性能,那是不是预分的region越多越好?
答案是否定的,因为RegionServer管理的region数量有规格限制,过多的region会导致每个region的数据量以及请求量过少,造成不必要的资源浪费。
- 点赞
- 收藏
- 关注作者
评论(0)