本文将介绍HBase的客户端连接实现,并说明如何正确管理HBase的连接。

最近在搭建一个HBase的可视化管理平台,搭建完成后发现不管什么查询都很慢,甚至于使用api去listTable都要好几秒。

经过一番排查发现,是每次请求的时候,都去临时创建了一个connection,而创建connection非常耗时导致整体的rt上升。

因此,就深入了解了下如何正确管理HBase的connection,同时,也在优化过程中有些小细节的总结。

本文基于hbase 2.0.0版本的源码,github上3.0版本的源码已经有很大差异了,但是思想还是差不多的

1.HBase-client和HBase是如何连接的?

这个问题实际上在我之前的文章 深入HBase读写 中介绍过。

当HBase-client第一次请求读写的时候,需要三步走:

1)HBase-client从zk中获取保存meta table的位置信息,知道meta table保存在了哪个region server,然后缓存这个位置信息;

2)HBase-client会查询这个保存meta table的特定的region server,查询meta table信息,在table中获取自己想要访问的row key所在的region在哪个region server上。

3)客户端直接访问目标region server,获取对应的row

所以,我们知道hbase-client实际上包含三部分连接:

  • 跟zk连接,获取相关元信息
  • 跟HMaster连接,做相关DDL操作
  • 直接跟各个region server进行连接,进行增删改查

2.HBase客户端连接原理

常规写法是这样的

Connection connection = ConnectionFactory.createConnection(conf);

try {
Table table = connection.getTable(TableName.valueOf("tablename”));
// 插入数据
Put put = new Put(Bytes.toBytes("row"));
put.addColumn(Bytes.toBytes("family"), Bytes.toBytes("qualifier"), Bytes.toBytes("value"));
table.put(put);
// 单行读取
Get get = new Get(Bytes.toBytes("row"));
Result res = table.get(get);
// 删除一行数据
Delete delete = new Delete(Bytes.toBytes("row"));
table.delete(delete);
}catch (IOException e) {
//.....
} finally {
table.close();
connection.close();
}

我们不禁有这样的疑问:

1)HBase没有连接池吗?

2)connection表示的是一个连接吗?

3)connection每个线程都得创建吗?线程安全吗?

4)table每个线程都得创建吗?线程安全吗?

下面一一解答。

首先,Connection是线程安全的,而Table和Admin则不是线程安全的。

因此正确的做法是一个进程(或服务)使用一个Connection对象,而在不同的线程中使用单独的Table和Admin对象。

Connection持有RpcClient,RpcClient管理了一个连接池poolMap

protected final PoolMap<ConnectionId, T> connections;

//….

this.connections = new PoolMap<>(getPoolType(conf), getPoolSize(conf));

通过AbstractRpcClient的getConnection看到,连接T继承RpcConnection,叫做NettyRpcConnection。

这里顺便通过getPoolType和getPoolSize看了下线程池的大小和类型。

在枚举类PoolType中有三种线程池类型Reusable, ThreadLocal, RoundRobin,用户可以用hbase.client.ipc.pool.type指定线程池类型,通过hbase.client.ipc.pool.size指定线程池大小(默认是1)。

3.优化实践

搞清楚上面的原理后,下面就可以开始优化我们的HBase管理平台了。

只需要对每个HBase集群的connection使用Map保存下来,每次请求的时候拿出对应的connection进去相关操作即可。然后需要注意在系统退出的时候关闭所有的connection。

上代码:

public class ConnectionManager {
private Map<String, Connection> connectionMap = new ConcurrentHashMap<>(); public Connection getConnection(String resourceId, Configuration configuration) {
ResourceInfo resourceInfo = ResourceInfoCache.getResourceInfoByCache(resourceId);
if (resourceInfo == null) {
throw new IllegalArgumentException("error resourceid: " + resourceId);
}
String key = getClusterKey(resourceInfo);
if (connectionMap.containsKey(key)) {
return connectionMap.get(key);
}
synchronized (this) {
//DCL检查
if (connectionMap.containsKey(key)) {
return connectionMap.get(key);
}
Connection connection = null;
try {
connection = ConnectionFactory.createConnection(configuration);
} catch (IOException e) {
return null;
}
connectionMap.put(key, connection);
return connection;
}
} @PreDestroy
public void doDestroy() {
for (Map.Entry<String, Connection> entry : connectionMap.entrySet()) {
Connection connection = entry.getValue();
if (connection != null) {
try {
connection.close();
} catch (IOException e) {
//。。。。
}
}
}
}
}

这里有几个注意点:

  • 将ConnectionManager注册为bean,交给spring容器管理生命周期,同时保证单例。
  • 使用@PreDestroy保证应用关闭时,能正确释放所有连接,避免连接泄漏
  • connectionMap使用ConcurrentHashMap保证线程安全
  • DCL检查,避免重复创建同一个connection,浪费资源;并且避免重复创建connection后,无法关闭导致连接泄漏。

在需要查询时,只需要通过getConnection获取已经存在的connection即可。

当然,如果是普通的应用使用HBase-client,一般只需要对一个HBase的集群创建全局唯一的一个Connection即可(一般交给spring容器管理),每次请求的时候,创建对应的Table进行CRUD。

看到这里了,原创不易,点个关注、点个赞吧,你最好看了~

知识碎片重新梳理,构建Java知识图谱:https://github.com/saigu/JavaKnowledgeGraph(历史文章查阅非常方便)

扫码关注我的公众号“阿丸笔记”,第一时间获取最新更新。同时可以免费获取海量Java技术栈电子书、各个大厂面试题。

如何正确管理HBase的连接,从原理到实战的更多相关文章

  1. HBase存储及读写原理介绍

    一.HBase介绍及其特点 HBase是一个开源的非关系型分布式数据库,它参考了谷歌的BigTable建模,实现的编程语言为Java.它是Apache软件基金会的Hadoop项目的一部分,运行于HDF ...

  2. IM开发基础知识补课(四):正确理解HTTP短连接中的Cookie、Session和Token

    本文引用了简书作者“骑小猪看流星”技术文章“Cookie.Session.Token那点事儿”的部分内容,感谢原作者. 1.前言 众所周之,IM是个典型的快速数据流交换系统,当今主流IM系统(尤其移动 ...

  3. Hbase的连接池--HTablePool被Deprecated之后

      说明: 最近两天在调研HBase的连接池,有了一些收获,特此记录下来. 本文先将官方文档(http://hbase.apache.org/book.html)9.3.1.1节翻译,方便大家阅读,然 ...

  4. ssh连接的原理

    ssh是linux系统中的一个远程连接工具,也是一种网络协议,通过各种加密算法达到安全连接的效果.若能使用ssh连接到另外一台机器上,我们就可以认为是安全的.本节主要介绍的是ssh连接的原理以及ssh ...

  5. 管理IPv6网络连接

    以下操作建立在Linux功能-管理IPv4网络连接之上,请先完成该部分操作后进行以下测试. 1. 修改 net1,配置 IPv6 地址为 2001:X/64 ,网关为 2001:254 [root@d ...

  6. 解决SQL Server管理器无法连接远程数据库Error: 1326错误

    解决SQL Server管理器无法连接远程数据库Error: 1326错误 我们在在使用SQL Server时都会遇到使用SQL Server Management Studio无法连接远程数据库实例 ...

  7. 全易通人事考勤工资验厂管理系统软件创建连接SQL2000数据库的操作方法和说明

    全易通人事考勤工资验厂管理系统软件创建连接SQL2000数据库的操作方法和说明.全易通人事考勤工资验厂管理系统软件,有2种数据库,一个是ACCESS,另一个是SQL.不过由于ACCESS数据库比较小, ...

  8. HTTP协议学习笔记---HTTP持久连接和如何正确地关闭HTTP连接

    一,持久连接 什么是持久连接?对于HTTP协议而言,它是基于请求响应模型,Client向Server发请求时,先建立一条HTTP连接,Server给Client响应数据后,连接关闭. 当Client发 ...

  9. Foxpro数据库连接错误解决方法--【VFP DBF文件不是一个有效的路径。 确定路径名称拼写是否正确,以及是否连接到文件存放的服务器】

    直接访问vfp dbf文件时报错: 错误描述: 'd:\vfpData\test.dbf'不是一个有效的路径. 确定路径名称拼写是否正确,以及是否连接到文件存放的服务器. 解决办法:Data Sour ...

随机推荐

  1. 如何将自己的测试脚本分离成PO模式的测试框架

    1 PO模式 1.1 PO模式介绍 Page Object Model 测试页面和测试脚本分离,即页面封装成类,供测试脚本调用. (将项目分为page.py和test.py) 测试用例:就是excel ...

  2. RabbitMQ 在Ubuntu18.04上的安装

    1.安装erlang由于rabbitMq需要erlang语言的支持,在安装rabbitMq之前需要安装erlang sudo apt-get install erlang2.安装Rabbitmq更新源 ...

  3. Chrome EC框架探索_0.0_引言

    0.0 引言 嵌入式硬件抽象框架常常面临着这样的尴尬:封装层次较高的(arduino,mbed)不能充分暴露必要的API并面临着性能问题,封装层次较低的(HAL,LL)接口复杂且开发困难.近日发现的一 ...

  4. [dp+博弈]棋盘的必胜策略

    链接:https://ac.nowcoder.com/acm/problem/21797来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言65536K ...

  5. innobackupex备份过程(有图有真相)

    innobackupex命令构成: 1. Innobackupex内部封装了xtrabackup和mysqldump命令: 2. Xtrabackup是用来备份innoDB表的,内部实现对innoDB ...

  6. “GANs”与“ODEs”:数学建模的终结?

    在本文中,我想将经典数学建模和机器学习之间建立联系,它们以完全不同的方式模拟身边的对象和过程.虽然数学家基于他们的专业知识和对世界的理解来创建模型,而机器学习算法以某种隐蔽的不完全理解的方式描述世界, ...

  7. PTA-7-20 表达式转换(中缀转后缀,带括号,负数,小数转换)

    本题考点:中缀表达式转后缀表达式. 难点: 带有小数的数字 数字可能带有正负号 题目描述: 算术表达式有前缀表示法.中缀表示法和后缀表示法等形式.日常使用的算术表达式是采用中缀表示法,即二元运算符位于 ...

  8. 深入理解Java AIO(二)—— AIO源码解析

    深入理解Java AIO(二)—— AIO源码解析 这篇只是个占位符,占个位置,之后再详细写(这个之后可能是永远) 所以这里只简单说一下我看了个大概的实现原理,具体的等我之后更新(可能不会更新了) 当 ...

  9. Javascript/Jquery实现日期前一天后一天

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...

  10. UVA11300 Spreading the Wealth 数学

    前方数学警告 题目链接:https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=25&am ...