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

排查
1. 查看Kafka,数据确实存在2条2. 开始排查Flume是否被业务规则过滤,发现数据正常没有被过滤3. 查看HBase是否存在2条,是不是业务端过滤掉,发现HBase只有一条
现在基本确定是Flume数据丢失或者HBase数据覆盖
但是为什么会覆盖呢?
HBase多版本存储,如果RowKey一致依赖于timestamp的值
- timestamp值一样会覆盖
- timestamp值不一样会被存储为多版本
会不会是控制多版本的timestamp出了问题,在Flume业务代码中找到了以下代码。
long ts = timestamp + (Arrays.hashCode(dataBuf) & 0xffffffffl) % 1000;Put put = new Put((VID+"_"+timestamp+"_"+TYPE).getBytes(), ts);//设置时间戳
timestamp使用了终端时间,为了防止timestamp冲突,对报文体进行了hash然后取模偏移保证timestamp不冲突,好像没问题呀。
进一步思考。难道是hash值不同但是余数相同了?把数据拿下来验证。果然。。
2条报文hash值分别是3752260917 , 241739917 余数相同。
至此问题找到。
解决
在hash取模基础之后再增加序列值取模,进一步保证唯一性。
总结
其实如果协议中分包加了编号信息就不需要这么麻烦保证timestamp不冲突,但是由于国标协议缺陷导致需要特殊处理,另外HBase多版本存储要小心使用,否则会造成数据丢失。
