如何正确管理HBase的连接,从原理到实战 - 阿丸 - 博客园

标签: | 发表时间:2020-04-19 18:38 | 作者:
出处:https://www.cnblogs.com

本文将介绍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();     
}

我们不禁有这样的疑问:

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。

如何正确管理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(历史文章查阅非常方便)

相关 [正确 管理 hbase] 推荐:

如何正确管理HBase的连接,从原理到实战 - 阿丸 - 博客园

- -
本文将介绍HBase的客户端连接实现,并说明如何正确管理HBase的连接. 最近在搭建一个HBase的可视化管理平台,搭建完成后发现不管什么查询都很慢,甚至于使用api去listTable都要好几秒. 经过一番排查发现,是每次请求的时候,都去临时创建了一个connection,而创建connection非常耗时导致整体的rt上升.

HBase表管理系统

- - CSDN博客推荐文章
源码下载: https://github.com/fansy1990/ssh_v3/releases. 部署参考: http://blog.csdn.net/fansy1990/article/details/51356583. HBase表管理系统主要是对表以及表数据的相关操作;. 直接打开Table管理界面,即可看到所有表的简要信息,包括数据库(namspace)、表名、简单表描述等;.

使用zookeeper管理多个hbase集群

- d0ngd0ng - 蓝色时分
    zookeeper是hbase集群的"协调器". 由于zookeeper的轻量级特性,因此我们可以将多个hbase集群共用一个zookeeper集群,以节约大量的服务器. 多个hbase集群共用zookeeper集群的方法是使用同一组ip,修改不同hbase集群的"zookeeper.znode.parent"属性,让它们使用不同的根目录.

连接池连接HBase的正确姿势

- -
在云HBase值班的时候,经常会遇见有用户咨询诸如“HBase是否支持连接池. ”这样的问题,也有用户因为应用中创建的Connection对象过多,触发了zookeeper的连接数限制,导致客户端连不上的. 究其原因,都是因为对HBase客户端的原理不了解造成的. 本文简单介绍HBase客户端的Connection对象与socket连接的关系,并给出Connection的正确用法.

hbase介绍

- AreYouOK? - 淘宝数据平台与产品部官方博客 tbdata.org
hbase是bigtable的开源山寨版本. 是建立的hdfs之上,提供高可靠性、高性能、列存储、可伸缩、实时读写的数据库系统. 它介于nosql和RDBMS之间,仅能通过主键(row key)和主键的range来检索数据,仅支持单行事务(可通过hive支持来实现多表join等复杂操作). 主要用来存储非结构化和半结构化的松散数据.

Riak对比HBase

- - NoSQLFan
文章来自 Riak官方wiki,是一篇Riak与HBase的对比文章. Riak官方的对比通常都做得很中肯,并不刻意偏向自家产品. 对比的Riak版本是1.1.x,HBase是0.94.x. Riak 与 HBase 都是基于 Apache 2.0 licensed 发布. Riak 的实现是基于 Amazon 的 Dynamo 论文,HBase 是基于 Google 的 BigTable.

[转]HBase简介

- - 小鸥的博客
   Hbase是一个分布式开源数据库,基于Hadoop分布式文件系统,模仿并提供了基于Google文件系统的Bigtable数据库的所有功能. 其目标是处理非常庞大的表,可以用普通的计算机处理超过10亿行数据,并且有数百万列元素组成的数据表. Hbase可以直接使用本地文件系统或者Hadoop作为数据存储方式,不过为了提高数据可靠性和系统的健壮性,发挥Hbase处理大数据量等功能,需要使用Hadoop作为文件系统.

HBase表设计

- - 互联网 - ITeye博客
默认情况下,在创建HBase表的时候会自动创建一个region分区,当导入数据的时候,所有的HBase客户端都向这一个region写数据, 直到这 个region足够大了才进行切分. 一种可以加快批量写入速度的方法是通过预先创建一些空的regions,这样当数据写入HBase时,会按 照 region分区情况,在集群内做数据的负载均衡.

HBase Memstore配置

- - 行业应用 - ITeye博客
HBase Memstore配置. 本文为翻译,原英文地址:http://blog.sematext.com/2012/07/16/hbase-memstore-what-you-should-know/.     当regionserver(以下简称RS)收到一个写请求,会将这个请求定位到某个特定的region.

hbase原理

- - CSDN博客云计算推荐文章
1.hbase利用hdfs作为其文件存储系统,利用mapreduce来处理数据,利用zookeeper作为协调工具. 2.行键(row key),类似于主键,但row key是表自带的. 3.列族(column family) ,列(也称作标签/修饰符)的集合,定义表的时候指定的,列是在插入记录的时候动态增加的.