使用hbase的目的是爲了海量數據的隨機讀寫,可是在實際使用中卻發現針對隨機讀的優化和gc是一個很大的問題,並且hbase的數據是存儲在Hdfs,而Hdfs是面向流失數據訪問進行設計的,就不免帶來效率的降低。下面介紹一下Facebook Message系統在HBase online storage場景下的一個案例(《Apache Hadoop Goes Realtime at Facebook》, SIGMOD 2011),最近他們在存儲領域頂級會議FAST2014上發表了一篇論文《Analysis of HDFS Under HBase: A Facebook Messages Case Study》分析了他們在使用HBase中遇到的一些問題和解決方案。該論文首先講了Facebook的分析方法包括tracing/analysis/simulation,FM系統的架構和文件與數據構成等,接下來開始分析FM系統在性能方面的一些問題,並提出瞭解決方案。
FM系統的主要讀寫I/O負載 數據庫
Figure 2描述了每一層的I/O構成,解釋了在FM系統對外請求中讀佔主導,可是因爲logging/compaction/replication/caching致使寫被嚴重放大。apache
總的來講,HBase stack的logging/compaction/replication/caching會放大寫I/O,致使業務邏輯上讀爲主導的HBase系統在地層實際磁盤I/O中寫佔據了主導。
FM系統的主要文件類型和大小 緩存
FM系統的幾種文件類型如Table 2所示,這個是純業務的邏輯描述。在HBase的每一個RegionServer上的每一個column family對應一個或者多個HFile文件。FM系統中有8個column family,因爲每一個column family存儲的數據的類型和大小不同,使得每一個column family的讀寫比是不同的。並且不多數據是讀寫都會請求的,因此cache all writes可能做用不大(Figure 4)。 網絡
對於每一個column family的文件,90%是小於15M的。可是少許的特別大的文件會拉高column family的平均文件大小。例如MessageMeta這個column family的平均文件大小是293M。從這些文件的生命週期來看,大部分FM的數據存儲在large,long-lived files,然而大部分文件倒是small, short-lived。這對HDFS的NameNode提出了很大的挑戰,由於HDFS設計的初衷是爲了存儲少許、大文件準備的,全部的文件的元數據是存儲在NameNode的內存中的,還有有NameNode federation。
FM系統的主要I/O訪問類型下面從temporal locality, spatial locality, sequentiality的角度來看。
73.7%的數據只被讀取了一次,可是1.1%的數據被讀取了至少64次。也就是說只有少部分的數據被重複讀取了。可是從觸發I/O的角度,只有19%的讀操做讀取的是隻被讀取一次的數據,而大部分I/O是讀取那些熱數據。
在HDFS這一層,FM讀取數據沒有表現出sequentiality,也就是說明high-bandwidth, high-latency的機械磁盤不是服務讀請求的理想存儲介質。並且對數據的讀取也沒有表現出spatial locality,也就是說I/O預讀取也沒啥做用。
解決方案1. Flash/SSD做爲cache使用。 架構
下面就考慮怎麼架構可以加速這個系統了。目前Facebook的HBase系統每一個Node掛15塊100MB/s帶寬、10ms尋址時間的磁盤。Figure 9代表:a)增長磁盤塊數有點用;b)增長磁盤帶寬沒啥大用;c)下降尋址時間很是有用。
因爲少部分一樣的數據會被常常讀取,因此一個大的cache可以把80%左右的讀取操做攔截而不用觸發磁盤I/O,並且只有這少部分的hot data須要被cache。那麼拿什麼樣的存儲介質作cache呢?Figure 11說明若是拿足夠大的Flash作二級緩存,cache命中率會明顯提升,同時cache命中率跟內存大小關係並不大。
注:關於拿Flash/SSD作cache,能夠參考HBase BucketBlockCache(HBASE-7404) app
咱們知道你們比較關心Flash/SSD壽命的問題,在內存和Flash中shuffling數據可以使得最熱的數據被交換到內存中,從而提高讀性能,可是會下降Flash的壽命,可是隨着技術的發展這個問題帶來的影響可能愈來愈小。
說完加速讀的cache,接着討論了Flash做爲寫buffer是否會帶來性能上的提高。因爲HDFS寫操做只要數據被DataNode成功接收到內存中就保證了持久性(由於三臺DataNode同時存儲,因此認爲從DataNode的內存flush到磁盤的操做不會三個DataNode都失敗),因此拿Flash作寫buffer不會提升性能。雖然加寫buffer會使後臺的compaction操做下降他與前臺服務的I/O爭用,可是會增長很大複雜度,因此仍是不用了。最後他們給出告終論就是拿Flash作寫buffer沒用。
而後他們還計算了,在這個存儲棧中加入Flash作二級緩存不但能提高性能達3倍之多,並且只須要增長5%的成本,比加內存性價比高不少。
2.分層架構的缺點和改進方案 分佈式
如Figure 16所示,通常分佈式數據庫系統分爲三個層次:db layer/replication layer/local layer。這種分層架構的最大優勢是簡潔清晰,每層各司其職。例如db layer只須要處理DB相關的邏輯,底層的存儲認爲是available和reliable的。
HBase是圖中a)的架構,數據的冗餘replication由HDFS來負責。可是這個帶來一個問題就是例如compaction操做會讀取多個三備份的小文件到內存merge-sorting成一個三備份的大文件,這個操做只能在其中的一個RS/DN上完成,那麼從其餘RS/DN上的數據讀寫都會帶來網絡傳輸I/O。
圖中b)的架構就是把replication層放到了DB層的上面,Facebook舉的例子是Salus,不過我對這個東西不太熟悉。我認爲Cassandra就是這個架構的。這個架構的缺點就是DB層須要處理底層文件系統的問題,還要保證和其餘節點的DB層協調一致,太複雜了。
圖中c)的架構是在a的基礎上的一種改進,Spark使用的就是這個架構。HBase的compaction操做就能夠簡化成join和sort這樣兩個RDD變換。 oop
Figure 17展現了local compaction的原理,原來的網絡I/O的一半轉化成了本地磁盤讀I/O,並且能夠利用讀cache加速。咱們都知道在數據密集型計算系統中網絡交換機的I/O瓶頸很是大,例如MapReduce Job中Data Shuffle操做就是最耗時的操做,須要強大的網絡I/O帶寬。加州大學聖迭戈分校(UCSD)和微軟亞洲研究院(MSRA)都曾經設計專門的數據中心網絡拓撲來優化網絡I/O負載,相關研究成果在計算機網絡頂級會議SIGCOMM上發表了多篇論文,可是因爲其對網絡路由器的改動傷筋動骨,最後都沒有成功推廣開來。 性能
Figure 19展現了combined logging的原理。如今HBase的多個RS會向同一個DataNode發送寫log請求,而目前DataNode端會把來自這三個RS的log分別寫到不一樣的文件/塊中,會致使該DataNode磁盤seek操做較多(再也不是磁盤順序I/O,而是隨機I/O)。Combined logging就是把來自不一樣RS的log寫到同一個文件中,這樣就把DataNode的隨機I/O轉化成了順序I/O。優化