HBase之 HTable线程不安全

阅读更多

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

 

我们来看看Htable的api说明

 

 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这是为什么呢
还是从HTbale的源码来看
 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实例。例如,最好这样做:
HBaseConfiguration conf = HBaseConfiguration.create();
HTable table1 = new HTable(conf, "myTable");
HTable table2 = new HTable(conf, "myTable");

而不是这样:

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中取,用完放回,很简单~~~

你可能感兴趣的:(HBase,HTable,线程安全)