深刻理解HBase Memstore

轉自: http://www.cnblogs.com/shitouer/archive/2013/02/05/configuring-hbase-memstore-what-you-should-know.htmlhtml

MemStore是HBase很是重要的組成部分,深刻理解MemStore的運行機制、工做原理、相關配置,對HBase集羣管理以及性能調優有很是重要的幫助。

HBase Memstore

首先經過簡單介紹HBase的讀寫過程來理解一下MemStore究竟是什麼,在何處發揮做用,如何使用到以及爲何要用MemStore。算法

圖一:Memstore Usage in HBase Read/Write Paths緩存

當RegionServer(RS)收到寫請求的時候(write request),RS會將請求轉至相應的Region。每個Region都存儲着一些列(a set of rows)。根據其列族的不一樣,將這些列數據存儲在相應的列族中(Column Family,簡寫CF)。不一樣的CFs中的數據存儲在各自的HStore中,HStore由一個Memstore及一系列HFile組成。Memstore位於RS的主內存中,而HFiles被寫入到HDFS中。當RS處理寫請求的時候,數據首先寫入到Memstore,而後當到達必定的閥值的時候,Memstore中的數據會被刷到HFile中。安全

用到Memstore最主要的緣由是:存儲在HDFS上的數據須要按照row key 排序。而HDFS自己被設計爲順序讀寫(sequential reads/writes),不容許修改。這樣的話,HBase就不可以高效的寫數據,由於要寫入到HBase的數據不會被排序,這也就意味着沒有爲未來的檢索優化。爲了解決這個問題,HBase將最近接收到的數據緩存在內存中(in Memstore),在持久化到HDFS以前完成排序,而後再快速的順序寫入HDFS。須要注意的一點是實際的HFile中,不只僅只是簡單地排序的列數據的列表,詳見Apache HBase I/O – HFile網絡

除了解決「無序」問題外,Memstore還有一些其餘的好處,例如:app

  • 做爲一個內存級緩存,緩存最近增長數據。一種顯而易見的場合是,新插入數據老是比老數據頻繁使用。
  • 在持久化寫入以前,在內存中對Rows/Cells能夠作某些優化。好比,當數據的version被設爲1的時候,對於某些CF的一些數據,Memstore緩存了數個對該Cell的更新,在寫入HFile的時候,僅須要保存一個最新的版本就行了,其餘的均可以直接拋棄。

有一點須要特別注意:每一次Memstore的flush,會爲每個CF建立一個新的HFile。 在讀方面相對來講就會簡單一些:HBase首先檢查請求的數據是否在Memstore,不在的話就到HFile中查找,最終返回merged的一個結果給用戶。oop

HBase Memstore關注要點

迫於如下幾個緣由,HBase用戶或者管理員須要關注Memstore而且要熟悉它是如何被使用的:性能

  • Memstore有許多配置能夠調整以取得好的性能和避免一些問題。HBase不會根據用戶本身的使用模式來調整這些配置,你須要本身來調整。
  • 頻繁的Memstore flush會嚴重影響HBase集羣讀性能,並有可能帶來一些額外的負載。
  • Memstore flush的方式有可能影響你的HBase schema設計

接下來詳細討論一下這些要點:優化

Configuring Memstore Flushes

對Memstore Flush來講,主要有兩組配置項:this

  • 決定Flush觸發時機
  • 決定Flush什麼時候觸發而且在Flush時候更新被阻斷(block)

第一組是關於觸發「普通」flush,這類flush發生時,並不影響並行的寫請求。該類型flush的配置項有:

  • hbase.hregion.memstore.flush.size
1
2
3
4
5
6
7
8
9
< property >
  < name >hbase.hregion.memstore.flush.size</ name >
  < value >134217728</ value >
  < description >
  Memstore will be flushed to disk if size of the memstore
  exceeds this number of bytes. Value is checked by a thread that runs
  every hbase.server.thread.wakefrequency.
  </ description >
</ property >
  • base.regionserver.global.memstore.lowerLimit
1
2
3
4
5
6
7
8
9
10
< property >
  < name >hbase.regionserver.global.memstore.lowerLimit</ name >
  < value >0.35</ value >
  < description >Maximum size of all memstores in a region server before
  flushes are forced. Defaults to 35% of heap.
  This value equal to hbase.regionserver.global.memstore.upperLimit causes
  the minimum possible flushing to occur when updates are blocked due to
  memstore limiting.
  </ description >
</ property >

須要注意的是第一個設置是每一個Memstore的大小,當你設置該配置項時,你須要考慮一下每臺RS承載的region總量。可能一開始你設置的該值比較小,後來隨着region增多,那麼就有可能由於第二個設置緣由Memstore的flush觸發會變早許多。

第二組設置主要是出於安全考慮:有時候集羣的「寫負載」很是高,寫入量一直超過flush的量,這時,咱們就但願memstore不要超過必定的安全設置。在這種狀況下,寫操做就要被阻止(blocked)一直到memstore恢復到一個「可管理」(manageable)的大小。該類型flush配置項有:

  • hbase.regionserver.global.memstore.upperLimit
1
2
3
4
5
6
7
8
9
< property >
  < name >hbase.regionserver.global.memstore.upperLimit</ name >
  < value >0.4</ value >
  < description >Maximum size of all memstores in a region server before new
  updates are blocked and flushes are forced. Defaults to 40% of heap.
  Updates are blocked and flushes are forced until size of all memstores
  in a region server hits hbase.regionserver.global.memstore.lowerLimit.
  </ description >
</ property >
  •  hbase.hregion.memstore.block.multiplier
1
2
3
4
5
6
7
8
9
10
11
12
< property >
  < name >hbase.hregion.memstore.block.multiplier</ name >
  < value >2</ value >
  < description >
  Block updates if memstore has hbase.hregion.block.memstore
  time hbase.hregion.flush.size bytes. Useful preventing
  runaway memstore during spikes in update traffic. Without an
  upper-bound, memstore fills such that when it flushes the
  resultant flush files take a long time to compact or split, or
  worse, we OOME.
  </ description >
</ property >

某個節點「寫阻塞」對該節點來講影響很大,可是對於整個集羣的影響更大。HBase設計爲:每一個Region僅屬於一個RS可是「寫負載」是均勻分佈於整個集羣(全部Region上)。有一個如此「慢」的節點,將會使得整個集羣都會變慢(最明顯的是反映在速度上)。

提示:嚴重關切Memstore的大小和Memstore Flush Queue的大小。理想狀況下,Memstore的大小不該該達到hbase.regionserver.global.memstore.upperLimit的設置,Memstore Flush Queue 的size不能持續增加。

頻繁的Memstore Flushes

要避免「寫阻塞」,貌似讓Flush操做盡可能的早於達到觸發「寫操做」的閾值爲宜。可是,這將致使頻繁的Flush操做,而由此帶來的後果即是讀性能降低以及額外的負載。

每次的Memstore Flush都會爲每一個CF建立一個HFile。頻繁的Flush就會建立大量的HFile。這樣HBase在檢索的時候,就不得不讀取大量的HFile,讀性能會受很大影響。

爲預防打開過多HFile及避免讀性能惡化,HBase有專門的HFile合併處理(HFile Compaction Process)。HBase會週期性的合併數個小HFile爲一個大的HFile。明顯的,有Memstore Flush產生的HFile越多,集羣系統就要作更多的合併操做(額外負載)。更糟糕的是:Compaction處理是跟集羣上的其餘請求並行進行的。當HBase不可以跟上Compaction的時候(一樣有閾值設置項),會在RS上出現「寫阻塞」。像上面說到的,這是最最不但願的。

提示:嚴重關切RS上Compaction Queue 的size。要在其引發問題前,阻止其持續增大。

想了解更多HFile 建立和合並,可參看 Visualizing HBase Flushes And Compactions

理想狀況下,在不超過hbase.regionserver.global.memstore.upperLimit的狀況下,Memstore應該儘量多的使用內存(配置給Memstore部分的,而不是真個Heap的)。下圖展現了一張「較好」的狀況:

 「Somewhat」, because we could configure lower limit to be closer to upper, since we barely ever go over it.

說是「較好」,是由於咱們能夠將「Lower limit」配置的更接近於「Upper limit」,咱們幾乎不多有超過它。

Multiple Column Families & Memstore Flush

每次Memstore Flush,會爲每一個CF都建立一個新的HFile。這樣,不一樣CF中數據量的不均衡將會致使產生過多HFile:當其中一個CF的Memstore達到閾值flush時,全部其餘CF的也會被flush。如上所述,太頻繁的flush以及過多的HFile將會影響集羣性能。

提示:不少狀況下,一個CF是最好的設計。

HLog (WAL) Size & Memstore Flush

第一張HBase Read/Write path圖中,你可能已經注意到當數據被寫入時會默認先寫入Write-ahead Log(WAL)。WAL中包含了全部已經寫入Memstore但還未Flush到HFile的更改(edits)。在Memstore中數據尚未持久化,當RegionSever宕掉的時候,可使用WAL恢復數據。

當WAL(在HBase中成爲HLog)變得很大的時候,在恢復的時候就須要很長的時間。所以,對WAL的大小也有一些限制,當達到這些限制的時候,就會觸發Memstore的flush。Memstore flush會使WAL 減小,由於數據持久化以後(寫入到HFile),就沒有必要在WAL中再保存這些修改。有兩個屬性能夠配置:

  •  hbase.regionserver.hlog.blocksize
  • hbase.regionserver.maxlogs

你可能已經發現,WAL的最大值由hbase.regionserver.maxlogs * hbase.regionserver.hlog.blocksize (2GB by default)決定。一旦達到這個值,Memstore flush就會被觸發。因此,當你增長Memstore的大小以及調整其餘的Memstore的設置項時,你也須要去調整HLog的配置項。不然,WAL的大小限制可能會首先被觸發,於是,你將利用不到其餘專門爲Memstore而設計的優化。拋開這些不說,經過WAL限制來觸發Memstore的flush並不是最佳方式,這樣作可能會會一次flush不少Region,儘管「寫數據」是很好的分佈於整個集羣,進而頗有可能會引起flush「大風暴」。

提示:最好將hbase.regionserver.hlog.blocksize * hbase.regionserver.maxlogs 設置爲稍微大於hbase.regionserver.global.memstore.lowerLimit * HBASE_HEAPSIZE.

Compression & Memstore Flush

HBase建議壓縮存儲在HDFS上的數據(好比HFiles)。除了節省硬盤空間,一樣也會顯著地減小硬盤和網絡IO。使用壓縮,當Memstore flush並將數據寫入HDFS時候,數據會被壓縮。壓縮不會減慢多少flush的處理過程,卻會大大減小以上所述問題,例如由於Memstore變大(超過 upper limit)而引發的「寫阻塞」等等。

提示:壓縮庫建議使用Snappy。有關Snappy的介紹及安裝,可分別參考:《Hadoop壓縮-SNAPPY算法》和《Hadoop HBase 配置 安裝 Snappy 終極教程

相關文章
相關標籤/搜索