Rowkey 是行的主键,它是以字典顺序排序的。所以 Rowkey 的设计是至关重要的, 关系到你应用层的查询效率。
有时作为 Rowkey 的字段长度不一样,比如 user_id, 而通过对 Rowkey 进行规整化,能够避免 Rowkey 长度不一致,导致每次请求返回的数据量不一,可将组合的 Rowkey 映射成等长 hash 值。
如果 Rowkey 是以字符串形式保存,比如日期格式(yyyy-MM-dd HH:mm:ss),会造成大量存储空间的浪费, 因此可以对字符串进行数值编码,将编码后的数保存到 Rowkey 中。
如果 Rowkey 由多个字段组成,需要把高基维度放到最前面,也就是 distinct 的字段数量在千万以上,比如 user_id 放到前面,这样字段能在过滤中起到很大作用、大幅缩小查询范围。
如果组合 Rowkey 的第一部分是时间戳,HBase又是按照 Rowkey 排序的,很可能邻近的数据存到一个 HRegionServer 里,考虑到最新的数据访问频率最高,将导致某个 HRegionServer 读请求负载过重,产生热点问题,一个可行的方案是 Rowkey 前缀加随机数,这可以保证数据均匀分布,但对数据读取造成了麻烦。和加盐类似的方案有对 Rowkey 进行哈希、翻转Rowkey (经常改变的部分放到前面)等。
数据热点问题:热点发生在大量的 client 直接访问集群的一个或极少数个节点(访问可能是读, 写或者其他操作)。大量访问会使热点 HRegion 所在的单个机器超出自身承受能力,引起性能下降甚至 HRegion 不可用,这也会影响同一个 HRegionServer 上的其他HRegion,由于主机无法服务其他 HRegion 的请求,造成资源浪费。设计良好的数据访问模式以使集群被充分、均衡的利用。
可以通过下面方式解决 HRegion 热点问题:
Hfile 是 HBase 中 KeyValue 数据的存储格式。从 HBase 物理数据模型中可以看出,HBase 是面向列表(簇)的存储。每个 Cell 由 {row key,column(=< family> + < label>),version}
唯一确定的单元,他们组合在一起就是一个 KeyValue。 根据上述描述,这个 KeyValue 中的 key 就是 {row key,column(=< family> + < label>),version}
,而 value 就是 cell 中的值。
HBase 的三维有序存储中的三维是指:rowkey( 行主键),column key(columnFamily+< label>), timestamp(时间戳或者版本号) 三部分组成的三维有序存储。
Rowkey:我们在根据 rowkey 范围查询的时候,我们一般是知道 startRowkey,如果我们通过 scan 只传 startRowKey:d开头的,那么查询的是所有比 d 大的都查了,而我们只需要 d 开头的数据,那就要通过 endRowKey 来限制。我们可以通过设定 endRowKey 为: d 开头,后面的根据你的 rowkey 组合来设定,一般是加比 startKey 大一位。
column key:column key 是第二维,数据按 rowkey 字典排序后,如果 rowkey 相同,则是根据 column key 来排序的,也是按字典排序。我们在设计 table 的时候要学会利用这一点。比如我们的收件箱,有时候需要按主题排序,那我们就可以把主题设置为我们的 column key,即设计为“columnFamily+主题”这样的设计。
timestamp:时间戳,是第三维,这是个按降序排序的,即最新的数据排在最前面。