Hbase rowkey设计时遗留的陷阱

来源:互联网 发布:yy音效软件 编辑:程序博客网 时间:2024/05/17 23:12
接触Hbase时间不长,也只是了解些皮毛。今天发现之前开发程序中的一个小bug。

 因为hbase不同于一般的关系数据库,不能很好地支持复杂的条件查询,因此rowkey的设计显得尤为重要。

我设计的rowkey是这种形式的: 商品ID#日期#机构ID#采购单号(#为字段间的分隔,方便范围查询),商品ID是一串long型的数值,具有连续性。为了充分发挥分布式的优点,需要将这些记录离散地存储在hbase集群的各节点上。此时我就将商品ID反转后再存储——Bytes.toBytes(Long.reverse(商品ID),以达到离散存储的目的。然后将这些字段分别转换成byte数组再通过Bytes.add()组装好当成rowkey。就这样我可以高效地根据rowkey去查询记录了,范围查询时只需要把startRow中的查询条件以#结尾,而stopRow的查询条件以$结尾。原因很简单#的ASCII码是35,$的ASCII码是36。

 到这里一切都很正常,问题出在读数据时对rowkey进行解析,以得到需要的字段。我起初是怎么做的呢?读取到rowkey(其实就是个byte[]),然后我根据#的字节码去做类似split的操作。split之后再做相应的转换。乍一看没什么问题,但仔细想想就会发现这么做是有风险的。上实验代码:

  byte[] a =Bytes.toBytes(Long.reverse(717252));
  byte[] b =Bytes.toBytes("#");
  for(int i =0 ; i
   System.out.print(a[i]+",");
  }
  System.out.println();
  for(int j = 0; j
   System.out.print(b[j]+",");
  }

 

输出结果为:

35,-113,80,0,0,0,0,0,
35,

 

若商品ID是717252时,在我读取rowkey并split获取字段时就会出错。正常情况我split应该得到3个字段,而这种特殊情况我就会split得到4个字段。根本原因就是商品ID在反转后转换成byte时生成了与#号相同的字节码!!于是我陷入了沉思,如何规避这样的危险呢。其实很简单,数位数呗~ long型占8字节,如果后面没有类似这样的反转,前8个字节特殊对待一下(直接截取subBytes),后边的字节就继续放心大胆地用#号split吧。

 

第一篇很水的个人技术博客,就这样ending吧~~Hbase <wbr>rowkey设计时遗留的陷阱

0 0