標籤:

HBase讀性能怎麼樣?

在生產環境直接讀是否可以?是否需要在前面擋一層MC或者Redis的緩存嗎?


HBase是一個寫快讀慢的系統(當然,這裡的慢是相對於寫來說的)。若生產環境是一個read heavy場景,可對HBase做讀優化,主要手段是:1)增強系統IO能力(HDFS層面); 2)增大BlockCache; 3) 調整Major Compaction策略。若隨機讀為主,還可以調小blocksize。具體的性能指標可以參考Yahoo ycsb論文: http://labs.yahoo.com/news/yahoo-cloud-serving-benchmark/


謝邀

國內用HBase的公司很多啊,生產環境用當然不是問題。有個人的回答說HBase不行用hdfs的不行得用rocksdb,我只能說,他提到的那些公司除了百度外都也用HBase。。。百度我不確定有沒有用,但內部造的有的輪子也是bigtable的架構,底下一樣是分散式文件系統。。。更別說如果簡單搞個主從是最終一致性了。。

至於說延遲如何要不要用緩存抗,這個你得自己測,不同場景不同硬體測出來的數據完全不一樣,大多數場景其實也不需要緩存因為HBase本來也有cache。

最後不得不對好幾個人說一句,不懂彆強答了。。


HBase是一種NoSQL,通常被稱為Hadoop Database,它是開源並基於Google Big Table白皮書,HBase運行在HDFS之上,因此使它具有高度可擴展性,並支持Hadoop map-reduce程序設計模型。HBase有兩種訪問方式:通過行鍵進行隨機訪問;通過map-reduce離線或批訪問。

谷歌曾經面對過一個挑戰的問題:如何能在整個互聯網上提供實時的搜索結果?答案是它本質上需要將互聯網緩存,並重新定義在這樣龐大的緩存上快速查找的新方法。為了達到這個目的,定義如下技術:

  • 谷歌文件系統GFS:可擴展分散式文件系統,用於大型的、分散式的、數據密集型的應用程序。

  • BigTable:分散式存儲系統,用於管理被設計成規模很大的結構化數據:來自數以千計商用伺服器的PB級別的數據。

  • MapReduce:一個程序模型,用於處理和生成大數據集的相關實現。

在谷歌發布這些技術的文檔之後, 不久以後我們就看到了它們的開源實現版本 ,就在2007年,Mike Cafarella發布了BigTable開源實現的代碼,他稱其為HBase,自此,HBase成為Apache的頂級項目,並運行在Facebook,Twitter,Adobe……僅舉幾個例子。

HBase不是一個關係型資料庫,它需要不同的方法定義你的數據模型,HBase實際上定義了一個四維數據模型,下面就是每一維度的定義:

  • 行鍵:每行都有唯一的行鍵,行鍵沒有數據類型,它內部被認為是一個位元組數組。

  • 列簇:數據在行中被組織成列簇,每行有相同的列簇,但是在行之間,相同的列簇不需要有相同的列修飾符。在引擎中,HBase將列簇存儲在它自己的數據文件中,所以,它們需要事先被定義,此外,改變列簇並不容易。

  • 列修飾符:列簇定義真實的列,被稱之為列修飾符,你可以認為列修飾符就是列本身。

  • 版本:每列都可以有一個可配置的版本數量,你可以通過列修飾符的制定版本獲取數據。

HBase Four-Dimensional Data Model

如圖1中所示,通過行鍵獲取一個指定的行,它由一個或多個列簇構成,每個列簇有一個或多個列修飾符(圖1中稱為列),每列又可以有一個或多個版本。為了獲取指定數據,你需要知道它的行鍵、列簇、列修飾符以及版本。當設計HBase數據模型時,對考慮數據是如何被獲取是十分有幫助的。你可以通過以下兩種方式獲得HBase數據:

  • 通過他們的行鍵,或者一系列行鍵的表掃描。

  • 使用map-reduce進行批操作

這種雙重獲取數據的方法使得HBase變得十分強大,典型地,在Hadoop中存儲數據意味著它對離線或批處理方式分析是有益的(尤其是批處理分析),但是,對實時獲取是不必要的。HBase通過key/value存儲來支持實時分析,以及通過map-reduce支持批處理分析。讓我們首先來看實時數據獲取,作為key/value存儲,key是行鍵,value是列簇的集合,如圖2所示。

HBase as a Key/Value Store

如你在圖2中看到的,key是我們所提到過的行鍵,value是列簇的集合。你可以通過key檢索到value,或者換句話說,你可以通過行鍵「得到」行,或者你能通過給定起始和終止行鍵檢索一系列行,這就是前面提到的表掃描。你不能實時的查詢一個列的值,這就引出了一個重要的話題:行鍵的設計。

有兩個原因令行鍵的設計十分重要:

  • 表掃描是對行鍵的操作,所以,行鍵的設計控制著你能夠通過HBase執行的實時/直接獲取量。

  • 當在生產環境中運行HBase時,它在HDFS上部運行,數據基於行鍵通過HDFS,如果你所有的行鍵都是以user-開頭,那麼很有可能你大部分數據都被分配一個節點上(違背了分散式數據的初衷),因此,你的行鍵應該是有足夠的差異性以便分散式地通過整個部署。

你定義行鍵的方式取決於你想怎樣存取那些行。如果你想以用戶為基礎存儲數據,那麼一個策略是利用位元組隊列在HBase中存儲行鍵,所以我們可以創建一個用戶ID的哈希(例如MD5或SHA-1),然後在哈希後面附上時間(long類型)。使用哈希有兩個重點:(1)是它能夠將value分散開,數據能夠分散式地通過簇,(2)是它確保key的長度是一致的,以更加容易在表掃描中使用。

講了足夠多的理論,下面部分向你展示如何搭建HBase環境,並如何通過命令行使用。

你可以從Apache網站下載HBase,HBase團隊推薦你在UNIX/Linux環境下安裝HBase,如果你想在Windows下運行,你需要先安裝Cygwin,並在這上運行HBase。當你下載完這些文件,解壓到硬碟上。此外,你還需要安裝Java環境,如果你還沒有,從Oracle網站下載Java環境。在環境配置中添加名為HBASE_HOME的變數,值為你解壓HBase文件的根目錄,隨後,執行bin文件夾下的start-hbase.sh腳本,它會在下面目錄輸出日誌文件:

$HBASE_HOME/logs/

你可以在瀏覽器中輸入下面URL測試是否安裝正確:

http://localhost:60010

如果安裝正確,你應該看到下面界面。

HBase Management Screen

讓我們開始用命令行操作HBase,在HBase bin目錄下執行下面命令:

./hbase shell

你應該看到如下類似的輸出:

1

2

3

4

5

6

7

HBase Shell; enter "help&" for list of supported commands.

Type "exit&" to leave the HBase Shell

Version 0.98.5-hadoop2, rUnknown, Mon Aug 4 23:58:06 PDT 2014

hbase(main):001:0&>

創建一個名為PageViews的表,並具有名為info的列簇:

1

2

3

4

5

hbase(main):002:0&> create "PageViews", "info"

0 row(s) in 5.3160 seconds

=&> Hbase::Table - PageViews

每張表至少要有一個列簇,因此我們創建了info,現在,看看我們的表,執行下面list命令:

1

2

3

4

5

6

7

8

9

hbase(main):002:0&> list

TABLE

PageViews

1 row(s) in 0.0350 seconds

=&> ["PageViews"]

如你所見,list命令返回一個名為PageViews的表,我們可以通過describe命令得到表的更多信息:

1

2

3

4

5

6

7

8

9

10

11

12

13

hbase(main):003:0&> describe "PageViews"

DESCRIPTION ENABLED

"PageViews", {NAME =&> "info", DATA_BLOCK_ENCODING =&> "NONE", BLOOMFILTER =&> "ROW",

REPLICATION_SCOPE =&> "0", VERSIONS =&> "1", COMPRESSION =&> "NONE true

", MIN_VERSIONS =&> "0", TTL =&> "FOREVER", KEEP_DELETED_CELLS =&> "false",

BLOCKSIZE =&> "65536", IN_MEMORY =&> "false", BLOCKCACHE =&> "true"}

1 row(s) in 0.0480 seconds

Describe命令返回表的詳細信息,包括列簇的列表,這裡我們創建的僅有一個:info,現在為表添加以下數據,下面命令是在info中添加新的行:

1

2

3

hbase(main):004:0> put #039;PageViews#039;, #039;rowkey1#039;, #039;info:page#039;, #039;/mypage#039;

0 row(s) in 0.0850 seconds

Put命令插入一條行鍵為rowkey1的新紀錄,指定在info下的page列,插入值為/mypage的記錄,我們隨後可以通過get命令通過行鍵rowkey1查詢到這條記錄:

1

2

3

4

5

6

7

hbase(main):005:0&> get "PageViews", "rowkey1"

COLUMN CELL

info:page timestamp=1410374788088, value=/mypage

1 row(s) in 0.0250 seconds

你可以看到列info:page,或者更多具體的列,其值為/mypage,並帶有時間戳表明該條記錄是什麼時候插入的。讓我們在做表掃描之前再添加一行:

1

2

3

hbase(main):006:0&> put "PageViews", "rowkey2", "info:page", "/myotherpage"

0 row(s) in 0.0050 seconds

現在我們有兩行記錄了,讓我們查詢出PageViews表的所有記錄:

1

2

3

4

5

6

7

8

9

hbase(main):007:0&> scan "PageViews"

ROW COLUMN+CELL

rowkey1 column=info:page, timestamp=1410374788088, value=/mypage

rowkey2 column=info:page, timestamp=1410374823590, value=/myotherpage

2 row(s) in 0.0350 seconds

如前面所提到的,我們不能查詢本身,但是我們可以對錶進行scan操作,如果你執行scan table命令,它會返回表中所有行,這很有可能不是你想要做的。你可以給出行的範圍來限制返回的結果,讓我們插入一帶有s開頭行鍵的新記錄:

1

hbase(main):012:0&> put "PageViews", "srowkey2", "info:page", "/myotherpage"

現在,如果我增加點限制,想查詢行鍵在r和s之間的記錄,可以使用如下結構:

1

2

3

4

5

6

7

8

9

hbase(main):014:0&> scan "PageViews", { STARTROW =&> "r", ENDROW =&> "s" }

ROW COLUMN+CELL

rowkey1 column=info:page, timestamp=1410374788088, value=/mypage

rowkey2 column=info:page, timestamp=1410374823590, value=/myotherpage

2 row(s) in 0.0080 seconds

這個scan返回了僅有s開頭的記錄,這個類比是基於全行鍵上的,所以rowkey1比r大,所有它被返回了。另外,scan的結果包含了所指範圍的STARTROW,但不包含ENDROW,注意,ENDROW不是必須指定的,如果我們執行相同查詢只給出了STARTROW,那麼我們會得到行鍵比r大的所有記錄。

1

2

3

4

5

6

7

8

9

10

11

hbase(main):013:0&> scan "PageViews", { STARTROW =&> "r" }

ROW COLUMN+CELL

rowkey1 column=info:page, timestamp=1410374788088, value=/mypage

rowkey2 column=info:page, timestamp=1410374823590, value=/myotherpage

srowkey2 column=info:page, timestamp=1410375975965, value=/myotherpage

3 row(s) in 0.0120 seconds


線上環境不建議採用hbase,由於hbase採用hdfs作為底層存儲,hdfs注重的是什麼?是吞吐,是容量可擴展,而對高並發且要求低延遲的線上系統,並不是很好的選擇。

目前業內普遍採用的是RocksDB+ssd盤的方式,facebook,百度,360,滴滴,頭條等很多公司都在使用RocksDB。優化後的RocksDB平均時延能做到&<2ms,p99時延&<5ms。十六節點,一主一備,讀並發上百萬。


這要看是否啟用bloomfilter 和 blockcache的,而且和region的內存,機器的內存,regionServer 是否對hdfs 本地化,是否採用壓縮,操作系統的buffer等相關因素太多了。

粗略的回答如下:

hbase 0.98的讀性能在150 - 400 之間, 沒啟用bloomfilter 和blockcache,冷數據(memstore被刷為0),情況下,在150左右。


內存有多大,hbase就有多快


那些說Hbase不行的人有沒有去了解過Hbase


這麼粗略的問題,我只能想到一個粗略的答案: 「和hbase的運維/使用人員的水平正相關」


HBase本身就是就具有高性能讀寫的特點。在讀上,本身就有BlockCache,而且在0.96版本中加入了bucket cache二級緩存,所有說他在讀上性能很好。在業務層面加入MC或者Redis來

緩存查詢結果更好,可以減少對HBase的請求次數,每次從HBase查當然沒有直接從MC或者Redis裡面取查詢結果快了。而且用MC或者Redis做分頁更好。


哪些說HBase讀性能不行的,不能在線上用的?就說一句:小米,阿里,京東,雅虎,FB都是線下公司?


hbase讀性能可以,關鍵設計好rowkey:

1,數據量大的讀hbase

2,數據量小的讀redis

3,也可以用redis做hbase的cache


這樣我想到某個看似非核心實則主流程強依賴的業務,由於運維手段和業務使用的原因,即便在前面擋了一層mc緩存,hbase的讀取性能仍然讓人深感無力。


若數據不在memstore或者blockcache 則需要去磁碟讀文件 但是不做合併的情況下 小文件會比較多 不考慮布隆過濾器 如果有n個文件 每個文件有m數據 則io次數粗略估計是n*log m也就是log m^n,而對於總數據量相同的b樹來說,則只需log n*m ,往往還要-1,因為根節點常駐內存。所以hbase讀相對較慢,原因在文件數量,布隆過濾器可以稍作緩解,也就是判定該數據不在文件內,但是如果數據太多,比特位都滿了,判斷就不太准了。題主可以去搜索類似 b樹與lsm樹的比較 差不多就是我說的意思。


寫是MemStore和HLog append方式所以很快,讀忽略blockcache的話,由於不同的CF存儲在不同的HFile中開銷相對大些。


讀性能的關鍵是你blockcache做的是否夠好


很好……好像現在特別火,我們實驗室的大數據項目就是用hbase


讀性能具體是什麼,如果我的讀請求很大,像taobao那種使用場景,可以搭起負載平衡的環境嗎,如何搭建呢

http://www.idouye.cn 土木工程


不建議生產環境直接訪問,加上redis比較合適。

是否用hbase跟你的取決於你的數據規模和常用的訪問模式。

有時候level db也是不錯的選擇。


推薦閱讀:

從百萬級別數據的分析角度,Mysql,Mongodb,Hbase如何選擇?
怎麼看hadoop的源碼,求大神指教?

TAG:HBase |