介绍
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);
水平一般,能力有限,大数据小学生一枚。文章主要用于个人学习和总结,如果能给他人带来帮助,纯属意外。