面試題百日百刷-HBase中HTable API有沒有線程安全問題,在程序是單例還是多例?
鎖屏面試題百日百刷,每個工作日堅持更新面試題。請看到最后就能獲取你想要的,接下來的是今日的面試題:
1.HBase內(nèi)部機(jī)制是什么?
Hbase是一個能適應(yīng)聯(lián)機(jī)業(yè)務(wù)的數(shù)據(jù)庫系統(tǒng)
物理存儲:hbase的持久化數(shù)據(jù)是將數(shù)據(jù)存儲在HDFS上。
存儲管理:一個表是劃分為很多region的,這些region分布式地存放在很多regionserver上Region內(nèi)部還可以
劃分為store,store內(nèi)部有memstore和storefile。
版本管理:hbase中的數(shù)據(jù)更新本質(zhì)上是不斷追加新的版本,通過compact操作來做版本間的文件合并Region
的split。
集群管理:ZooKeeper + HMaster + HRegionServer。
2.HTable API有沒有線程安全問題,在程序是單例還是多例?
在單線程環(huán)境下使用hbase的htable是沒有問題,但是突然高并發(fā)多線程情況下就可能出現(xiàn)問題。
以下為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. 當(dāng)有多個線程競爭時可能把當(dāng)前正在寫的線程corrupted,那么原因是什么呢?
根據(jù)Htable的源碼:
public?HTable(final?byte?[]?tableName)throws?IOException{
?this(HBaseConfiguration.create(), tableName);
}
public static Configuration create() {
?Configuration conf = new Configuration();
?return addHbaseResources(conf);
}
從上面我們可以看到每一個HTable的實例化過程都要創(chuàng)建一個新的conf,我們甚至可以認(rèn)為一個conf對應(yīng)的是一個HTable的connection,因此如果客戶端對于同一個表,每次新new 一個configuration對象的話,那么意味著這兩個HTable雖然操作的是同一個table,但是建立的是兩條鏈接connection,它們的socket不是共用的,在多線程的情況下,經(jīng)常會有new Htable的情況發(fā)生,而每一次的new都可能是一個新的connection,而我們知道zk上的鏈接是有限制的如果鏈接達(dá)到一定閾值的話,那么新建立的鏈接很有可能擠掉原先的connection,而導(dǎo)致線程不安全。
因此hbase官方文檔建議我們:HTable不是線程安全的。建議使用同一個HBaseConfiguration實例來創(chuàng)建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");
當(dāng)然最方便的方法就是使用HTablepool了,維持一個線程安全的map里面存放的是tablename和其引用的映射,可以認(rèn)為是一個簡單的計數(shù)器,當(dāng)需要new 一個HTable實例時直接從該pool中取,用完放回。
3.HBase有沒有并發(fā)問題?
針對HBase在高并發(fā)情況下的性能,我們進(jìn)行如下測試:
測試版本:hbase 0.94.1、 hadoop 1.0.2、 jdk-6u32-linux-x64.bin、snappy-1.0.5.tar.gz
測試hbase搭建:14臺存儲機(jī)器+2臺master、DataNode和regionserver放在一起。
測試一:高并發(fā)讀(4w+/s) + 少量寫(允許分拆、負(fù)載均衡)
癥狀:1-2天后,hbase掛掉(系統(tǒng)性能極差,不到正常的10%)。其實并非全部掛掉,而是某些regionserver掛了,并在幾個小時內(nèi)引發(fā)其他regionserver掛掉。系統(tǒng)無法恢復(fù):單獨啟regionserver無法恢復(fù)正常。重啟后正常。
測試二:高并發(fā)讀(4w+/s)
癥狀:1-2天后,hbase掛掉(系統(tǒng)性能極差,不到正常的10%)。后發(fā)現(xiàn)是由于zookeeper.session.timeout設(shè)置不正確導(dǎo)致(參見regionserver部分:http://hbase.apache.org/book.html#trouble)。重啟后正常。
測試三:高并發(fā)讀(4w+/s)
癥狀:1-2天后,hbase掛掉(系統(tǒng)性能極差,不到正常的10%)。從log未看出問題,但regionserver宕機(jī),且datanode也宕機(jī)。重啟后正常。
測試四:高并發(fā)讀(4w+/s)+禁止分拆、禁止majorcompaction、禁止負(fù)載均衡(balance_switch命令)癥狀:1-2天后,hbase掛掉(系統(tǒng)性能極差,不到正常的10%)。從log未看出問題,但regionserver宕機(jī),且datanode也宕機(jī)。重啟后正常。
測試期間,還發(fā)現(xiàn)過:無法獲取".MATE."表的內(nèi)容(想知道regionserver的分布情況)、hbase無法正確停止、hbase無法正確啟動(日志恢復(fù)失敗,文件錯誤,最終手動刪除日志重啟)。
全部內(nèi)容在[git](https://gitee.com/zjlalaforgit/interview)上,了解更多請點我頭像或到我的主頁去獲得,謝謝