在 《HBase Rowkey 设计指南》 文章中,我们介绍了避免数据热点的三种比较常见方法:
- 加盐 - Salting
- 哈希 - Hashing
- 反转 - Reversing
其中在加盐(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个 Region 里面的,因为经过加盐了,所以这些数据前缀都是类似于 A-,B-,C-
等开头的。其次我们需要知道,每个 Region 其实是有 Start Key 和 End Key 的,这些 Start Key 和 End Key 其实就是我们创建 iteblog 表指定的。如果你看了 《HBase 协处理器入门及实战》 这篇文章,你就知道协处理器的代码其实是在每个 Region 里面执行的;而这些代码在 Region 里面执行的时候是可以拿到当前 Region 的信息,包括了 Start Key 和 End Key,所以其实我们可以将拿到的 Start Key 信息和查询的 UID 进行拼接,这样就可以查询我们要的数据。协处理器处理篇就是基于这样的思想来查询加盐之后的数据的。
定义 proto 文件
为什么需要定义这个请参见 《HBase 协处理器入门及实战》 这篇文章。因为我们查询的时候需要传入查询的参数,比如tableName、 StartKey 、 EndKey 以及是否加盐等标记;同时当查询到结果的时候,我们还需要将数据返回,所以我们定义的 proto 文件如下:
|
然后我们使用 protobuf-maven-plugin
插件将上面的 proto 生成 java 类,具体如何操作参见 《在 IDEA 中使用 Maven 编译 proto 文件》。我们将生成的 DataQueryProtos.java
类拷贝到 com.iteblog.data.coprocessor.generated
包里面。
编写协处理器代码
有了请求和返回的类,现在我们需要编写协处理器的处理代码了,结合上面的分析,协处理器的代码实现如下:
|
大家可以看到,这里面的代码框架和 《HBase 协处理器入门及实战》 里面介绍的 HBase 提供的 RowCountEndpoint
示例代码很类似。主要逻辑在 queryByStartRowAndEndRow
函数实现里面。我们通过 DataQueryRequest
拿到客户端查询的表,StartKey 和 EndKey 等数据。通过 this.env.getRegion().getRegionInfo().getStartKey()
可以拿到当前 Region 的 StartKey,然后再和客户端传进来的 StartKey 和 EndKey 进行拼接就可以拿到完整的 Rowkey 前缀。剩下的查询就是正常的 HBase Scan 代码了。
现在我们将 SlatTableDataSearch
类进行编译打包,并部署到 HBase 表里面去,具体如何部署参见 《HBase 协处理器入门及实战》
协处理器客户端代码编写
到这里,我们的协处理器服务器端的代码和部署已经完成了,现在我们需要编写协处理器客户端代码。其实也很简单,如下:
|
我们运行上面的代码,可以得到如下的输出:
|
可以看到,和我们使用 HBase Shell 输出的一致,而且我们还把所有的 UID = 1000 的数据拿到了。好了,到这里,使用协处理器查询 HBase 加盐之后的表已经算完成了,明天我将介绍使用 Spark 如何查询加盐之后的表。