Hbase 高可用、預先分區、布隆過濾器:html
HBase中Hmaster負責監控RegionServer的生命週期,均衡RegionServer的負載,若是Hmaster掛掉了,那麼整個HBase集羣將陷入不健康的狀態,而且此時的工做狀態並不會維持過久。因此HBase支持對Hmaster的高可用配置。node
關閉HBase集羣(若是沒有開啓則跳過此步)python
stop-hbase.sh
在conf目錄下建立backup-masters文件算法
touch conf/backup-masters
在backup-masters文件中配置高可用HMaster節點apache
echo datanode2 > conf/backup-masters
將整個conf目錄scp到其餘節點vim
scp -r conf/ datanode1:/opt/module/hbase/ scp -r conf/ datanode3:/opt/module/hbase/
每個region維護着startRow與endRowKey,若是加入的數據符合某個region維護的rowKey範圍,則該數據交給這個region維護。依照這個原則,咱們能夠將數據所要投放的分區提早大體的規劃好,以提升HBase性能。數組
create 'staff1','info','partition1',SPLITS => ['1000','2000','3000','4000']
create 'staff2','info','partition2',{NUMREGIONS => 15, SPLITALGO => 'HexStringSplit'}
[hadoop@datanode1 hbase]$ vim splits.txt #在hbase建立該文件 aaaa bbbb cccc dddd create 'staff2','info','partition2',{NUMREGIONS => 15, SPLITALGO => 'HexStringSplit'}
//自定義算法,產生一系列Hash散列值存儲在二維數組中 byte[][] splitKeys = 某個散列值函數 //建立HBaseAdmin實例 HBaseAdmin hAdmin = new HBaseAdmin(HBaseConfiguration.create()); //建立HTableDescriptor實例 HTableDescriptor tableDesc = new HTableDescriptor(tableName); //經過HTableDescriptor實例和散列值二維數組建立帶有預分區的HBase表 hAdmin.createTable(tableDesc, splitKeys); import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HBaseConfiguration; import org.apache.hadoop.hbase.HColumnDescriptor; import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.client.Admin; import org.apache.hadoop.hbase.client.Connection; import org.apache.hadoop.hbase.client.ConnectionFactory; import org.apache.hadoop.hbase.util.Bytes; public class create_table_sample { public static void main(String[] args) throws Exception { Configuration conf = HBaseConfiguration.create(); conf.set("hbase.zookeeper.quorum", "192.168.1.101,192.168.1.102,192.168.1.103"); Connection connection = ConnectionFactory.createConnection(conf); Admin admin = connection.getAdmin(); TableName table_name = TableName.valueOf("Java_Table"); if (admin.tableExists(table_name)) { admin.disableTable(table_name); admin.deleteTable(table_name); } HTableDescriptor desc = new HTableDescriptor(table_name); HColumnDescriptor family1 = new HColumnDescriptor(Bytes.toBytes("info")); family1.setTimeToLive(3 * 60 * 60 * 24); //過時時間 family1.setMaxVersions(3); //版本數 desc.addFamily(family1); byte[][] splitKeys = { Bytes.toBytes("row01"), Bytes.toBytes("row02"), }; admin.createTable(desc, splitKeys); admin.close(); connection.close(); System.out.println("建立成功!!!"); } }
一條數據的惟一標識就是rowkey,那麼這條數據存儲於哪一個分區,取決於rowkey處於哪一個一個預分區的區間內,設計rowkey的主要目的,就是讓數據均勻的分佈於全部的region中,在必定程度上防止數據傾斜。接下來咱們就談一談rowkey經常使用的設計方案。緩存
本來rowKey爲1001的,SHA1後變成:dd01903921ea24941c26a48f2cec24e0bb0e8cc7服務器
本來rowKey爲3001的,SHA1後變成:49042c54de64a1e9bf0b33e00245660ef92dc7bd網絡
本來rowKey爲5001的,SHA1後變成:7b61dec07e02c188790670af43e717f0f46e8913
在作此操做以前,通常咱們會選擇從數據集中抽取樣本,來決定什麼樣的rowKey來Hash後做爲每一個分區的臨界值。
20170524000001轉成10000042507102
20170524000002轉成20000042507102
常見的是將URL反轉好比 www.baidu.com 轉成 com.baidu.wwww
20170524000001_a12e
20170524000001_93i7
主要是爲了防止數據傾斜好比電話號碼做爲Rowkey的時候是有規律可循的,在進行MapReduce做業的時候會致使數據傾斜。
HBase操做過程當中須要大量的內存開銷,Table是能夠緩存在內存中的,通常會分配整個可用內存的70%給HBase的Java堆。可是不建議分配很是大的堆內存,由於GC過程持續過久會致使RegionServer處於長期不可用狀態,通常16~48G內存就能夠了,若是由於框架佔用內存太高致使系統內存不足,框架同樣會被系統服務拖死。
hdfs-site.xml、hbase-site.xml
屬性:dfs.support.append 解釋:開啓HDFS追加同步,能夠優秀的配合HBase的數據同步和持久化。默認值爲true。
hdfs-site.xml
屬性:dfs.datanode.max.transfer.threads 解釋:HBase通常都會同一時間操做大量的文件,根據集羣的數量和規模以及數據動做,設置爲4096或者更高。默認值:4096
hdfs-site.xml
屬性:dfs.image.transfer.timeout 解釋:若是對於某一次數據操做來說,延遲很是高,socket須要等待更長的時間,建議把該值設置爲更大的值(默認60000毫秒),以確保socket不會被timeout掉。
mapred-site.xml
屬性: mapreduce.map.output.compress mapreduce.map.output.compress.codec 解釋:開啓這兩個數據能夠大大提升文件的寫入效率,減小寫入時間。第一個屬性值修改成true,第二個屬性值修改成:org.apache.hadoop.io.compress.GzipCodec或者其餘壓縮方式。
優化DataNode存儲
屬性:dfs.datanode.failed.volumes.tolerated 解釋: 默認爲0,意思是當DataNode中有一個磁盤出現故障,則會認爲該DataNode shutdown了。若是修改成1,則一個磁盤出現故障時,數據會被複制到其餘正常的DataNode上,當前的DataNode繼續工做。
設置RPC監聽數量
hbase-site.xml
屬性:hbase.regionserver.handler.count 解釋:默認值爲30,用於指定RPC監聽的數量,能夠根據客戶端的請求數進行調整,讀寫請求較多時,增長此值。
hbase-site.xml
屬性:hbase.hregion.max.filesize 解釋:默認值10737418240(10GB),若是須要運行HBase的MR任務,能夠減少此值,由於一個region對應一個map任務,若是單個region過大,會致使map任務執行時間過長。該值的意思就是,若是HFile的大小達到這個數值,則這個region會被切分爲兩個Hfile。
hbase-site.xml
屬性:hbase.client.write.buffer 解釋:用於指定HBase客戶端緩存,增大該值能夠減小RPC調用次數,可是會消耗更多內存,反之則反之。通常咱們須要設定必定的緩存大小,以達到減小RPC次數的目的。
hbase-site.xml
屬性:hbase.client.scanner.caching 解釋:用於指定scan.next方法獲取的默認行數,值越大,消耗內存越大。
當MemStore達到閾值,將Memstore中的數據Flush進Storefile;compact機制則是把flush出來的小文件合併成大的Storefile文件。split則是當Region達到閾值,會把過大的Region一分爲二。
涉及屬性:
即:128M就是Memstore的默認閾值
hbase.hregion.memstore.flush.size:134217728
即:這個參數的做用是當單個HRegion內全部的Memstore大小總和超過指定值時,flush該HRegion的全部memstore。RegionServer的flush是經過將請求添加一個隊列,模擬生產消費模型來異步處理的。那這裏就有一個問題,當隊列來不及消費,產生大量積壓請求時,可能會致使內存陡增,最壞的狀況是觸發OOM。
hbase.regionserver.global.memstore.upperLimit:0.4 hbase.regionserver.global.memstore.lowerLimit:0.38
即:當MemStore使用內存總量達到hbase.regionserver.global.memstore.upperLimit指定值時,將會有多個MemStores flush到文件中,MemStore flush 順序是按照大小降序執行的,直到刷新到MemStore使用內存略小於lowerLimit
在平常生活中,包括在設計計算機軟件時,咱們常常要判斷一個元素是否在一個集合中。好比在字處理軟件中,須要檢查一個英語單詞是否拼寫正確(也就是要判斷它是否在已知的字典中);在 FBI,一個嫌疑人的名字是否已經在嫌疑名單上;在網絡爬蟲裏,一個網址是否被訪問過等等。最直接的方法就是將集合中所有的元素存在計算機中,遇到一個新元素時,將它和集合中的元素直接比較便可。通常來說,計算機中的集合是用哈希表(hash table)來存儲的。它的好處是快速準確,缺點是費存儲空間。 當集合比較小時,這個問題不顯著,可是當集合巨大時,哈希表存儲效率低的問題就顯現出來了。好比說,一個像 Yahoo,Hotmail 和 Gmai 那樣的公衆電子郵件(email)提供商,老是須要過濾來自發送垃圾郵件的人(spamer)的垃圾郵件。一個辦法就是記錄下那些發垃圾郵件的 email 地址。因爲那些發送者不停地在註冊新的地址,全世界少說也有幾十億個發垃圾郵件的地址,將他們都存起來則須要大量的網絡服務器。若是用哈希表,每存儲一億個 email 地址, 就須要 1.6GB 的內存(用哈希表實現的具體辦法是將每個 email 地址對應成一個八字節的信息指紋googlechinablog.com/2006/08/blog-post.html,而後將這些信息指紋存入哈希表,因爲哈希表的存儲效率通常只有 50%,所以一個 email 地址須要佔用十六個字節。一億個地址大約要 1.6GB, 即十六億字節的內存)。所以存貯幾十億個郵件地址可能須要上百 GB 的內存。除非是超級計算機,通常服務器是沒法存儲的。
布隆過濾器只須要哈希表 1/8 到 1/4 的大小就能解決一樣的問題。
Bloom Filter是一種空間效率很高的隨機數據結構,它利用位數組很簡潔地表示一個集合,並能判斷一個元素是否屬於這個集合。Bloom Filter的這種高效是有必定代價的:在判斷一個元素是否屬於某個集合時,有可能會把不屬於這個集合的元素誤認爲屬於這個集合(false positive)。所以,Bloom Filter不適合那些「零錯誤」的應用場合。而在能容忍低錯誤率的應用場合下,Bloom Filter經過極少的錯誤換取了存儲空間的極大節省。
下面咱們具體來看Bloom Filter是如何用位數組表示集合的。初始狀態時,Bloom Filter是一個包含m位的位數組,每一位都置爲0,如圖9-5
爲了表達S={x1, x2,…,xn}這樣一個n個元素的集合,Bloom Filter使用k個相互獨立的哈希函數(Hash Function),它們分別將集合中的每一個元素映射到{1,…,m}的範圍中。對任意一個元素x,第i個哈希函數映射的位置hi(x)就會被置爲1(1≤i≤k)。注意,若是一個位置屢次被置爲1,那麼只有第一次會起做用,後面幾回將沒有任何效果。如圖9-6所示,k=3,且有兩個哈希函數選中同一個位置(從左邊數第五位)。
在判斷y是否屬於這個集合時,咱們對y應用k次哈希函數,若是全部hi(y)的位置都是1(1≤i≤k),那麼咱們就認爲y是集合中的元素,不然就認爲y不是集合中的元素。如圖9-7所示y1就不是集合中的元素。y2或者屬於這個集合,或者恰好是一個false positive。
爲了add一個元素,用k個hash function將它hash獲得bloom filter中k個bit位,將這k個bit位置1。
爲了query一個元素,即判斷它是否在集合中,用k個hash function將它hash獲得k個bit位。若這k bits全爲1,則此元素在集合中;若其中任一位不爲1,則此元素比不在集合中(由於若是在,則在add時已經把對應的k個bits位置爲1)。
· 不容許remove元素,由於那樣的話會把相應的k個bits位置爲0,而其中頗有可能有其餘元素對應的位。所以remove會引入false negative,這是絕對不被容許的。
布隆過濾器決不會漏掉任何一個在黑名單中的可疑地址。可是,它有一條不足之處,也就是它有極小的可能將一個不在黑名單中的電子郵件地址斷定爲在黑名單中,由於有可能某個好的郵件地址正巧對應一個八個都被設置成一的二進制位。好在這種可能性很小,咱們把它稱爲誤識機率。
布隆過濾器的好處在於快速,省空間,可是有必定的誤識別率,常見的補救辦法是在創建一個小的白名單,存儲那些可能個別誤判的郵件地址。
布隆過濾器具體算法高級內容,如錯誤率估計,最優哈希函數個數計算,位數組大小計算,請參見http://blog.csdn.net/jiaomeng/article/details/1495500。