天天看点

Hbase数据热点和倾斜问题

介绍

Hbase每一条记录是按照rowkey做为唯一标识符设计的,rowkey按照字典顺序排序,方便数据读取扫描。众所周知,数据是存储在Region中,每个Region都包含rowkey开始和结束范围,数据rowkey在哪个范围寻找对应的Region进行存储。

Region存储范围样例:

Region start-rowkey end-rowkey
region-01 1 10 存储rowkey在1-10范围内的数据
region-02 11 20 存储rowkey在11-20范围内的数据
region-03 21 30 存储rowkey在21-30范围内的数据

以上就是数据在各个Region中的存储方式,这种设计在给数据读写带来方便的同时,也带来了一些其他负面问题。

数据热点(Hotspotting)

Hbase数据按照rowkey进行存储,虽然为查询数据提供了极大便利,但同时也产生了其他问题,比如数据热点(Hotspotting)问题。当大部分rowkey集中在某个范围时,会导致某几个Region数据量很大,其他Region数据量很少,这就是数据倾斜问题。因此整个集群压力都集中在某几个Region上,导致读写性能大幅度下降,这就是数据热点问题。数据热点问题严重情况下会导致Region下线,甚至整个集群宕机。

为了避免以上现象,我们需要将数据尽可能的均匀分布在各个Region中,因此Hbase中rowkey的设计至关重要。

rowkey设计原则

了解Hbase数据的存储原理和rowkey的作用之后,rowkey的设计就成为了重中之重。通常rowkey设计要遵循长度、散列、唯一三大原则。

长度:rowkey是以ByteArray进行存储,可以是任意字符。rowkey设计越短越好,建议在16字节以下。由于在底层数据文件中是按照key-value形式存储的,如果rowkey按照100字节,1000万条数据,那么仅rowkey就占用了将近1GB空间。

散列:散列性原则是通过rowkey将数据均匀分布在各个Region中,避免数据倾斜和热点问题。

唯一:rowkey代表每一行记录的主键,必须具有唯一性。

数据倾斜和热点问题

数据倾斜和热点是一个很常见的问题,往往给生产和维护带来了很大困扰。那么如何有效的避免或减少这种问题呢?答案就是优化rowkey设计,官方提供了以下几种优化方案:

参考网址:官方网址 第35章节Rowkey Design

Salting

原理:一句话简单描述为在rowkey前边加上随机值,其中随机值数量是region的个数。

假设有四个rowkey

foo0001、foo0002、foo0003、foo0004

我们想要均匀分布在四个region中,假设有a、b、c、d四个salt,每个salt都在不同的region上。加入salt后rowkey就变成了

a-foo0003、b-foo0001、c-foo0004、d-foo0002

每一个rowkey都增加了随机salt前缀,这样就能减轻数据倾斜问题

缺点:由于数据增加了随机前缀salt,因此查询就变得更加复杂

Hashing

原理:为了弥补随机前缀对查询带来的影响,引申出了一种one-way hash方法,保证相同的rowkey永远都有相同的前缀salt。

还是上边的例子,这次将salt换成hash(rowkey),这样同一个rowkey生成的salt永远一样,保障了查询性能。

Reversing the Key

原理:将rowkey中经常变化的数字部分或者固定长度的部分做为前缀,这样增加了散列性,能够有效减缓数据倾斜问题。

缺点:有可能丧失了原来rowkey的有序性,对数据查询带来影响。

建表时预分区

在建表时根据数据量和数据分布情况,合理的设定Region数量,设计合适的rowkey。这样一方面能有效避免数据倾斜问题,还能防止Region频繁分裂和合并带来额外的IO开销。

缺点:这种方式有很大的局限性,只适合有限的数据量或者增长缓慢的场景。

byte[][] splitKeys = {
		Bytes.toBytes("01"),
		Bytes.toBytes("02"),
		Bytes.toBytes("03"),
		Bytes.toBytes("04")
};
List<String> families = new ArrayList<>();
families.add("f1");
hbaseManager.createTable("test", families, splitKeys);
           

水平一般,能力有限,大数据小学生一枚。文章主要用于个人学习和总结,如果能给他人带来帮助,纯属意外。

继续阅读