前言:本篇主要是笔者在工作过程中发现或遇到的问题的一些总结。不涉及HBase基础及原理的探讨,如有需要,可参照笔者前两篇文章:基础篇、架构篇。
单调递增的RowKey有何不妥?
关于RowKey的设计,HBase的官方文档是给了一些案例的,建议可以通读官方文档的相应章节。单调递增的RowKey(如时间戳),可能会出现一段时间内,客户端仅访问某个RegionServer的情况,不但降低了热点数据的RegionServer的读写性能,而且整个集群的资源无法被充分利用。所以RowKey应该具有随机性,可以散列到各个RegionServer中。
HBase的二级索引?
我们直到,不像传统的关系型数据库,HBase仅支持RowKey索引,不直接支持二级索引。这也决定了HBase的使用场景:海量数据存储,高并发读写,单唯独的检索。设想一种场景,我们记录用户的登陆信息,可以通过IP或账号结合时间戳的方式查询用户的登陆信息,那么RowKey的设计就变得很棘手了。UID、IP、时间戳的随机组合均无法组成满足单维查询的需求,因此需要用到二级索引。简而言之,就是需要多加一张映射表,可以有以下设计。
表一:RowKey:UID + IP + 时间戳,value:用户登录信息
表二:IP + 时间戳,value:表一的RowKey信息
HBase内部可能影响客户端读写请求的操作
- Region拆分
- Region合并
- Region中Store的Maojor Compaction
- 待补充...
HBase中各种内部机制的操作单位
- MemStore Flush,Region级别操作
- Region拆分&合并,Region级别操作
- Minor/Major Compaction,Store级别操作
HBase为什么不推荐多列族
HBase表的列族数量控制在1 - 3个为佳,最好只有一个,有以下原因:
- MemStore Flush是Region级别的操作,会触发Region中多个Store同时触发Flush,而有些Store的MemStore还没什么数据,但仍需要刷盘,造成不必要的性能损耗。
- MemStore Flush后会产生StoreFile,StoreFile一多又需要执行Compaction操作,多个列族Compaction的开销也会增加。
- 设想一张表有多个列族,且多个列族之间的写入量差别很大,随着数据写入,触发Region拆分,那么低数据量的列族对应的StoreFile也会被拆分。