HBase多版本存储导致的一个偶发问题

标签(空格分隔): HBase


现象

终端上传数据量如果超过一个阈值则会分包传输,在HBase中会存储2条数据,但是有一些报文只存储了1条丢失了1条
HBase多版本存储导致的一个偶发问题 - 图1

排查

  1. 1. 查看Kafka,数据确实存在2
  2. 2. 开始排查Flume是否被业务规则过滤,发现数据正常没有被过滤
  3. 3. 查看HBase是否存在2条,是不是业务端过滤掉,发现HBase只有一条

现在基本确定是Flume数据丢失或者HBase数据覆盖

但是为什么会覆盖呢?
HBase多版本存储,如果RowKey一致依赖于timestamp的值

  • timestamp值一样会覆盖
  • timestamp值不一样会被存储为多版本

会不会是控制多版本的timestamp出了问题,在Flume业务代码中找到了以下代码。

  1. long ts = timestamp + (Arrays.hashCode(dataBuf) & 0xffffffffl) % 1000;
  2. Put put = new Put((VID+"_"+timestamp+"_"+TYPE).getBytes(), ts);//设置时间戳

timestamp使用了终端时间,为了防止timestamp冲突,对报文体进行了hash然后取模偏移保证timestamp不冲突,好像没问题呀。

进一步思考。难道是hash值不同但是余数相同了?把数据拿下来验证。果然。。
2条报文hash值分别是3752260917 , 241739917 余数相同。

至此问题找到。

解决

在hash取模基础之后再增加序列值取模,进一步保证唯一性。

总结

其实如果协议中分包加了编号信息就不需要这么麻烦保证timestamp不冲突,但是由于国标协议缺陷导致需要特殊处理,另外HBase多版本存储要小心使用,否则会造成数据丢失。