HTable API有没有线程安全问题,在程序中是单例还是多例?

2023-10-17 15:44:22 浏览数 (2)

  在单线程环境下使用hbase的htable是没有问题,但是突然高并发多线程情况下就可能出现问题。

  以下为Htable的API说明:

代码语言:javascript复制
This class is not thread safe for updates; the underlying write buffer can be corrupted  if multiple threads contend over a single HTable instance.   

  当有多个线程竞争时可能把当前正在写的线程corrupted,那么原因是什么呢?

  根据Htable的源码:

代码语言:javascript复制
public HTable(final byte [] tableName)  
 throws IOException {  
   this(HBaseConfiguration.create(), tableName);  
 }
	
public static Configuration create() {  
	Configuration conf = new Configuration();  
	return addHbaseResources(conf);  
}  

  从上面我们可以看到每一个HTable的实例化过程都要创建一个新的conf,我们甚至可以认为一个conf对应的是一个HTable的connection,因此如果客户端对于同一个表,每次新new 一个configuration对象的话,那么意味着这两个HTable虽然操作的是同一个table,但是建立的是两条链接connection,它们的socket不是共用的,在多线程的情况下,经常会有new Htable的情况发生,而每一次的new都可能是一个新的connection,而我们知道zk上的链接是有限制的如果链接达到一定阈值的话,那么新建立的链接很有可能挤掉原先的connection,而导致线程不安全。

  因此hbase官方文档建议我们:HTable不是线程安全的。建议使用同一个HBaseConfiguration实例来创建HTable实例,这样可以共享ZooKeeper和socket实例。例如,最好这样做:

代码语言:javascript复制
HBaseConfiguration conf = HBaseConfiguration.create();
HTable table1 = new HTable(conf, "myTable");
HTable table2 = new HTable(conf, "myTable");

  而不是这样:

代码语言:javascript复制
HBaseConfiguration conf1 = HBaseConfiguration.create();
HTable table1 = new HTable(conf1, "myTable");
HBaseConfiguration conf2 = HBaseConfiguration.create();
HTable table2 = new HTable(conf2, "myTable");

  当然最方便的方法就是使用HTablepool了,维持一个线程安全的map里面存放的是tablename和其引用的映射,可以认为是一个简单的计数器,当需要new 一个HTable实例时直接从该pool中取,用完放回。

0 人点赞