在过滤器的底层最基础的是Filter接口和FilterBase抽象类,它们实现了过滤器的空壳和骨架,避免重复结构的代码。大部分实体过滤器一般直接继承FilterBase,或者间接继承该类。使用流程都是实例化一个过滤器传递给Scan和Get实例。
在初始化过滤器的时候需要指定参数,一部分过滤器继承了CompareFilter,需要指定两个参数。
继承自CompareFilter的过滤器比基类FilterBase多了一个compare方法,它需要一个比较运算符参数来自定义比较操作过程。
操作 | 描述 |
---|---|
LESS | 小于设定的值 |
LESS_OR_EQUAL | 小于等于设定的值 |
EQUAL | 等于设定的值 |
NOT_EQUAL | 不等于设定的值 |
GREATER_OR_EQUAL | 大于等于设定的值 |
GREATER | 大于设定的值 |
NO_OP | 排除一切设定的值 |
CompareFilter需要的第二类型是比较器。比较器都继承自WritableByteArrayComparable,该类继承了Compare和Writable接口。
操作 | 描述 |
---|---|
BinnaryCompartor | 使用Bytes.compareTo比较当前值与阙值 |
BinnaryPrefixCompartor | 与上面一样,只不过只匹配左边的 |
NullCompartor | 不做匹配,只判断是否为空值 |
BitCompartor | 使用BitWiseOp的or,and,xor进行匹配 |
RegexStringCompartor | 使用正则表达式匹配 |
SubStringCompartor | 根据匹配字段匹配,相当于contains |
后三种比较器只能与EQUALH和NOT_EQUAL搭配使用,因为它们的CompareTo返回值为0或1
比较器过滤器 | 描述 |
---|---|
RowFilter | 行过滤器 |
FamilyFilter | 列族过滤器 |
QualifierFilter | 列过滤器 |
ValueFilter | 值过滤器 |
DependentCloumnFilter | 参考列过滤器,得到与参考列时间戳相同的列 |
专用过滤器 | 描述 |
---|---|
SingleCloumnValueFilter | 单列值过滤器,匹配值相同的列的最新一列数据,若参数设为false则匹配所有版本的数据 |
SingleCloumnValueExcludeFilter | 单列排除过滤器,排除匹配的列 |
PrefixFilter | 前缀过滤器 |
PageFilter | 分页过滤器,通过pagesize参数可以调整返回的条数,在物理分离的region上返回的结果可能使分页过滤器失效,可以考虑在客户端进行处理 |
KeyOnlyFilter | 只返回匹配的键,不返回数据。其有一个lenAsVal可以用来二次排序,快速迭代所有列 |
FirstKeyOnlyFilter | 首次行键过滤器,只访问最近的一列,可以用来行数统计 |
InclusiveStopFilter | 排除终止行 |
TimeStampsFilter | 时间戳过滤器 |
CloumnCountGetFilter、CloumnPaginationFilter、CloumnPrefixFilter、 RandomFilter | 限制每行最多取多少列 对一行的列进行分页 前缀过滤器 随机过滤器,需要传递一个0-1的参数,-1表示过滤所有,大于1表示返回所有 |
SkipFilter 跳转过滤器 过滤匹配列的该行数据
WhileMatchFilter 全匹配过滤器 只要有一列匹配则放弃整个扫描
我们可以使用FilterList来任意组合不同过滤器的功能,但只能有一个比较运算符。也可以通过过滤器的顺序来精确的过滤。
用户可以实现Filter接口或者继承FilterBase来自定义一个过滤器。接口中有一个公用的枚举类型ReturnCode,它被filterKeyValue用来通知执行框架下一步的工作。
自定义的过滤器需要打成jar包上传到服务器,并且在hbase-env.xml中进行配置。并重启hbase的守护进程。
用户可以使用计数器来对long型的列计数,从而放弃延迟较高的批处理操作。客户端API提供了专门的方法来完成这种读取并修改操作。同时在单独一次客户端操作中保持原子性。
客户端不用初始化计数器,当用户第一次使用计数器时,计数器将会被置为0。也就是说用户创建一个新列时,计数器为0。操作一次,计数器加1。用户可以通过Bytes来读写计数器的值。需要通过Bytes.toLong来解码,要求值为long型。可以使用incr命令来操作计数器。
可以通过Htable的IncrementCloumnValue来对单列的计数器进行操作。
另一个增加计数器的方法是Htable的increment。用户需要构造一个Increment实例,并传入行键。
协处理器允许用户进行region级别的操作,将部分计算推送到服务器端。协处理器主要包含两大类observer和endpoint。
所有的协处理器都要实现这个接口,它定义了协处理器的一些基本协议。Priority和State是两个被用于框架管理的枚举类。在协处理器的生命周期中,start和stop方法会被框架隐式调用。CoprocessorHost负责维护协处理器的实例和环境。
静态加载:可以通过配置hbase-site.xml来静态加载协处理器
动态加载:禁用表后使用alter命令加载协处理器。也可以通过java api重新定义表,这会使其上的协处理器失效
静态加载的协处理器称之为 System Coprocessor(系统级协处理器),作用范围是整个 HBase 上的所有表,需要重启HBase服务;
动态加载的协处理器称之为 Table Coprocessor(表处理器),作用于指定的表,不需要重启 HBase 服务。
适用场景:
权限校验:在执行Get
或Put
操作之前,可以使用preGet
或prePut
方法检查权限;
完整性约束: HBase 不支持关系型数据库中的外键功能,可以通过触发器在插入或者删除数据的时候,对关联的数据进行检查;
二级索引:使用钩子关联行修改操作来维护二级索引。
目前 HBase 内置实现的 Observer 主要有以下几个:
Endpoint 和 RDMBS 的存储过程很类似,用户提供一些自定义代码,并在 HBase 服务器端执行,结果通过 RPC 返回给客户,Endpoint 可以实现 min、 max、 avg、 sum、 distinct、 group by 等功能。
服务端代码需要Protobuf 插件,来序列rpc协议的代码。并且实现RegionCoprocessor和Coproceseor接口,并实现一个返回该服务的方法getServices。
创建一个HTable实例是一个非常耗时的操作。多线程情况下复用Htable还会造成线程安全问题。所以客户端提供了一个Htable线程池来共享Htable实例
每个客户端都需要通过zookeeper来对region进行寻址和查询-ROOT和.META资源,为了减少网络传输开销,客户端提供了Hconnection来共享连接