引言
假设HBase某张表有1000个Region,里面存储着100万行数据,现在需要统计满足某些条件的行数,普通的做法是使用Filter(过滤条件),通过HBase API将满足过滤条件的行数据Scan至客户端之后进行汇总,这需要在HBase RegionServer与Client之间传送大量的数据,占用大量的网络带宽,并影响响应时间。
这是一种典型的“移动数据”的计算方案,即将所有数据传送到计算节点后进行计算,熟悉Hadoop MapReduce的人知道,MR使用的是“移动计算”,即将计算任务传送到存储数据的节点,由这些节点负责完成计算流程,仅仅只返回计算的结果,这些节点与客户端之间仅仅需要传送各自的结果数据即可,减少网络带宽的同时,很大程度提高响应时间。
对应统计行数的例子,如果我们能够将计算任务(过滤数据、汇总结果)传送至HBase中存储这些数据的Region中,由这些Region完成各自的计算任务(过滤数据、汇总结果),然后将各自的结果(每个Region中满足条件的行数)返回至客户端,由客户端对这些结果(1000个Region会返回1000个整数)进行求和,即可得出最后的满足条件的总行数。可以看出这种方式是一种理想的计数方式。
但这仅仅是我们的一种设想,HBase并不能够提前知道我们的需求是统计行数,它无法事先为我们内置这样的API,但按照我们设想的这种方式的确可以大大提高程序处理效率,而且在计数、求和、求平均值、求最大值、求最小值,甚至更为复杂的包含过滤条件的分组统计场景中(这些场景中仅仅需要由各个Region返回少量的数据,再由客户端口对这些数据进行汇总即可),能够避免大量的数据传输,提高程序处理效率,减少系统响应时间。
Endpoint
HBase Endpoint(Coprocessor)就是为实现这一目的而设计的,它支持自定义逻辑,并通过RPC机制进行调用,也可以理解为自定义扩展RPC Protocol。
实现一个Endpoint(即自定义一个RPC Protocol)涉及到以下两个步骤:
(1)创建自定义RPC Protocol接口,并继承接口CoprocessorProtocol,其中自定义RPC Protocol接口中的方法表示Client与Region的交互协议;
(2)实现自定义RPC Protocol接口,并继承类BaseEndpointCoprocessor,其中自定义RPC Protocol接口中的方法实现表示Client与Region的交互细节。
CoprocessorProtocol实例是与具体的单个Region相关联的,Client进行RPC请求时必须能够识别出应该在相应表的哪些Regions上发起CoprocessorProtocol实例方法调用,然而Region相关操作很少被Client直接处理,且Region的名称和数目经常变化,因此Endpoint使用RowKey来识别这些Regions,具体表现在HTable的三个API,如下:
<T extends CoprocessorProtocol> T coprocessorProxy(Class<T> protocol, byte[] row)
这个API使用在单个Region的场景,这个Region满足的条件是包含数据行row。
<T extends CoprocessorProtocol, R> Map<byte[],R> coprocessorExec(Class<T> protocol, byte[] startKey, byte[] endKey, Batch.Call<T,R> callable)
<T extends CoprocessorProtocol, R> void coprocessorExec(Class<T> protocol, byte[] startKey, byte[] endKey, Batch.Call<T,R> callable, Batch.Callback<R> callback)
这两个API使用在多个Region的场景,这些Region满足的条件是包含startKey——endKey范围内所有数据行的Regions。
以统计行数为例,调用过程如下图所示:
关于Endpoint的具体实现细节及部署方式,请参考《HBase The Definitive Guide》相关章节。
应用场景
在使用HBase Endpoint过程中,Region的识别由RowKey决定,而数据的过滤则通过设置Filter实现,如下所示:
long getRowCount(Filter filter) throws IOException
这样Region中的数据就可以通过filter进行过滤。
注意:Filter是在发起RPC请求之前就准备好的,作为自定义RPC Protocol的参数。
计数
各个Region返回的是各自Region(满足条件)的数据行数,Client仅需要求和即可。
最大值
各个Region返回的是各自Region的数据最大值,Client仅需要在这些返回的值中找出最大值即可。
最小值
各个Region返回的是各自Region的数据最小值,Client仅需要在这些返回的值中找出最小值即可。
求和
各个Region返回的是各自Region数据的和,Client仅需要对这些值求和即可。
求平均值
各个Region返回的是各自Region的数据行数及总和,Client需要对每个Region的数据行数及总和进行汇总,然后得出平均值。
以上都是一些比较简单的场景,主要用以说明问题而已,可以通过对RowKey、EndPoint RPC Protocol的合理设计,完成更为复杂的分组统计。