本文主要展示“HBase如何设计rowkey”,简单易懂,思路清晰,希望能帮你解开疑惑。让边肖带领大家学习和学习文章《HBase如何设计rowkey》。
HBase中的rowkey按照字典顺序排序,通过rowkey查询可以实现对千万条数据的毫秒级响应。但是,如果rowkey设计不合理,往往会出现一个共同的问题——热点。当大量客户端请求(读或写)仅指向群集的一个节点或少量节点时,这意味着出现了热点问题。
避免热点的方法是尽可能将rowkey均匀地分布到所有区域。以下是设计rowkey的几种常见方法:
00-1010 salt add指的是在rowkeys的前缀上添加随机数据,这样rowkeys就可以尽可能的分发到其他regionserver。
假设遇到以下rowkey,并且表的预分区被设置为每个字母对应一个区域。前缀“a”是一个地区,前缀“b”是另一个地区,以此类推。那么在这个表中,所有以“f”开头的rowkey都将位于同一个区域。例如:
foo0001
foo0002
foo0003
foo0004
然后,如果你想把它们分散到四个不同的区域,你可以用四个不同的前缀: a,b,c和d来加盐。加盐后,rowkey变成这样。
a-foo0003
b-foo0001
c-foo0004
d-foo0002
(ps:由于数据现在可以写入四个区域,理论上,性能比以前对同一区域的写入吞吐量高四倍)
而且,如果后续写入新数据,rowkey会随机添加前缀,并将其写入不同的区域。
缺点:虽然加盐可以在很大程度上避免热点问题,提高写作效率,但由于rowkey是随机添加盐值的,所以在阅读时会额外花费。加盐后如何具体读取数据,后面会介绍。
00-1010 hash的算法有很多,MD5可能是rowkey设计中最常用的算法,但需要注意的是MD5 hash还是有碰撞的可能,概率很小,但也不是零。
因此,一般用md5对rowkey进行哈希时,都会附加一个唯一的字段,比如account字段,MD5用于account,截取6位MD5返回值,然后拼接account字段,即:
substr(md5(account))帐户
此外,通过md5哈希后的rowkey,在创建表预分区时,可以使用hbase附带的HexStringSplit方法。
00-1010如果定义的rowkey字段在数据的前部有小范围的变化,在数据的后部有缓慢的变化和高频率的变化,您可以考虑反转该字段,尤其是对于时间戳相似的数据。
无论rowkey采用哪种设计方式,查询时都要进行相应的数据处理,比如哈希。查询时,还需要先对数据进行哈希处理,然后查询rowkey。逆序设计的Rowkey也是如此。
第一:加盐(salting)
rowkey可以是最大长度为64KB的任意字符串,但建议将rowkey设计得尽可能短,因为:
1.hbase数据存储以键值的形式存储。如果rowkey比较长,比如100字节,那么1000w行的数据就需要100 * 1000 w=10亿字节,将近1G的数据。
2.memstore会将数据缓存到内存中,如果rowkey较长,也会占用更多空间。
3.建议rowkey设计为8字节的整数倍,控制在16字节,因为现在的操作系统大多是64位的,整数倍更好的利用了操作系统的特性。
同样,ColumnFamily应该尽可能短,最好是一个字符,如f或d。
00-1010我们知道,长类型是8个字节,通过长类型可以存储一个最大值为18,446,744,073,709,551,615的无符号数,只有8个字节,但是如果以字符串类型的形式存储这样一个数,则需要几乎3倍的空间大小(假设每个字符占用一个字节)。
举个例子来验证:
//长
//
longl=1234567890L
byte[]lb=Bytes . tobytes(l);
system . out . println(' longbyteslength : ' lb . length);
nbsp; // returns 8
String s = String.valueOf(l);
byte[] sb = Bytes.toBytes(s);
System.out.println("long as string length: " + sb.length); // returns 10
// hash
//
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] digest = md.digest(Bytes.toBytes(s));
System.out.println("md5 digest bytes length: " + digest.length); // returns 16
String sDigest = new String(digest);
byte[] sbDigest = Bytes.toBytes(sDigest);
System.out.println("md5 digest as string length: " + sbDigest.length); // returns 26
但是,也有一个缺点,就是如果使用这种二进制表示的类型时候,在hbase shell界面查数据的时候,可读性比较差,比如:
hbase(main):002:0> get 'table1', 'rowkey1'
COLUMN CELL
f:q timestamp=1369163040570, value=\x00\x00\x00\x00\x00\x00\x00\x01
1 row(s) in 0.0310 seconds
以上是“HBase怎么设计rowkey”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!
内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/137950.html