预分区
通常hbase会自动处理region拆分,当region的大小到达一定阈值后,region将被拆分成两个,之后在两个region都能继续增长数据。
然而在这个过程当中,会出现两个问题:
第一点,就是我们所说的热点问题,数据会继续往一个region中写,出现写热点问题;
第二点,则是拆分合并风暴,当用户的region大小以恒定的速度增长,region的拆分会在同一时间发生,因为同时需要压缩region中的存储文件,这个过程会重写拆分后的region,这将会引起磁盘I/O上升 。
压缩:hbase支持大量的压缩算法,而且通常开启压缩,因为cpu压缩和解压的时间比从磁盘读写数据的时间消耗的更短,所以压缩会带来性能的提升。
对于拆分合并风暴,通常我们需要关闭hbase的自动管理拆分。然后手动调用hbase的split(拆分)和major_compact(压缩),对其进行时间控制,来分散I/O负载。但是其中的split操作同样是高I/O的操作。
所谓预分区,就是预先创建hbase表分区。这需要我们明确rowkey的取值范围和构成逻辑。
比如前面我们所列举的电信电话详单表。通过加盐我们得到的 rowkey构成是:随机数+主叫+被叫+时间,如果我们现在并没有500台机器,只有10台,但是按照我们的计划,未来将扩展到500台的规模。所以我们仍然设计0到499的随机数,但是将以主叫177开头的通话记录分配到十个region当中,所以我们将随机数均分成十个区域,范围如下:
-50,50-100,100-150,150-200,200-250,250-300,300-350,350-400,400-450,450-
然后我们将我们的预分区存入数组当中,当插入数据时,先根据插入数据的首部随机数,判断分区位置,再进行插入数据。同样,这样也能使得各台节点负载均衡。
如果在hbase shell中使用create建表时只写了表名和列族名**,那么这张表将只有一个region ,当一个region的大小超过阈值时会自动split成两个**,但split操作会带来资源消耗。region个数太少时,在数据量大、访问量大,或被批处理程序读写情况下性能可能会很差,并且伴随大批量读写而来的GC可能会使regionserver宕机,接着region被transit到其他节点上,将逐步拖垮HBase集群上的所有节点。
所以推荐在建表时进行预分区,充分考虑rowkey的分布做出合理的预分区方案,要考虑的点包括region的个数、region的大小等。
Region的个数
如果使用MapReduce读取HBase表数据,Map的个数等于该表region的个数,每个region都会有一个单独进程来处理,这个进程会逐条处理region中的每一行数据。举例来说如果只有一个region,那么读取数据的就只有一个进程;如果拆成10个数据均匀分布的region,那么10个map会带来10倍的效率提升。
大数据量情况下越发需要并行处理,因此我们往往希望源表的region的个数多一些。但是