使用HBase Coprocessor协处理器

2024-08-27 11:48

本文主要是介绍使用HBase Coprocessor协处理器,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原文:

http://www.zhyea.com/2017/04/13/using-hbase-coprocessor.html

HBase的Coprocessor是模仿谷歌BigTable的Coprocessor模型实现的。

Coprocessor提供了一种机制可以让开发者直接在RegionServer上运行自定义代码来管理数据。

首先必须要指明使用Coprocessor还是存在一些风险的。Coprocessor是HBase的高级功能,本来是只为HBase系统开发人员准备的。因为Coprocessor的代码直接在RegionServer上运行,并直接接触数据,这样就带来了数据破坏的风险,比如“中间人攻击(Man-in-the-MiddleAttack,简称“MITM攻击”,见百度词条)”以及其他类型的恶意入侵。目前还没有任何机制来屏蔽Coprocessor导致的数据破坏。此外,因为没有资源隔离,一个即使不是恶意设计的但表现不佳的Coprocessor也会严重影响集群的性能和稳定性。

通常我们访问HBase的方式是使用scan或get获取数据,使用Filter过滤掉不需要的部分,最后在获取到的数据上进行业务运算。但是在数据量非常大的时候,比如一个有上亿行及十万个列的数据集,再按常用的方式移动获取数据就会在网络层面遇到瓶颈。客户端也需要有强大的计算能力以及足够的内存来处理这么多的数据。此外,这也会使客户端的代码变得庞大而复杂。

这种场景正是Coprocessor可以发挥作用的地方。我们可以将业务运算代码封装到Coprocessor中并在RegionServer上运行,即在数据实际存储位置执行,最后将运算结果返回到客户端。

如下的一些理论可以帮助我们理解Coprocessor是如何发挥作用的:

触发器和存储过程:一个Observer Coprocessor有些类似于关系型数据库中的触发器,通过它我们可以在一些事件(如Get或是Scan)发生前后执行特定的代码。Endpoint Coprocessor则类似于关系型数据库中的存储过程,因为它允许我们在RegionServer上直接对它存储的数据进行运算,而非是在客户端完成运算。

MapReduce:MapReduce的原则就是将运算移动到数据所处的节点。Coprocessor也是按照相同的原则去工作的。

AOP:如果熟悉AOP的概念的话,可以将Coprocessor的执行过程视为在传递请求的过程中对请求进行了拦截,并执行了一些自定义代码。

Coprocessor类型

Coprocessor可以分为两大类:Observer Coprocessors(观察者)和EndPoint Coprocessor(终端)。

Observer Coprocessors

Observer Coprocessor在一个特定的事件发生前或发生后触发。在事件发生前触发的Coprocessor需要重写以pre作为前缀的方法,比如prePut。在事件发生后触发的Coprocessor使用方法以post作为前缀,比如postPut。

Observer Coprocessor的使用场景如下:

  • 安全性:在执行Get或Put操作前,通过preGet或prePut方法检查是否允许该操作;
  • 引用完整性约束:HBase并不直接支持关系型数据库中的引用完整性约束概念,即通常所说的外键。但是我们可以使用Coprocessor增强这种约束。比如根据业务需要,我们每次写入user表的同时也要向user_daily_attendance表中插入一条相应的记录,此时我们可以实现一个Coprocessor,在prePut方法中添加相应的代码实现这种业务需求。
  • 二级索引:可以使用Coprocessor来维持一个二级索引。这里暂不展开,有时间会单独说明。

根据作用的对象,Observer Coprocessor有如下几种:RegionObserver、RegionServerObserver、MasterObserver和WalObserver。我们可以通过这些Observer来处理其观察的对象的操作,比如可以通过RegionObserver处理Region相关的事件,如Get和Put操作。

Endpoint Coprocessor

Endpoint Coprocessor可以让开发者在数据本地执行运算。一个典型的案例:一个table有几百个Region,需要计算它的运行平均值或者总和。

Observer Coprocessor中代码的执行是相对透明的,而对于Endpoint Coprocessor,则需要显式的调用Table, HTableInterface或者HTable中的CoprocessorService()方法才能使之执行。

从0.96版本开始,HBase开始使用Google的protobuff。这对Endpoint Coprocessor的开发多少有一些影响。Endpoint Coprocessor不应该使用HBase内部成员,尽量只使用公共的API,最理想的情况应该是只依赖接口和数据结构。这样可以使开发的Endpoint Coprocessor更加健壮,不会受到HBase内核演进的干扰。注释为private或evolving的HBase内部API在删除前不必遵守关于deprecate的语义版本规则或相关的一般java规则。而使用protobuff生成的文件不会受到这些注释的影响,因为这些文件是用protoc工具自动生成的。在生成时这些文件时,protoc不知道也不会考虑HBase是如何工作的。

装载和卸载Coprocessor

要使用Coprocessor,就需要先完成对其的装载。这可以静态实现(通过HBase配置文件),也可以动态完成(通过shell或Java API)。

静态装载和卸载Coprocessor

按以下如下步骤可以静态装载自定义的Coprocessor。需要注意的是,如果一个Coprocessor是静态装载的,要卸载它就需要重启HBase。

静态装载步骤如下:

1. 在hbase-site.xml中使用<property>标签定义一个Coprocessor。<property>的子元素<name>的值只能从下面三个中选一个:

  • hbase.coprocessor.region.classes 对应 RegionObservers和Endpoints;
  • hbase.coprocessor.wal.classes 对应 WALObservers;
  • hbase.coprocessor.master.classes 对应MasterObservers。

而<value>标签的内容则是自定义Coprocessor的全限定类名。

下面演示了如何装载一个自定义Coprocessor(这里是在SumEndPoint.java中实现的),需要在每个RegionServer的hbase-site.xml中创建如下的记录:

如果要装载多个类,类名需要以逗号分隔。HBase会使用默认的类加载器加载配置中的这些类,因此需要将相应的jar文件上传到HBase服务端的类路径下。

使用这种方式加载的Coprocessor将会作用在HBase所有表的全部Region上,因此这样加载的Coprocessor又被称为系统Coprocessor。在Coprocessor列表中第一个Coprocessor的优先级值为Coprocessor.Priority.SYSTEM,其后的每个Coprocessor的值将会按序加一(这意味着优先级会减降低,因为优先级是按整数的自然顺序降序排列的)。

当调用配置的Observer Coprocessor时,HBase将会按照优先级顺序依次调用它们的回调方法。

2. 将代码放到HBase的类路径下。一个简单的方法是将封装好的jar(包括代码和依赖)放到HBase安装路径下的/lib目录中。

3. 重启HBase。

静态卸载的步骤如下:

1. 移除在hbase-site.xml中的配置。

2. 重启HBase。

3. 这一步是可选的,将上传到HBase类路径下的jar包移除。

动态装载Coprocessor

动态装载Coprocessor的一个优势就是不需要重启HBase。不过动态装载的Coprocessor只是针对某个表有效。因此,动态装载的Coprocessor又被称为表级Coprocessor。

此外,动态装载Coprocessor是对表的一次schema级别的调整,因此在动态装载Coprocessor时,目标表需要离线。

动态装载Coprocessor有两种方式:通过HBase Shell和通过Java API。

在下面介绍关于动态装载的部分,假设已经封装好了一个coprocessor.jar的包,里面包含实现代码及所有的依赖,并且已经将这个jar上传到了HDFS中。

通过HBase Shell动态装载和卸载

装载步骤如下

1. 在HBase Shell中disable 掉目标表

2. 使用类似如下的命令加载Coprocessor

简单解释下这个命令。这条命令在一个表的table_att中添加了一个新的属性“Coprocessor”。使用的时候Coprocessor会尝试从这个表的table_attr中读取这个属性的信息。这个属性的值用管道符“|”分成了四部分:

  • 文件路径:文件路径中需要包含Coprocessor的实现,并且对所有的RegionServer都是可达的。这个路径可以是每个RegionServer的本地磁盘路径,也可以是HDFS上的一个路径。通常建议是将Coprocessor实现存储到HDFS。HBASE-14548允许使用一个路径中包含的所有的jar,或者是在路径中使用通配符来指定某些jar,比如:hdfs://<namenode>:<port>/user/<hadoop-user>/ 或者 hdfs://<namenode>:<port>/user/<hadoop-user>/*.jar。需要注意的是如果是用路径来指定要加载的Coprocessor,这个路径下的所有jar文件都会被加载,不过该路径下的子目录中的jar不会被加载。另外,如果要用路径指定Coprocessor时,就不要再使用通配符了。这些特性在Java API中也得到了支持。
  • 类名:Coprocessor的全限定类名。
  • 优先级:一个整数。HBase将会使用优先级来决定在同一个位置配置的所有Observer Coprocessor的执行顺序。这个位置可以留白,这样HBase将会分配一个默认的优先级。
  • 参数(可选的):这些值会被传递给要使用的Coprocessor实现。这个项是可选的。

3. enable这个表

4. 检验Coprocessor是否被加载

Coprocessor可以在TABLE_ATTRIBUTES中找到。

加载步骤就是这样。

卸载步骤如下

1. disbale目标表

2. 使用alter命令移除掉Coprocessor

3. enable目标表

使用Java API动态装载和卸载

装载方式如下

针对不同版本的HBase会有不同的JavaAPI。幸运的是有一个全版本的Java API。下面的代码演示了是如何使用Java API来装载Coprocessor的:

0.96及更高版本的HBase还有另一套API。在这套API里,HTableDescriptor的addCoprocessor()方法提供了一种更简单的方式来动态加载Coprocessor:

卸载方式如下:

卸载方式就是重新加载表定义信息。重新加载的时候就不需要再使用setValue()方法或者是addCoprocessor()方法设置表的Coprocessor信息了:

对于0.96及更高版本的HBase,可以使用HTableDescriptor类的removeCoprocessor()方法。

Coprocessor示例程序

在写示例程序之前,先假设一个场景:我们有一张名为“users”的表,包含personalDet和salaryDet两个列族。这两个列族中分别记录了个人信息和薪资信息的详情。具体如下表:


personalDetsalaryDet
rowkeynamelastnamedobgrossnetallowances
adminAdminAdmin



cdickensCharlesDickens02/07/18121000080002000
jverneJulesVerne02/08/18281200090003000
Observer 实例

现在我们写一个Observer Coprocessor,目标是阻止在对users表进行scan或get时获取admin用户的信息。具体步骤如下:

  • 实现RegionObserver接口。
  • 重写preGetOp()方法(preGet()方法已经过时)检查客户端有没有查询行键为“admin”的记录。如果有的话直接返回空结果,没有的话,正常处理请求。
  • 将代码和依赖封装成一个jar。
  • 上传jar到HDFS——HBase需要能访问到这个HDFS。
  • 加载Coprocessor。
  • 编写测试程序进行测试。

下面是Coprocessor的实现:

重写preGetOp方法将只对Get操作生效,要对scan生效还需要重写preScannerOpen()方法来从scan结果中过滤掉“admin”的信息:

现在代码可以工作了,不过还存在一个问题:如果客户端在scan的时候也使用了Filter,客户端使用的Filter就会被这个FIlter覆盖掉。这不是一个好方法,所以我们可以在查询结果上做手脚,从查询结果中删除掉行键为“admin”的记录:

Endpoint实例

还是对users表进行处理。这次的目标是计算所有员工的薪资的总和。需要编写一个Endpoint Coprocessor,步骤如下:

1. 创建一个“.proto”文件定义服务

“.proto”是protobuff的对象描述文件,使用前需要先安装protobuff,目前使用的版本应该还是2.5版本。

2. 执行protoc命令,通过“.proto”文件生成Java代码

根据文件描述定义将会生成一个名为Sum.java的文件。

3. 编写一个Coprocessor类,实现Coprocessor和CoprocessorService两个接口,并实现接口中定义的方法:

4. 加载Coprocessor

5. 编写客户端代码调用Coprocessor

部署Coprocessor的原则

更新Coprocessor

更新动态部署的Coprocessor并不是简单地disable表,替换jar,然后重新启用Coprocessor。在JVM中,如果一个类还有引用,我们就无法重新加载它。因为当前的JVM对自定义的Coprocessor还有引用,要完成更新就需要重启JVM,也就是重启RegionSever。

关于日志

Coprocessor框架并没有提供日志相关的API。

注意事项

重复加载Coprocessor

如果我们先静态加载了一个Coprocessor,而后又通过HBase Shell动态加载了一次这个Coprocessor。那么先加载的Coprocessor并不会被覆盖,而是会同时存在两个Coprocessor实例。第二个Coprocessor会有更低的优先级,换句话说,重复加载的第二个Coprocessor实例实际上没有发挥作用。

################


这篇关于使用HBase Coprocessor协处理器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1111585

相关文章

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

pdfmake生成pdf的使用

实际项目中有时会有根据填写的表单数据或者其他格式的数据,将数据自动填充到pdf文件中根据固定模板生成pdf文件的需求 文章目录 利用pdfmake生成pdf文件1.下载安装pdfmake第三方包2.封装生成pdf文件的共用配置3.生成pdf文件的文件模板内容4.调用方法生成pdf 利用pdfmake生成pdf文件 1.下载安装pdfmake第三方包 npm i pdfma

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

git使用的说明总结

Git使用说明 下载安装(下载地址) macOS: Git - Downloading macOS Windows: Git - Downloading Windows Linux/Unix: Git (git-scm.com) 创建新仓库 本地创建新仓库:创建新文件夹,进入文件夹目录,执行指令 git init ,用以创建新的git 克隆仓库 执行指令用以创建一个本地仓库的

【北交大信息所AI-Max2】使用方法

BJTU信息所集群AI_MAX2使用方法 使用的前提是预约到相应的算力卡,拥有登录权限的账号密码,一般为导师组共用一个。 有浏览器、ssh工具就可以。 1.新建集群Terminal 浏览器登陆10.126.62.75 (如果是1集群把75改成66) 交互式开发 执行器选Terminal 密码随便设一个(需记住) 工作空间:私有数据、全部文件 加速器选GeForce_RTX_2080_Ti

【Linux 从基础到进阶】Ansible自动化运维工具使用

Ansible自动化运维工具使用 Ansible 是一款开源的自动化运维工具,采用无代理架构(agentless),基于 SSH 连接进行管理,具有简单易用、灵活强大、可扩展性高等特点。它广泛用于服务器管理、应用部署、配置管理等任务。本文将介绍 Ansible 的安装、基本使用方法及一些实际运维场景中的应用,旨在帮助运维人员快速上手并熟练运用 Ansible。 1. Ansible的核心概念