hbase配置
[root@node1 test]# cat /usr/hdp/current/hbase-client/conf/hbase-site.xml
<configuration>
#Todo
<property>
<name>dfs.domain.socket.path</name>
<value>/var/lib/hadoop-hdfs/dn_socket</value>
</property>
#Todo
<property>
<name>hbase.bulkload.staging.dir</name>
<value>/apps/hbase/staging</value>
</property>
#每條記錄的最大大小爲1MB
<property>
<name>hbase.client.keyvalue.maxsize</name>
<value>1048576</value>
</property>
#hbase client操作失敗重新請求數爲35
<property>
<name>hbase.client.retries.number</name>
<value>35</value>
</property>
#當一次scan操作不在本地內存時,需要從disk中獲取時,緩存的條數,這裏設置爲100000條,該值不能大於下文中hbase.client.scanner.timeout.period配置項的值
<property>
<name>hbase.client.scanner.caching</name>
<value>100000</value>
</property>
下圖中的第一個配置項hbase.client.scanner.timeout.period對應的是上文中的Number of Fetched Rows when Scanning from Disk,它的值必須小於下圖中的第一個配置項纔行。
第二個配置項的話默認是true的,無需額外配置,之前在解決一個相關問題時,將它置爲了false。
<property>
<name>hbase.client.scanner.timeout.period</name>
<value>120000</value>
</property>
#hbase是否配置爲分佈式
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
#Todo
<property>
<name>hbase.coprocessor.master.classes</name>
<value></value>
</property>
#Todo
<property>
<name>hbase.coprocessor.region.classes</name>
<value>org.apache.hadoop.hbase.security.access.SecureBulkLoadEndpoint</value>
</property>
#設置爲ture,忽略對默認hbase版本的檢查(設置爲false的話在maven工程的編譯過程中可能會遇到版本相關的問題)
<property>
<name>hbase.defaults.for.version.skip</name>
<value>true</value>
</property>
#設置系統進行1次majorcompaction的啓動週期,如果設置爲0,則系統不會主動出發MC過程,默認爲7天
<property>
<name>hbase.hregion.majorcompaction</name>
<value>604800000</value>
</property>
#用來作爲計算MC時間週期,與hbase.hregion.majorcompaction相結合,計算出一個浮動的MC時間。默認是0.50,簡單來說如果當前store中hfile的最早更新時間早於某個MCTime,就會觸發major compaction,hbase通過這種機制定期刪除過期數據。MCTime是一個浮動值,浮動區間爲[ hbase.hregion.majorcompaction - hbase.hregion.majorcompaction * hbase.hregion.majorcompaction.jitter , hbase.hregion.majorcompaction + hbase.hregion.majorcompaction * hbase.hregion.majorcompaction.jitter ]
<property>
<name>hbase.hregion.majorcompaction.jitter</name>
<value>0.50</value>
</property>
#單個region的大小爲10G,當region大於這個值的時候,一個region就會split爲兩個,適當的增加這個值的大小可以在寫操作時減少split操作的發生,從而減少系統性能消耗而增加寫操作的性能,默認是10G,官方建議10G~30G
<property>
<name>hbase.hregion.max.filesize</name>
<value>10737418240</value>
</property>
#當一個region的memstore總量達到hbase.hregion.memstore.block.multiplier * hbase.hregion.memstore.flush.size (默認2*128M)時,會阻塞這個region的寫操作,並強制刷寫到HFile,觸發這個刷新操作只會在Memstore即將寫滿hbase.hregion.memstore.flush.size時put了一個巨大的記錄的情況,這時候會阻塞寫操作,強制刷新成功才能繼續寫入
<property>
<name>hbase.hregion.memstore.block.multiplier</name>
<value>8</value>
</property>
#每個單獨的memstore的大小(默認128M),這裏調成了256M,每個列族columnfamily在每個region中都分配有它單獨的memstore,當memstore超過該值時,就會發生flush操作,將memstore中的內容刷成一個hfile,每一次memstore的flush操作,都會爲每一次columnfamily創建一個新的hfile;調高該值可以減少flush的操作次數,減少每一個region中的hfile的個數,這樣就會減少minor compaction的次數和split的次數,從而降低了系統性能損耗,提升了寫性能,也提升了讀性能(因爲讀操作的時候,首先要去memstore中查數據,查找不到的話再去hfile,hflie存儲在hdfs中,這就涉及到了對性能要求較高的io操作了)。當然這個值變大了之後,每次flush操作帶來的性能消耗也就更大。
<property>
<name>hbase.hregion.memstore.flush.size</name>
<value>268435456</value>
</property>
#mslab特性是在分析了HBase產生內存碎片後的根因後給出瞭解決方案,這個方案雖然不能夠完全解決Full GC帶來的問題,但在一定程度上延緩了Full GC的產生間隔,總之減少了內存碎片導致的full gc,提高整體性能。
<property>
<name>hbase.hregion.memstore.mslab.enabled</name>
<value>true</value>
</property>
#當任意一個store中有超過hbase.hstore.blockingStoreFiles個數的storefiles時,這個store所在region的update操作將會被阻塞,除非這個region的compaction操作完成或者hbase.hstore.blockingWaitTime超時。
Block操作會嚴重影響當前regionserver的響應時間,但過多的storefiles會影響讀性能,站在實際使用的角度,爲了獲取較爲平滑的響應時間,可以將該值設得很大,甚至無限大。默認值爲7,這裏暫時調大到100。
<property>
<name>hbase.hstore.blockingStoreFiles</name>
<value>100</value>
</property>
#一次minor compaction的最大file數
<property>
<name>hbase.hstore.compaction.max</name>
<value>10</value>
</property>
#一次minor compaction的最小file數
<property>
<name>hbase.hstore.compactionThreshold</name>
<value>4</value>
</property>
#本地文件目錄用來作爲hbase在本地的存儲
<property>
<name>hbase.local.dir</name>
<value>${hbase.tmp.dir}/local</value>
</property>
#todo
#與前文配置項圖中第二紅線標註的配置項重複
<property>
<name>hbase.master.distributed.log.splitting</name>
<value>ture</value>
</property>
#hbase master web界面綁定的IP地址(任何網卡的ip都可以訪問)
<property>
<name>hbase.master.info.bindAddress</name>
<value>0.0.0.0</value>
</property>
#hbase master web界面綁定端口
<property>
<name>hbase.master.info.port</name>
<value>16010</value>
</property>
#todo
<property>
<name>hbase.master.port</name>
<value>16000</value>
</property>
#分配1%的regionserver的內存給寫操作當作緩存,這個參數和下面的hfile.block.cache.size(讀緩存)息息相關,二者之和不能超過總內存的80%,讀操作時,該值最好爲0,但是這裏有個bug,取不到0,所以取值1%即0.01,系統儘可能的把內存給讀操作用作緩存
<property>
<name>hbase.regionserver.global.memstore.size</name>
<value>0.01</value>
</property>
#regionserver處理IO請求的線程數,默認是30這裏調高到240
<property>
<name>hbase.regionserver.handler.count</name>
<value>240</value>
</property>
#regionserver 信息 web界面接口
<property>
<name>hbase.regionserver.info.port</name>
<value>16030</value>
</property>
#regionserver服務端口
<property>
<name>hbase.regionserver.port</name>
<value>16020</value>
</property>
#todo
<property>
<name>hbase.regionserver.wal.codec</name>
<value>org.apache.hadoop.hbase.regionserver.wal.WALCellCodec</value>
</property>
#hbase所有表的文件存放在hdfs中的路徑,用戶可以在hdfs的web頁面和後臺命令行中查看,若要徹底刪除表,現在hbase中刪除,然後在hdfs中刪除源文件即可,drop命令運行過後hdfs上內容沒有刪除情況下。
<property>
<name>hbase.rootdir</name>
<value>hdfs://node1.dcom:8020/apps/hbase/data</value>
</property>
#todo
<property>
<name>hbase.rpc.protection</name>
<value>authentication</value>
</property>
#hbase rpc操作超時時間
<property>
<name>hbase.rpc.timeout</name>
<value>90000</value>
</property>
#todo
<property>
<name>hbase.security.authentication</name>
<value>simple</value>
</property>
#todo
<property>
<name>hbase.security.authorization</name>
<value>false</value>
</property>
#todo
<property>
<name>hbase.superuser</name>
<value>hbase</value>
</property>
#本地文件系統上的臨時目錄,最好不要使用/tmp下的目錄,以免重啓後丟失文件
<property>
<name>hbase.tmp.dir</name>
<value>/tmp/hbase-${user.name}</value>
</property>
#zookeeper配置文件zoo.cfg中定義的內容,zookeeper 客戶端通過該port連接上zookeeper服務
<property>
<name>hbase.zookeeper.property.clientPort</name>
<value>2181</value>
</property>
#zookeeper服務的節點數目和各節點名稱
<property>
<name>hbase.zookeeper.quorum</name>
<value>node1.dcom,node2.dcom,node3.dcom</value>
</property>
#zookeeper支持多重update
<property>
<name>hbase.zookeeper.useMulti</name>
<value>true</value>
</property>
#將regionserver的內存的79%分配作爲讀緩存,默認是40%,這裏因爲是單獨的讀操作性能調優所以調到了79%,上文中提到了一個bug,不能調爲最高的80%。該配置項與上文中的hbase.regionserver.global.memstore.size關係密切,二者的總和不能大於regionserver內存的80%,讀操作爲主時就將該值調高,寫操作爲主時就將hbase.regionserver.global.memstore.size調高
<property>
<name>hfile.block.cache.size</name>
<value>0.79</value>
</property>
#todo
<property>
<name>phoenix.query.timeoutMs</name>
<value>60000</value>
</property>
#zookeeper session會話超時時間
<property>
<name>zookeeper.session.timeout</name>
<value>90000</value>
</property>
#znode 存放root region的地址
#todo
<property>
<name>zookeeper.znode.parent</name>
<value>/hbase-unsecure</value>
</property>
</configuration>
# RegionServers maximum value for –Xmn 新生代jvm內存大小,默認是1024,這裏調到了4096,這個參數影響到regionserver 的jvm的CMS GC,64G內存的話建議1~3G,最大爲4G,regionserver –Xmn in –Xmx ratio配置項也密切相關,該比例設置的太大或者太小都不好,這方面涉及到的內容太多,後續再詳細介紹。
# Number of Fetched Rows when Scanning from Disk這個就是上文中提到的hbase.client.scanner.caching
# Maximum Store Files before Minor Compaction 在執行Minor Compaction合併操作前Store Files的最大數目,默認是3,這裏調到了4
————————————————
# The maximum amount of heap to use, in MB. Default is 1000.
#export HBASE_HEAPSIZE=3000 分配給hbase服務的內存,默認是1000,由於hbase較耗內存,所以提高到了3000
這個地方有疑問:這裏配置這麼小的內存到底是給誰用的?
1)另外還有幾個重要的配置參數介紹一下(這裏其實是我遇到個一個疑問)
Hbase.regionserver.global.memstore.uppperLimit默認0.4
Hbase.regionserver.global.memstore.lowerLimit默認0.35
一個regionserver會有多個region,多個memstore,所以可能單個region並沒有超過閾值,但是整個regionserver的內存佔用已經非常多了,上面這兩個參數也會去控制和影響內存的刷寫,當regionserver上全部的memstore佔用超過heap(heap的值在hbase-env.sh中設置,HBASE_HEAPSIZE默認爲1000,我們這裏設置爲3000)的40%時,強制阻塞所有的寫操作,將所有的memstore刷寫到HFile;當所有的memstore佔用超過heap的35%時,會選擇一些佔用內存比較大的memstore阻塞寫操作並進行flush。
注意:
這兩個配置項,在當前的環境中並未找到!懷疑是直接當作默認值,用戶可以自行添加修改?
Hbase的scan操作是一種批量讀取的操作,scan與read不同,scan一次性請求大量數據,默認的話是讀取全表,這就需要在客戶端的本地佔用很大的內存來緩存一次批量拉取的數據,下面介紹一下幾個關係密切的配置項。
讀取hbase數據的順序是:
先去memstore中查找,找不到再去blockcahe中,如果沒有就去hdfs中查找,找到之後讀取的同時保存一份到blockcahe中便於下次查找。
memstore和blockcahe都是在內存中查找速度很快,延時很低,性能很好,而在hdfs中查找和讀取就涉及到磁盤的讀取操作,磁盤IO消耗性能較大。
(1)hadoop配置
#當一次scan操作不在本地內存時,需要從disk中獲取時,緩存的條數,這裏設置爲100000條,該值不能大於下文中hbase.client.scanner.timeout.period配置項的值。該數值也並不是越高越好,太高的話scan超時時間就會很長,影響性能,一次性獲取條數固然多,但由於帶寬和其他的限制並不能很好的消化掉,太低當然也不行,配置時需要根據具體情況具體設置。
一條數據長度爲9k的話,一次緩存100000條就需要900MB,所以對ycsb client端有較高的內存要求。
<property>
<name>hbase.client.scanner.caching</name>
<value>100000</value>
</property>
#Scanner超時時間,必須大於hbase.client.scanner.caching的數值。這個參數是在配置hbase.client.scanner.caching後hadoop報錯之後我自己加的。
<property>
<name>hbase.client.scanner.timeout.period</name>
<value>120000</value>
</property>
Hbase本身提供了讀緩存,具體可以查看上面hbase-site.xml文件解析,本集羣環境中每個regionserver可提供最多40G左右的讀緩存。
簡單介紹下Hbase讀操作read的原理,首先去memstore中查找,查不到就在讀緩存blockcache中查找,再查不到就去hdfs也就是硬盤中查,並且將查到的結果放置在讀緩存blockcache中以便下次查找。Blockcache是一個LRU,當blockcache達到上限(heapsize*hfile.block.cache.size*0.85)時,會啓動淘汰機制,淘汰掉最老的一批數據。
Scan操作可以設置每次scan取到的條數,一次讀的越大每條數據消耗的RPC也就越少,性能也就相應會提高,但是設置的越大對內存的要求也就越高,應根據實際設備性能調整大小。
(1)hadoop配置
這裏介紹幾個關鍵配置:
#分配1%的regionserver的內存給寫操作當作緩存,這個參數和下面的hfile.block.cache.size(讀緩存)息息相關,二者之和不能超過總內存的80%,讀操作時,該值最好爲0,但是這裏有個bug,取不到0,所以取值1%即0.01,系統儘可能的把內存給讀操作用作緩存。
<property>
<name>hbase.regionserver.global.memstore.size</name>
<value>0.01</value>
</property>
#將regionserver的內存的79%分配作爲讀緩存,默認是40%,這裏因爲是單獨的讀操作性能調優所以調到了79%,上文中提到了一個bug,不能調爲最高的80%。該配置項與上文中的hbase.regionserver.global.memstore.size關係密切,二者的總和不能大於regionserver內存的80%,讀操作爲主時就將該值調高,寫操作爲主時就將hbase.regionserver.global.memstore.size調高。
<property>
<name>hfile.block.cache.size</name>
<value>0.79</value>
</property>
配置調優要點
本次測試一條數據長度爲9KB,共寫入40000000條,大概有1TB左右,集羣總共是200個region,每個region大小爲默認的10G,集羣總大小爲2TB。集羣總量足夠,rowkey分佈均勻的話不會發生集羣的splits操作。
(1)這裏簡單介紹下hbase 寫流程和原理:
客戶端流程解析:
a) 用戶提交put請求後,HBase客戶端會將put請求添加到本地buffer中,符合一定條件就會通過 AsyncProcess異步批量提交。HBase默認設置autoflush=true,表示put請求直接會提交給服務器進行處理;用戶可以設置autoflush=false,這樣的話put請求會首先放到本地buffer,等到本地buffer大小超過一定閾值(默認爲2M,可以通過配置文件配置)之後纔會提交。很顯然,後者採用groupcommit機制提交請求,可以極大地提升寫入性能,但是因爲沒有保護機制,如果客戶端崩潰的話會導致提交的請求丟失。
b) 在提交之前,HBase會在元數據表.meta.中根據rowkey找到它們歸屬的region server,這個定位的過程是通過HConnection的locateRegion方法獲得的。如果是批量請求的話還會把這些rowkey按照 HRegionLocation分組,每個分組可以對應一次RPC請求。
c) HBase會爲每個HRegionLocation構造一個遠程RPC請求 MultiServerCallable<Row>,然後通過rpcCallerFactory.<MultiResponse> newCaller()執行調用,忽略掉失敗重新提交和錯誤處理,客戶端的提交操作到此結束。
服務器端流程解析
a) 服務器端RegionServer接收到客戶端的寫入請求後,首先會反序列化爲Put對象,然後執行各種檢查操作,比如檢查region是否是隻讀、memstore大小是否超過blockingMemstoreSize等。檢查完成之後,就會執行如下核心操作:
b) 獲取行鎖、Region更新共享鎖:HBase中使用行鎖保證對同一行數據的更新都是互斥操作,用以保證更新的原子性,要麼更新成功,要麼失敗。
c) 開始寫事務:獲取write number,用於實現MVCC,實現數據的非鎖定讀,在保證讀寫一致性的前提下提高讀取性能。
d) 寫緩存memstore:HBase中每列都會對應一個store,用來存儲該列數據。每個store都會有個寫緩存memstore,用於緩存寫入數據。HBase並不會直接將數據落盤,而是先寫入緩存,等緩存滿足一定大小之後再一起落盤。
e) Append HLog:HBase使用WAL機制保證數據可靠性,即首先寫日誌再寫緩存,即使發生宕機,也可以通過恢復HLog還原出原始數據。該步驟就是將數據構造爲WALEdit對象,然後順序寫入HLog中,此時不需要執行sync操作。0.98版本採用了新的寫線程模式實現HLog日誌的寫入,可以使得整個數據更新性能得到極大提升。
f) 釋放行鎖以及共享鎖
g) Sync HLog:HLog真正sync到HDFS,在釋放行鎖之後執行sync操作是爲了儘量減少持鎖時間,提升寫性能。如果Sync失敗,執行回滾操作將memstore中已經寫入的數據移除。
h) 結束寫事務:此時該線程的更新操作纔會對其他讀請求可見,更新才實際生效。
i) flush memstore:當寫緩存滿256M之後,會啓動flush線程將數據刷新到硬盤。刷新操作涉及到HFile相關結構可參考相關資料,這裏不細說。
(2)hadoop配置
#當一個region的memstore總量達到hbase.hregion.memstore.block.multiplier* hbase.hregion.memstore.flush.size (默認2*128M)時,會阻塞這個region的寫操作,並強制刷寫到HFile,觸發這個刷新操作只會在Memstore即將寫滿hbase.hregion.memstore.flush.size時put了一個巨大的記錄的情況,這時候會阻塞寫操作,強制刷新成功才能繼續寫入。
該配置項默認爲2,調大至8,降低block發生的概率。
<property>
<name>hbase.hregion.memstore.block.multiplier</name>
<value>8</value>
</property>
#每個單獨的memstore的大小(默認128M),這裏調成了256M,每個列族columnfamily在每個region中都分配有它單獨的memstore,當memstore超過該值時,就會發生flush操作,將memstore中的內容刷成一個hfile,每一次memstore的flush操作,都會爲每一次columnfamily創建一個新的hfile;調高該值可以減少flush的操作次數,減少每一個region中的hfile的個數,這樣就會減少minor compaction的次數和split的次數,從而降低了系統性能損耗,提升了寫性能,也提升了讀性能(因爲讀操作的時候,首先要去memstore中查數據,查找不到的話再去hfile,hflie存儲在hdfs中,這就涉及到了對性能要求較高的io操作了)。當然這個值變大了之後,每次flush操作帶來的性能消耗也就更大。
<property>
<name>hbase.hregion.memstore.flush.size</name>
<value>268435456</value>
</property>
#分配75%的regionserver的內存給寫操作當作緩存,這個參數和下面的hfile.block.cache.size(讀緩存)息息相關,二者之和不能超過總內存的80%,追求寫入性能時,該值儘量設置的大一些;追求讀操作性能時,該值儘量取得小一些,但這裏有個bug,該值取不到0,現將該值設置爲0.75。
<property>
<name>hbase.regionserver.global.memstore.size</name>
<value>0.75</value>
</property>
#與上面相呼應,將regionserver的內存的5%分配作爲讀緩存,默認是40%,上文中提到了一個bug,不能調爲最高的80%。該配置項與上文中的hbase.regionserver.global.memstore.size關係密切,二者的總和不能大於regionserver內存的80%,讀操作爲主時就將該值調高,寫操作爲主時就將hbase.regionserver.global.memstore.size調高。
<property>
<name>hfile.block.cache.size</name>
<value>0.05</value>
</property>