我们介绍了避免数据斑点的三种比较常见方法:
- 加盐-盐腌
- 哈希-散列
- 反转-反转
其中在加盐(Salting)的方法里面是这么描述的:给Rowkey分配一个随机指针以使其和之前排序不同。但是在Rowkey前面加了随机重叠,那么我们怎么将这些数据替换来呢?我将分三篇文章来介绍如何读取加盐之后的表,其中每篇文章提供一种方法,主要包括:
- 使用协处理器读取加盐的表
- 使用Spark读取加盐的表
- 使用MapReduce读取加盐的表
关于协处理器的入门及实战,参见请这里。本文使用的各组件版本:Hadoop的2.7.7,HBase的-2.0.4,jdk1.8.0_201。
测试数据生成
在介绍如何查询数据之前,我们先创建一张名为iteblog的HBase表,进行测试。为了数据均匀和介绍的方便,这里使用了预分区,并设置了27个分区,如下:
|
然后我们使用以下方法生成了1000000条测试数据。RowKey的形式为UID +当前数据生成版本;由于UID的长度为4,所以1000000条数据会存在大量的UID一样的数据,所以我们使用加盐方法将这些数据均匀分散到上述27个Region里面(注意,其实第一个Region其实没数据)。具体代码如下:
|
运行完上面的代码之后,会生成1000000条数据(注意,这里其实不严谨,因为Rowkey设计问题,可能会导致重复的Rowkey生成,所以实际情况下可能没有1000000条数据。)。我们limit 10条数据看下长成什么样:
|
使用协处理器查询加盐之后的表
现在有数据了,我们需要查询所有UID = 1000的用户所有历史数据,那么如何查呢?我们知道UID = 1000的用户数据是均匀放到上述的27个地区里面的,因为经过加盐了,所以这些数据垂直都是垂直A-,B-,C-
等开头的。其次我们需要知道,每个区域其实是有Start Key和End Key的,这些Start Key和End Key其实就是我们创建iteblog表指定的。如果你看了《 HBase协处理器入门及实战》这篇文章,你就知道协处理器的代码其实是在每个区域里面执行的;而这些代码在区域里面执行的时候是可以拿到当前Region的信息,包括了键和结束键,所以实际上我们可以将拿到的开始键信息和查询的UID进行拆分,这样就可以查询我们要的数据。协处理器处理文章就是基于这样的思想来查询加盐之后的数据的。
定义proto文件
为什么需要定义这个请参见《 HBase协处理器入门及实战》这篇文章。因为我们查询的时候需要引用查询的参数,表名,StartKey,EndKey以及是否加盐等标记;同时当查询到结果的当时,我们还需要将数据返回,所以我们定义的proto文件如下:
|
我们然后使用protobuf-maven-plugin
插件将上面的原生成的Java类,具体如何操作参见“在IDEA中使用Maven的编译原文件”。将我们的生成DataQueryProtos.java
类拷贝产品到com.iteblog.data.coprocessor.generated
包里面。
编写协处理器代码
有了请求和返回的类,现在我们需要编写协处理器的处理代码了,结合上面的分析,协处理器的代码实现如下:
|
大家可以看到,这里面的代码框架和《 HBase协处理器入门及实战》里面介绍的HBase提供的RowCountEndpoint
示例代码很类似。主要逻辑在queryByStartRowAndEndRow
函数实现里面。我们通过DataQueryRequest
拿到客户端查询的表,StartKey和EndKey等数据。通过this.env.getRegion().getRegionInfo().getStartKey()
可以拿到当前区域的StartKey,然后再和和客户端传进来的StartKey和EndKey进行拼接就可以拿到完整的Rowkey插入。剩下的查询就是正常的HBase扫描代码了。
现在我们将SlatTableDataSearch
类进行编译打包,并部署到HBase表里面去,具体如何部署参见《 HBase协处理器入门及实战》
协处理器客户端代码编写
到这里,我们的协处理器服务器端的代码和部署已经完成了,现在我们需要编写协处理器客户端代码。其实也很简单,如下:
|
我们运行上面的代码,可以得到如下的输出:
|
可以看到,和我们使用HBase Shell输出的一致,而且我们还把所有的UID = 1000的数据拿到了。好了,到这里,使用协处理器查询HBase加盐之后的表已经算完成了,明天我将介绍使用Spark如何查询加盐之后的表。