Hbase作为Hadoop原生数据库,在数据存储上与底层的HDFS是互相配合的重要组件。Hbase也提供相应的API,来帮助开发者能够更便捷地完成开发任务。今天的大数据学习分享,我们就主要来讲讲Hbase Connection的使用。
对于很多初次接触HBase的伙伴,在使用其客户端API来构建Connection连接对象的时候,有可能会陷入以下几个误区。
类比druid等mysql数据库连接池,自己封装一个Connection对象的资源池,每次使用都从池中取出一个Connection对象;
在多线程的工作环境中,每个线程都会创建一个Connection对象,造成Connection对象被频繁创建,快速消耗;
每次访问HBase的时候临时创建一个Connection对象,使用完之后调用close方法,关闭连接;
一、HBase Connection的正确使用姿势
参考HBase技术社区文章连接HBase的正确姿势中对Connection的源码分析,们可知:
HBase客户端中的Connection对象并不是简单对应一个socket连接。
HBase客户端的Connection包含了对Zookeeper、HBase Master、HBase RegionServer三种socket连接的封装。因此,Connection对象每次被创建出来的开销是很大的,使用完毕之后断开,会带来严重的性能损耗。
在HBase中Connection类已经实现了对连接的管理功能,所以们不需要自己在Connection之上再做额外的管理。另外,Connection是线程安全的,而Table和Admin则不是线程安全的,因此正确的做法是,在一个JVM进程中共用一个Connection对象,而在不同的线程中使用单独的Table和Admin对象。
二、单例模式维护HBase的Connection
在普通的Java程序中,如果没有并发场景的存在,们可以简单地使用下面这种方式来创建Connection的对象。
///所有进程共用一个connection对象
connection=ConnectionFactory.createConnection(config);
...
///每个线程使用单独的table对象
Table table=connection.getTable(TableName.valueOf("test"));
try{
...
}finally{
table.close();
}
然而,在多线程中的场景中,们又该如何来管理们的连接对象呢?聪明的你,一定会首先想到单例模式。
单例模式是一种简单的设计模式,它的优点是只生成一个实例,可以保证在同一个JVM进程中,对象只存在一个。所以能节约系统资源,减少性能开销,同时能够严格控制用户对它的访问。
关于单例模式的实现,常见的有饿汉式、懒汉式、双重检测锁式、静态内部类式和枚举单例。
上述实现方式各有优劣,但使用时需要注意,线程是否安全和平衡效率。关于其具体的实现细节,网上有很多文章可供参考,这里不做详细罗列,只举例双重检测锁式的单例实现方式,在管理HBase客户端连接对象中的应用。具体实现代码:
public class SingleConnectionFactory {
private static final Logger LOGGER = LoggerFactory.getLogger(SingleConnectionFactory.class);
private volatile static Connection connection;
private SingleConnectionFactory() {}
public static Connection getConnection(Configuration configuration) {
if (connection == null) {
synchronized (SingleConnectionFactory.class) {
if (connection == null) {
try {
connection = ConnectionFactory.createConnection(configuration);
LOGGER.info("the connection of HBase is created successfully.");
} catch (IOException e) {
LOGGER.error("the connection of HBase is created failed.");
throw new HBaseSdkConnectionException(e);
}
}
}
}
return connection;
}
}
上述单例Connection对象创建工厂类,在多线程的测试环境中亦可保证同一个JVM进程中,只有一个Connection对象被创建出来,观察ZK客户端连接数监控,几乎无波动。
三、多例模式中维护HBase的Connection
在cuckoo-cloud(布谷鸟,微服务版大数据组件统一管理平台,目前已集成hbase-manager和kafka-manager的功能)中迁移们的hbase-manager应用时,遇到这样一个问题。
cuckoo-cloud平台上会管理们的多个HBase集群,这些HBase集群的连接信息被保存进数据库中,可以进行动态维护。在设计HBase的连接管理功能时,如果采用单例模式,那么,无论切换任意一个集群,始终操作的是最开始被初始化连接的集群;如果放弃单例模式,Connection对象又会被滥用。
所以,需要一个容器,它能保存不同集群的连接对象,且每个对象在一个JVM进程中只保留一个。
网上贴出来的多例实现代码都是基于创建多个固定对象的,但需要的是动态创建对象,最终的实现效果如下:
public class MultipleConnectionFactory {
private static final Logger LOGGER = LoggerFactory.getLogger(MultipleConnectionFactory.class);
private volatile static Map<String, Connection> connectionMap;
private MultipleConnectionFactory() {
}
public static Connection getConnection(Configuration configuration) {
String cluster = configuration.get(HConstants.ZOOKEEPER_QUORUM);
if (connectionMap == null || !connectionMap.containsKey(cluster)) {
synchronized (MultipleConnectionFactory.class) {
if (connectionMap == null || !connectionMap.containsKey(cluster)) {
try {
if (connectionMap == null) {
connectionMap = new HashMap<>(2);
}
if (!connectionMap.containsKey(cluster)) {
Connection connection = ConnectionFactory.createConnection(configuration);
LOGGER.info("the connection of HBase cluster [{}] is created successfully.", cluster);
connectionMap.put(cluster, connection);
}
} catch (IOException e) {
LOGGER.error("the connection of HBase is created failed.");
throw new HBaseSdkConnectionException(e);
}
}
}
}
return connectionMap.get(cluster);
}
}
类比双重检测锁式的单例实现方式,在此使用ZK的连接地址为key,来保证每一个集群的连接对象在同一个JVM进程中唯一存在。
关于大数据学习,HBase Connection的使用,以上就为大家做了基本的介绍了。Hbase通过API进行开发任务的时候,Connection的使用还是要根据具体的需求来确定。成都加米谷大数据,专业
大数据培训机构,大数据开发、数据分析与挖掘,零基础班本月正在招生中,课程大纲及试学视频,可联系客服获取!