如何正确管理HBase的连接,从原理到实战
本文将介绍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的连接,从原理到实战的更多相关文章
- HBase存储及读写原理介绍
一.HBase介绍及其特点 HBase是一个开源的非关系型分布式数据库,它参考了谷歌的BigTable建模,实现的编程语言为Java.它是Apache软件基金会的Hadoop项目的一部分,运行于HDF ...
- IM开发基础知识补课(四):正确理解HTTP短连接中的Cookie、Session和Token
本文引用了简书作者“骑小猪看流星”技术文章“Cookie.Session.Token那点事儿”的部分内容,感谢原作者. 1.前言 众所周之,IM是个典型的快速数据流交换系统,当今主流IM系统(尤其移动 ...
- Hbase的连接池--HTablePool被Deprecated之后
说明: 最近两天在调研HBase的连接池,有了一些收获,特此记录下来. 本文先将官方文档(http://hbase.apache.org/book.html)9.3.1.1节翻译,方便大家阅读,然 ...
- ssh连接的原理
ssh是linux系统中的一个远程连接工具,也是一种网络协议,通过各种加密算法达到安全连接的效果.若能使用ssh连接到另外一台机器上,我们就可以认为是安全的.本节主要介绍的是ssh连接的原理以及ssh ...
- 管理IPv6网络连接
以下操作建立在Linux功能-管理IPv4网络连接之上,请先完成该部分操作后进行以下测试. 1. 修改 net1,配置 IPv6 地址为 2001:X/64 ,网关为 2001:254 [root@d ...
- 解决SQL Server管理器无法连接远程数据库Error: 1326错误
解决SQL Server管理器无法连接远程数据库Error: 1326错误 我们在在使用SQL Server时都会遇到使用SQL Server Management Studio无法连接远程数据库实例 ...
- 全易通人事考勤工资验厂管理系统软件创建连接SQL2000数据库的操作方法和说明
全易通人事考勤工资验厂管理系统软件创建连接SQL2000数据库的操作方法和说明.全易通人事考勤工资验厂管理系统软件,有2种数据库,一个是ACCESS,另一个是SQL.不过由于ACCESS数据库比较小, ...
- HTTP协议学习笔记---HTTP持久连接和如何正确地关闭HTTP连接
一,持久连接 什么是持久连接?对于HTTP协议而言,它是基于请求响应模型,Client向Server发请求时,先建立一条HTTP连接,Server给Client响应数据后,连接关闭. 当Client发 ...
- Foxpro数据库连接错误解决方法--【VFP DBF文件不是一个有效的路径。 确定路径名称拼写是否正确,以及是否连接到文件存放的服务器】
直接访问vfp dbf文件时报错: 错误描述: 'd:\vfpData\test.dbf'不是一个有效的路径. 确定路径名称拼写是否正确,以及是否连接到文件存放的服务器. 解决办法:Data Sour ...
随机推荐
- Java基础语法(1)-关键字与保留字
title: Java基础语法(1)-关键字与保留字 blog: CSDN data: Java学习路线及视频 1.关键字 关键字(keyword)的定义和特点 定义:被Java语言赋予了特殊含义,用 ...
- 基于 websocket 的多端桥接平台
我们现在的业务是基于新闻客户端实现的,都要经过新闻客户端的环境,进行前后端数据上的交互.但是我们在调试过程中,非常的不方便. 通常使用的工具有:modheader, postman, fiddler ...
- 毫米波大规模阵列中的AOA估计
1.AOA估计在毫米波大规模MIMO中的重要性 在毫米波大规模MIMO的CSI估计中,AoA估计具有重要地位,主要原因归纳如下: 毫米波大规模MIMO 的信道具有空域稀疏性,可以简单通过AoA 和路径 ...
- Android应用开发基本流程
Android应用开发流程 应用规划及架构设计 开发应用程序的步骤 项目有哪些功能. 需要哪些必要的界面及界面之间跳转的流程. 需要的数据及其数据的来源和格式. 是否需要服务器端的支持. 是否需要本地 ...
- 关于LSTM实现长短期记忆功能问题
2019-09-07 22:01:45 问题描述:LSTM是如何实现长短期记忆功能的? 问题求解: 与传统的循环神经网络相比,LSTM仍然是基于当前输入和之前的隐状态来计算当前的隐状态,只不过对内部的 ...
- GO语言web框架Gin之完全指南
GO语言web框架Gin之完全指南 作为一款企业级生产力的web框架,gin的优势是显而易见的,高性能,轻量级,易用的api,以及众多的使用者,都为这个框架注入了可靠的因素.截止目前为止,github ...
- [CS充实之路] CS50 WEEK 1
前言 大学电子专业,幸好自学了JAVA,遂有幸工作了三年,但这期间一直在焦虑,一个是基础不扎实的担心,另一个是未来方向的不确定.去年开始终于下定决心,一方面走一遍CS之路,巩固知识体系,另一方面部署自 ...
- PyTorch大更新!谷歌出手帮助开发,正式支持TensorBoard | 附5大开源项目
大家又少了一个用TensorFlow的理由. 在一年一度的开发者大会F8上,Facebook放出PyTorch的1.1版本,直指TensorFlow"腹地". 不仅宣布支持Tens ...
- 【Pytest03】全网最全最新的Pytest框架fixture应用篇(1)
fixtrue修饰器标记的方法通常用于在其他函数.模块.类或者整个工程调用时会优先执行,通常会被用于完成预置处理和重复操作.例如:登录,执行SQL等操作. 完整方法如下:fixture(scope=' ...
- coding++:TimeUnit 使用
TimeUnit是java.util.concurrent包下面的一个类,表示给定单元粒度的时间段 主要作用 时间颗粒度转换 延时 常用的颗粒度 TimeUnit.DAYS //天 TimeUnit. ...