如何正确管理HBase的连接,从原理到实战「建议收藏」

如何正确管理HBase的连接,从原理到实战「建议收藏」本文将介绍HBase的客户端连接实现,并说明如何正确管理HBase的连接。 最近在搭建一个HBase的可视化管理平台,搭建完成后发现不管什么查询都很慢,甚至于使用api去listTable都要好几秒…

如何正确管理HBase的连接,从原理到实战

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

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

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

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

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

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

这个问题实际上在我之前的文章 深入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();     
}

代码100分

我们不禁有这样的疑问:

1)HBase没有连接池吗?

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

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

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

下面一一解答。

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

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

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

代码100分protected final PoolMap<ConnectionId, T> connections;

//….

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

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

如何正确管理HBase的连接,从原理到实战

 

这里顺便通过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技术栈电子书、各个大厂面试题。

阿丸笔记

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/8931.html

(0)
上一篇 2023-02-19
下一篇 2023-02-19

相关推荐

  • 了解Python中的float函数

    了解Python中的float函数在Python编程中,很多情况下需要用到数字,而数字又分为整数和浮点数。其中浮点数是一种有小数点的数字类型。在这篇文章中,我们将会深入了解Python语言中float函数的用法以及相关知识。

    2024-06-15
    62
  • 无法打开sql server的连接53_无法连接sql server

    无法打开sql server的连接53_无法连接sql server 这个报错一般两个原因,SQL SERVER实例服务未启动。 或者服务未配置1433端口。 配置1433端口是需要注意,配置一个本地IP的端口,还需要配置一个IPALL的端口,全都配置为143…

    2023-03-25
    153
  • MySQL学习笔记(15):SQL Mode

    MySQL学习笔记(15):SQL Mode本文更新于2019-06-29,使用MySQL 5.7,操作系统为Deepin 15.4。 与其他数据库不同,MySQL可以运行在不同的SQL Mode(SQL模式)下。 可通过变量@@sql_mod

    2023-03-19
    146
  • MySQL学习总结之路(服务与数据库管理)[亲测有效]

    MySQL学习总结之路(服务与数据库管理)[亲测有效]今天开始通过自学MySQL总结一些方法和一些基础的内容,写在这里,和大家一起讨论学习进步。(现在东西少,第一次写有这类结构的东西,过几天会出一个整体目录结构,方便查看) 安装部署直接跳过,我使用的版本

    2023-04-15
    156
  • 大数据运维:大数据平台+海量数据[通俗易懂]

    大数据运维:大数据平台+海量数据[通俗易懂]大数据开发独揽大权 大数据技术很早就在BAT这些公司生根发芽,但直到14、15年大数据技术才广泛应用在各大互联网公司,大数据技术由此深入各行各业。 此时大数据开发人才非常紧缺,很多公司大数据从立项,到

    2022-12-28
    162
  • 关于python生成url测试用例的信息

    关于python生成url测试用例的信息 基于属性的测试 会产生大量的、随机的参数,特别适合为单元测试和接口测试生成测试用例

    2023-12-01
    113
  • centos7编译mysql 5.7 源码

    centos7编译mysql 5.7 源码首先需要根据mysql的编译文档进行执行。mysql文档 需要些啥 cmake 官网 cmake的编译安装脚本 wget https://github.com/Kitware/CMake/relea…

    2023-02-08
    169
  • 用Python快速学习编程基础

    用Python快速学习编程基础Python是一种动态解释性语言,它具有简洁易懂、具有高层次的内置数据类型和动态语义等特点。Python具有交互式运行环境,可以在命令行或集成开发环境中进行代码写作。

    2024-02-06
    90

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注