RowKey设计不合理容易导致热点问题,即所有的访问集中在一个或几个结点之上,导致这些机器过载,性能下降。一些常用的避免热点的方法:
- 哈希
-
- 适用场景:1. 无需连续读取;2. RowKey较为复杂
- 具体方法:记原始Key为OriginalKey,则新的Rowkey = Substr(Md5(OriginalKey), 0, 3) + OriginalKey.
- 说明:MD5取4位做前缀用于保证负载均衡,OriginalKey也需要拼接上去,避免冲突
- 实例:龙源Key为查询语句拼接而成,如"2015-12-20_2015-12-20_bra:1-pla:12-cha:2",则生成的Rowkey为"9F38-2015-12-20_2015-12-20_bra:1-pla:12-cha:2"
- Reversing the key
-
- 适用场景:1. 无需连续读取;2. 固定长度或者数字类型的Rowkey
- 具体方法:将Rowkey倒序
- 说明:最后一位变化最频繁(数字的最低位)被移到开头,效果相当于哈希
- 实例:用户云聊天室,RowKey为roomID+msgID,由于roomID为单调增数字,最新的聊天室roomID最大,通常相对热度更高。若直接使用roomID,则最新的roomID集中在一个Region,产生热点。将roomID倒序后做为前缀,则最新的roomID被分散在不同的Region之中。若roomID=12345,msgId=8888,则原始Rowkey为‘12345-8888‘,改进后为’54321-8888‘
比较:和哈希相比,结果相似。优点是:1. 计算倒序代价比计算哈希低;2. 倒序无需额外的存储空间;
- 取模
-
- 适用场景:同Reversing the key类似
- 说明:区别是是否需要key。继续以聊天室为例,Original key为 roomID + msgID,若msgID全局唯一,则采用取模的方法,Rowkey = (roomID % N) + msgID;若msgID在roomID唯一,但在全局不唯一,则rowkey需要roomID的信息,采用Reversing the key的设计
- 单调增rowkey / 时间序
应避免使用单调增长的id或者时间戳做为rowkey,否则会出现请求集中在一个Region,然后再转移到下一个Region。若要上传时间序的数据,可以参考OpenTSDB的设计,其rowkey是[metric_type][event_timestamp],虽然包含了时间戳,但不在最开头;同一时间都更新最新时间戳的值,由于metric_type有很多种,足以用来均衡负载。
- 更详细内容请参考:Apache Book
- URL类似的RowKey
一些系统(如爬虫系统)以URL为Rowkey,要求一个Domain的内容连续存储;对于这类问题,有以下Rowkey设计思路予以参考:
-
- Reversed domains:
Examples: “com.cloudera.www”, “com.cloudera.blog”
用以使得一个网站的页面连续存储
-
- Domain Row Key = MD5(Reversed Domain) + Reversed Domain
MD5前缀(4字节)使得不同站的内容均匀分散到不同的RegionServer;
对需要连续存储的最小单元做MD5,可以是主域cloudera,也可以是子域,据业务需求而定;
-
- URL Rowkey = MD5(Reversed Domain) + Reversed Domain + URL ID
对于已有URL ID的,可直接使用ID;
将URL转成简短的ID,第一步将URL转成十进制ID,如MySql存储的自增ID;第二步将十进制ID转成[0-9a-zA-Z]的62进制。更多参考
http://stackoverflow.com/questions/742013/how-to-code-a-url-shortener
来源:oschina
链接:https://my.oschina.net/guoenzhou/blog/4291166