HBase Java API 的基本使用

This commit is contained in:
罗祥 2019-05-31 13:40:23 +08:00
parent ec22c3e62e
commit b37a5665cb

View File

@ -1,4 +1,4 @@
# Hbase Java API 的基本使用
# HBase Java API 的基本使用
<nav>
<a href="#一简述">一、简述</a><br/>
@ -11,19 +11,19 @@
## 一、简述
截至到目前2019年4月HBase 主要有1.x 和 2.x 两个主要的版本两个版本的Java API的接口和方法有所不同的1.x 中某些方法在2.x中被标识为`@deprecated`过时,所以下面关于API的样例我会分别给出1.x和2.x两个版本。完整的代码见本仓库
截至到目前(2019.04)HBase 有两个主要的版本分别是1.x 和 2.x 两个版本的Java API有所不同1.x 中某些方法在2.x中被标识为`@deprecated`过时。所以下面关于API的样例我会分别给出1.x和2.x两个版本。完整的代码见本仓库
>+ [Java API 1.x Examples](https://github.com/heibaiying/BigData-Notes/tree/master/code/Hbase/hbase-java-api-1.x)
>
>+ [Java API 2.x Examples](https://github.com/heibaiying/BigData-Notes/tree/master/code/Hbase/hbase-java-api-2.x)
同时在实际使用中,客户端的版本必须与服务端保持一致如果用2.x版本的客户端代码去连接1.x版本的服务端会抛出`NoSuchColumnFamilyException`等异常
同时你使用的客户端的版本必须与服务端版本保持一致如果用2.x版本的客户端代码去连接1.x版本的服务端会抛出`NoSuchColumnFamilyException`等异常。
## 二、Java API 1.x 基本使用
#### 2.1 新建Maven工程导入项目依赖
要使用Java API 操作HBase,仅需要引入`hbase-client`。这里我服务端的HBase版本为`hbase-1.2.0-cdh5.15.2`,对应的`Hbase client` 选取 1.2.0 版本
要使用Java API 操作HBase,需要引入`hbase-client`。这里选取的`HBase Client`的版本为`1.2.0`
```xml
<dependency>
@ -35,8 +35,6 @@
#### 2.2 API 基本使用
这里列举了常用的增删改查操作
```java
public class HBaseUtils {
@ -294,7 +292,7 @@ public class HBaseUtils {
### 2.3 单元测试
以单元测试的方式对封装的API进行测试
以单元测试的方式对上面封装的API进行测试
```java
public class HBaseUtilsTest {
@ -398,7 +396,7 @@ public class HBaseUtilsTest {
#### 3.1 新建Maven工程导入项目依赖
这里选取的`HBase Client`的版本为最新的`2.1.4`
这里选取的`HBase Client`的版本为最新的`2.1.4`
```xml
<dependency>
@ -410,13 +408,13 @@ public class HBaseUtilsTest {
#### 3.2 API 的基本使用
2.x 版本相比于1.x 废弃了一部分方法关于废弃的方法在源码中都会指明新的替代方法比如在2.x中创建表时`HTableDescriptor``HColumnDescriptor`等类都标识为废弃,且会在3.0.0版本移除,取而代之的是使用`TableDescriptorBuilder``ColumnFamilyDescriptorBuilder`来定义表和列族。在升级版本时,可以用源码中指明的新的替代方法来代替过期的方法。
2.x 版本相比于1.x 废弃了一部分方法关于废弃的方法在源码中都会指明新的替代方法比如在2.x中创建表时`HTableDescriptor``HColumnDescriptor`等类都标识为废弃,取而代之的是使用`TableDescriptorBuilder``ColumnFamilyDescriptorBuilder`来定义表和列族。
<div align="center"> <img width="700px" src="https://github.com/heibaiying/BigData-Notes/blob/master/pictures/deprecated.png"/> </div>
以下为HBase 2.x 版本Java API使用的完整示例:
以下为HBase 2.x 版本Java API使用示例:
```java
public class HBaseUtils {
@ -678,9 +676,9 @@ public class HBaseUtils {
## 四、正确连接Hbase
在上面的代码中在类加载时就初始化了Connection连接并且之后的方法都是复用这个Connection这时我们可能会考虑是否可以使用自定义连接池来获取更好的性能表现实际上这是没有必要的。
在上面的代码中在类加载时就初始化了Connection连接并且之后的方法都是复用这个Connection这时我们可能会考虑是否可以使用自定义连接池来获取更好的性能表现实际上这是没有必要的。
首先官方对于`Connection`做了如下表述
首先官方对于`Connection`的使用说明如下
```properties
Connection Pooling For applications which require high-end multithreaded
@ -690,9 +688,7 @@ as shown in the following example:
对于高并发多线程访问的应用程序例如在单个JVM中存在的为多个线程服务的Web服务器或应用程序服务器
您只需要预先创建一个Connection。例子如下
```
```java
// Create a connection to the cluster.
Configuration conf = HBaseConfiguration.create();
try (Connection connection = ConnectionFactory.createConnection(conf);
@ -715,19 +711,19 @@ Connection是一个集群连接封装了与多台服务器Matser/Region Se
之所以封装这些连接是因为HBase客户端需要连接三个不同的服务角色
+ Zookeeper主要用于获得meta-region位置集群Id、master等信息。
+ HBase Master主要用于执行HBaseAdmin接口的一些操作例如建表等
+ HBase RegionServer用于读、写数据。
+ **Zookeeper** :主要用于获取`meta`表的位置信息Master的信息
+ **HBase Master** 主要用于执行HBaseAdmin接口的一些操作例如建表等
+ **HBase RegionServer** :用于读、写数据。
<div align="center"> <img width="700px" src="https://github.com/heibaiying/BigData-Notes/blob/master/pictures/hbase-arc.png"/> </div>
Connection对象和实际的socket连接之间的对应关系如下图
Connection对象和实际的Socket连接之间的对应关系如下图
<div align="center"> <img width="700px" src="https://github.com/heibaiying/BigData-Notes/blob/master/pictures/hbase-connection.png"/> </div>
> 上面两张图片引用自博客:[连接HBase的正确姿势](https://yq.aliyun.com/articles/581702?spm=a2c4e.11157919.spm-cont-list.1.146c27aeFxoMsN%20%E8%BF%9E%E6%8E%A5HBase%E7%9A%84%E6%AD%A3%E7%A1%AE%E5%A7%BF%E5%8A%BF)
在HBase客户端代码中真正对应socket连接的是RpcConnection对象。HBase使用PoolMap这种数据结构来存储客户端到HBase服务器之间的连接。PoolMap封装了ConcurrentHashMap>的结构key是ConnectionId(封装了服务器地址和用户ticket),value是一个RpcConnection对象的资源池。当HBase需要连接一个服务器时首先会根据ConnectionId找到对应的连接池然后从连接池中取出一个连接对象。
在HBase客户端代码中真正对应Socket连接的是`RpcConnection`对象。HBase使用`PoolMap`这种数据结构来存储客户端到HBase服务器之间的连接。`PoolMap`的内部有一个`ConcurrentHashMap`实例其key是`ConnectionId`(封装了服务器地址和用户ticket)value是一个`RpcConnection`对象的资源池。当HBase需要连接一个服务器时首先会根据`ConnectionId`找到对应的连接池,然后从连接池中取出一个连接对象。
```java
@InterfaceAudience.Private
@ -744,7 +740,7 @@ public class PoolMap<K, V> implements Map<K, V> {
.....
```
HBase中提供了三种资源池的实现分别是ReusableRoundRobin和ThreadLocal。具体实现可以通hbase.client.ipc.pool.type配置项指定默认为Reusable。连接池的大小也可以通过hbase.client.ipc.pool.size配置项指定默认为1,即每个Server 1个连接。也可以通过修改配置实现
HBase中提供了三种资源池的实现分别是`Reusable``RoundRobin``ThreadLocal`。具体实现可以通`hbase.client.ipc.pool.type`配置项指定,默认为`Reusable`。连接池的大小也可以通过`hbase.client.ipc.pool.size`配置项指定默认为1即每个Server 1个连接。也可以通过修改配置实现
```java
config.set("hbase.client.ipc.pool.type",...);
@ -752,9 +748,9 @@ config.set("hbase.client.ipc.pool.size",...);
connection = ConnectionFactory.createConnection(config);
```
从以上的表述中,可以看出HBase中Connection类已经实现了对连接的管理功能所以我们不需要自己在Connection上再做额外的管理。
由此可以看出HBase中Connection类已经实现了对连接的管理功能所以我们在Connection上再做额外的管理。
另外Connection是线程安全的但Table和Admin却不是线程安全的因此正确的做法是一个进程共用一个Connection对象而在不同的线程中使用单独的Table和Admin对象。Table和Admin的获取`getTable()``getAdmin()`都是轻量级的操作,所以不必担心性能的消耗,同时使用完成后建议显示的调用`close()`方法关闭它们。
另外Connection是线程安全的但Table和Admin却不是线程安全的因此正确的做法是一个进程共用一个Connection对象而在不同的线程中使用单独的Table和Admin对象。Table和Admin的获取操作`getTable()``getAdmin()`都是轻量级,所以不必担心性能的消耗,同时建议在使用完成后显示的调用`close()`方法关闭它们。