Hbase连接管理

每个Htable实例都需要建立和远程主机的连接。这些连接在内部使用HConnection类表示,更重要的是,其被HConnectionManager类管理并共享。用户没有必要同时和这两个类打交道,需要创建一个Configuration实例,然后利用客户端API使用这些类。

HBase内部使用键值映射来存储连接,使用Configuration实例作为键值映射的键。换句话说,当你创建很多HTable实例时,如果你提供了相同的Configuration引用,那么它们都共享同一个底层的HConnection实例。有关细节如下:

  • 共享ZooKeeper连接

       因为每个客户端最终都需要Zookeeper连接来完成表的region地址初始寻址,连接一旦建立后,共享就变得很有意义,这使得之后的客户端实例可以共用

  • 缓存通用资源

       通过ZooKeeper查询到的-ROOT-和.META.的地址,以及region的地址定位都需要网络传输开销。这些地址将被缓存在客户端来减少网络的调用次数,因此达到加速寻址的目的。

       对于每个连接远程集群的本地客户端来说,它们的地址表都是相同的,因此运行相同进程的客户共享连接非常有用,这是通过共享HConnection实例来实现的。另外,当寻址失败时(如region拆分时),连接有内置的重试机制来刷新缓存,对于其它所有共享相同连接引用的客户端来说,这项更改立即生效,因此这更加减少了客户端初始化的开销

另一个受益的类是HTablePool,所有连接池中的HTable实例都自动共用一个提供的Configuration实例,因此它们也共享连接。因为当用户想创建多个HTable实例时,最好先创建一个共用的Configuration实例。

HTable table1 = new HTable("table1");
//...
HTable table2 = new HTable("table2");

上述代码不如以下代码有效:

Configuration conf = HBaseConfiguration.create();
HTable table1 = new HTable(conf,"table1");
//...
HTable table2 = new HTable(conf,"table2");

后者隐式共享HBase客户端API类提供的连接。

注:目前没有明显的证据表明共享连接会带来性能问题,即使在繁忙的多线程环境下也是如此。

共享连接的缺点在于释放,如果用户不显示关闭连接,它将一直存在,直到客户端退出。这样可能导致很多ZooKeeper连接都保持打开状态,尤其在大型分布式环境下,比如执行MapReduce作业的HBase程序,这样可能会产生一些问题。最坏的情况是耗尽所有的连接句柄或内存,并导致I/O异常。

用户可通过显示关闭连接避免这种情况。建议用户不再需要HTable时主动调用HTable的close()方法,调用这个方法将释放所有共享资源,其中包括ZooKeeper连接,同时移除内部列表中的连接引用。

每个用户重用Configuration实例时,连接管理都会增加引用计数。因此用户必须调用close()来触发清除工作。以下是显式的方法来清理一个连接或所有连接:

static void delectConnection(Configuration conf, boolean stopProxy)
static void deleteAllConnections(boolean stopProxy)

所有的共享连接都是按照Configuration实例作为键,因此用户需要提供这个实例来关闭相应的连接。布尔类型参数stopProxy保证强制清除整个客户端RPC栈,因此不再需要远程连接服务器时,应用将这个参数设置为true。

deleteAllConnections(boolean stopProxy) 函数只需要stopProxy参数,它将遍历整个连接管理器注册过的共享连接列表,然后逐一释放连接。

如果用户需要显式地使用某个连接,可以通过如下方式使用 getConnection() 方法。

Configuration newConfig = new Configuration(originalConf);
HConnection connection = HConnectionManager.getConnection(newConfig);
HConnectionManager.deleteConnection(newConfig,true);

这样操作的好处是可以保证这个连接的用户唯一,但是,切记必须要在调用结束后关闭它。

 

 

 

 

 

你可能感兴趣的:(HBase)