Copyright © 2010 Apache Software Foundation, 盛大遊戲-數據倉庫團隊-顏開(譯)css
Revision History | |
---|---|
Revision 0.90.4 | |
配置,數據模型使用入門 |
Abstracthtml
這是 Apache HBase的官方文檔, Hbase是一個分佈式,版本化(versioned),構建在 Apache Hadoop和 Apache ZooKeeper上的列數據庫.java
我(譯者)熟悉Hbase的源代碼,從事Hbase的開發運維工做,若是有什麼地方不清楚,歡迎一塊兒討論。郵箱yankaycom@gmail.comnode
Table of Contentsreact
hbase.regionserver.blockCacheCount
hbase.regionserver.blockCacheFree
hbase.regionserver.blockCacheHitRatio
hbase.regionserver.blockCacheSize
hbase.regionserver.compactionQueueSize
hbase.regionserver.fsReadLatency_avg_time
hbase.regionserver.fsReadLatency_num_ops
hbase.regionserver.fsSyncLatency_avg_time
hbase.regionserver.fsSyncLatency_num_ops
hbase.regionserver.fsWriteLatency_avg_time
hbase.regionserver.fsWriteLatency_num_ops
hbase.regionserver.memstoreSizeMB
hbase.regionserver.regions
hbase.regionserver.requests
hbase.regionserver.storeFileIndexSizeMB
hbase.regionserver.stores
hbase.regionserver.storeFiles
hbase.regionserver.handler.count
hfile.block.cache.size
hbase.regionserver.global.memstore.upperLimit
hbase.regionserver.global.memstore.lowerLimit
hbase.hstore.blockingStoreFiles
hbase.hregion.memstore.block.multiplier
List of Tableslinux
webtable
anchor
contents
這本書是 HBase 的官方指南。 版本爲 0.90.4.能夠在Hbase官網上找到它。也能夠在 javadoc, JIRA 和 wiki 找到更多的資料。git
此書正在編輯中。 能夠向 HBase 官方提供補丁JIRA.github
這個版本系譯者水平限制,沒有理解清楚或不須要翻譯的地方保留英文原文。web
若這是你第一次踏入分佈式計算的精彩世界,你會感到這是一個有趣的年代。分佈式計算是很難的,作一個分佈式系統須要不少軟硬件和網絡的技能。你的集羣能夠會由於各式各樣的錯誤發生故障。好比Hbase自己的Bug,錯誤的配置(包括操做系統),硬件的故障(網卡和磁盤甚至內存) 若是你一直在寫單機程序的話,你須要從新開始學習。這裏就是一個好的起點: 分佈式計算的謬論.算法
Table of Contents
Section 1.2, 「快速開始」會介紹如何運行一個單機版的Hbase.他運行在本地磁盤上。 Section 1.3, 「慢速開始(相對快速開始)」 會介紹如何運行一個分佈式的Hbase。他運行在HDFS上
本指南介紹了在單機安裝Hbase的方法。會引導你經過shell建立一個表,插入一行,而後刪除它,最後中止Hbase。只要10分鐘就能夠完成如下的操做。
選擇一個 Apache 下載鏡像,下載 HBase Releases. 點擊 stable
目錄,而後下載後綴爲 .tar.gz
的文件; 例如 hbase-0.90.4.tar.gz
.
解壓縮,而後進入到那個要解壓的目錄.
$ tar xfz hbase-0.90.4.tar.gz$ cd hbase-0.90.4
如今你已經能夠啓動Hbase了。可是你可能須要先編輯 conf/hbase-site.xml
去配置hbase.rootdir
,來選擇Hbase將數據寫到哪一個目錄 .
hbase.rootdir file:///DIRECTORY/hbase
將 DIRECTORY
替換成你指望寫文件的目錄. 默認 hbase.rootdir
是指向 /tmp/hbase-${user.name}
,也就說你會在重啓後丟失數據(重啓的時候操做系統會清理/tmp
目錄)
如今啓動Hbase:
$ ./bin/start-hbase.shstarting Master, logging to logs/hbase-user-master-example.org.out
如今你運行的是單機模式的Hbaes。因此的服務都運行在一個JVM上,包括Hbase和Zookeeper。Hbase的日誌放在logs
目錄,當你啓動出問題的時候,能夠檢查這個日誌。
你須要確認安裝了Oracle的1.6 版本的java.若是你在命令行鍵入java有反應說明你安裝了Java。若是沒有裝,你須要先安裝,而後編輯conf/hbase-env.sh
,將其中的JAVA_HOME
指向到你Java的安裝目錄。
用shell鏈接你的Hbase
$ ./bin/hbase shellHBase Shell; enter 'help ' for list of supported commands.Type "exit " to leave the HBase ShellVersion: 0.90.0, r1001068, Fri Sep 24 13:55:42 PDT 2010hbase(main):001:0>
輸入 help 而後 能夠看到一列shell命令。這裏的幫助很詳細,要注意的是表名,行和列須要加引號。
建立一個名爲 test
的表,這個表只有一個 column family 爲 cf
。能夠列出全部的表來檢查建立狀況,而後插入些值。
hbase(main):003:0> create 'test', 'cf'0 row(s) in 1.2200 secondshbase(main):003:0> list 'table'test1 row(s) in 0.0550 secondshbase(main):004:0> put 'test', 'row1', 'cf:a', 'value1'0 row(s) in 0.0560 secondshbase(main):005:0> put 'test', 'row2', 'cf:b', 'value2'0 row(s) in 0.0370 secondshbase(main):006:0> put 'test', 'row3', 'cf:c', 'value3'0 row(s) in 0.0450 seconds
以上咱們分別插入了3行。第一個行key爲row1
, 列爲 cf:a
, 值是 value1
。Hbase中的列是由 column family前綴和列的名字組成的,以冒號間隔。例如這一行的列名就是a
.
檢查插入狀況.
Scan這個表,操做以下
hbase(main):007:0> scan 'test'ROW COLUMN+CELLrow1 column=cf:a, timestamp=1288380727188, value=value1row2 column=cf:b, timestamp=1288380738440, value=value2row3 column=cf:c, timestamp=1288380747365, value=value33 row(s) in 0.0590 seconds
Get一行,操做以下
hbase(main):008:0> get 'test', 'row1'COLUMN CELLcf:a timestamp=1288380727188, value=value11 row(s) in 0.0400 seconds
disable 再 drop 這張表,能夠清除你剛剛的操做
hbase(main):012:0> disable 'test'0 row(s) in 1.0930 secondshbase(main):013:0> drop 'test'0 row(s) in 0.0770 seconds
關閉shell
hbase(main):014:0> exit
運行中止腳原本中止HBase.
$ ./bin/stop-hbase.shstopping hbase...............
以上步驟僅僅適用於實驗和測試。接下來你能夠看 Section 1.3, 「慢速開始(相對快速開始)」 ,咱們會介紹不一樣的Hbase運行模式,運行分佈式Hbase中須要的軟件 和如何配置。
Hbase有以下須要,請仔細閱讀本章節以確保全部的須要都被知足。若是需求沒有能知足,就有可能遇到莫名其妙的錯誤甚至丟失數據。
和Hadoop同樣,Hbase須要Oracle版本的Java6.除了那個有問題的u18版本其餘的均可以用,最好用最新的。
該版本的Hbase只能夠運行在Hadoop 0.20.x,不能夠運行於hadoop 0.21.x (0.22.x也不行). HBase運行在沒有持久同步功能的HDFS上會丟失數據。 Hadoop 0.20.2 和 Hadoop 0.20.203.0就沒有這個功能。如今只有 branch-0.20-append 補丁有這個功能[1]. 如今官方的發行版都沒有這個功能,因此你要本身打這個補丁。推薦看 Michael Noll 寫的詳細的說明, Building an Hadoop 0.20.x version for HBase 0.90.2.
你還能夠用 Cloudera's CDH3. CDH 打了這個補丁 (CDH3 betas 就能夠知足; b2, b3, or b4).
由於Hbase創建在Hadoop之上,因此他用到了hadoop.jar,這個Jar在 lib
裏面。這個jar是hbase本身打了branch-0.20-append 補丁的hadoop.jar. Hadoop使用的hadoop.jar和Hbase使用的 必須 一致。因此你須要將 Hbase lib
目錄下的hadoop.jar替換成Hadoop裏面的那個,防止版本衝突。比方說CDH的版本沒有HDFS-724而branch-0.20-append裏面有,這個HDFS-724補丁修改了RPC協議。若是不替換,就會有版本衝突,繼而形成嚴重的出錯,Hadoop會看起來掛了。
你能夠這麼幹。詳細能夠參見這個郵件列表.
HBase運行在Hadoop 0.20.x上,就能夠使用其中的安全特性 -- 只要你用這兩個版本0.20S 和CDH3B3,而後把hadoop.jar替換掉就能夠了.
必須安裝ssh , sshd 也必須運行,這樣Hadoop的腳本才能夠遠程操控其餘的Hadoop和Hbase進程。ssh之間必須都打通,不用密碼均可以登陸,詳細方法能夠Google一下 ("ssh passwordless login").
HBase使用本地 hostname 纔得到IP地址. 正反向的DNS都是能夠的.
若是你的機器有多個接口,Hbase會使用hostname指向的主接口.
若是還不夠,你能夠設置 hbase.regionserver.dns.interface
來指定主接口。固然你的整個集羣的配置文件都必須一致,每一個主機都使用相同的網絡接口
還有一種方法是設置 hbase.regionserver.dns.nameserver
來指定nameserver,不使用系統帶的.
集羣的時鐘要保證基本的一致。稍有不一致是能夠容忍的,可是很大的不一致會形成奇怪的行爲。 運行 NTP 或者其餘什麼東西來同步你的時間.
若是你查詢的時候或者是遇到奇怪的故障,能夠檢查一下系統時間是否正確!
ulimit
和 nproc
HBase是數據庫,會在同一時間使用不少的文件句柄。大多數linux系統使用的默認值1024是不能知足的,會致使FAQ: Why do I see "java.io.IOException...(Too many open files)" in my logs?異常。還可能會發生這樣的異常
2010-04-06 03:04:37,542 INFO org.apache.hadoop.hdfs.DFSClient: Exception increateBlockOutputStream java.io.EOFException 2010-04-06 03:04:37,542 INFO org.apache.hadoop.hdfs.DFSClient: Abandoning block blk_-6935524980745310745_1391901
因此你須要修改你的最大文件句柄限制。能夠設置到10k. 你還須要修改 hbase 用戶的 nproc
,若是太低會形成 OutOfMemoryError
異常。 [2][3].
須要澄清的,這兩個設置是針對操做系統的,不是Hbase自己的。有一個常見的錯誤是Hbase運行的用戶,和設置最大值的用戶不是一個用戶。在Hbase啓動的時候,第一行日誌會如今ulimit信息,因此你最好檢查一下。 [4]
ulimit
若是你使用的是Ubuntu,你能夠這樣設置:
在文件 /etc/security/limits.conf
添加一行,如:
hadoop - nofile 32768
能夠把 hadoop
替換成你運行Hbase和Hadoop的用戶。若是你用兩個用戶,你就須要配兩個。還有配nproc hard 和 soft limits. 如:
hadoop soft/hard nproc 32000
.
在 /etc/pam.d/common-session
加上這一行:
session required pam_limits.so
不然在 /etc/security/limits.conf
上的配置不會生效.
還有註銷再登陸,這些配置才能生效!
dfs.datanode.max.xcievers
一個 Hadoop HDFS Datanode 有一個同時處理文件的上限. 這個參數叫 xcievers
(Hadoop的做者把這個單詞拼錯了). 在你加載以前,先確認下你有沒有配置這個文件conf/hdfs-site.xml
裏面的xceivers
參數,至少要有4096:
dfs.datanode.max.xcievers 4096
對於HDFS修改配置要記得重啓.
若是沒有這一項配置,你可能會遇到奇怪的失敗。你會在Datanode的日誌中看到xcievers exceeded,可是運行起來會報 missing blocks錯誤。例如: 10/12/08 20:10:31 INFO hdfs.DFSClient: Could not obtain block blk_XXXXXXXXXXXXXXXXXXXXXX_YYYYYYYY from any node: java.io.IOException: No live nodes contain current block. Will get new block locations from namenode and retry...
[5]
HBase沒有怎麼在Windows下測試過。因此不推薦在Windows下運行.
若是你實在是想運行,須要安裝Cygwin 還虛擬一個unix環境.詳情請看 Windows 安裝指導 . 或者 搜索郵件列表找找最近的關於windows的注意點
HBase有兩個運行模式: Section 1.3.2.1, 「單機模式」 和 Section 1.3.2.2, 「分佈式模式」. 默認是單機模式,若是要分佈式模式你須要編輯 conf
文件夾中的配置文件.
無論是什麼模式,你都須要編輯 conf/hbase-env.sh
來告知Hbase java的安裝路徑.在這個文件裏你還能夠設置Hbase的運行環境,諸如 heapsize和其餘 JVM有關的選項, 還有Log文件地址,等等. 設置 JAVA_HOME
指向 java安裝的路徑.
這是默認的模式,在 Section 1.2, 「快速開始」 一章中介紹的就是這個模式. 在單機模式中,Hbase使用本地文件系統,而不是HDFS ,因此的服務和zooKeeper都運做在一個JVM中。zookeep監聽一個端口,這樣客戶端就能夠鏈接Hbase了。
分佈式模式分兩種。僞分佈式模式是把進程運行在一臺機器上,但不是一個JVM.而徹底分佈式模式就是把整個服務被分佈在各個節點上了 [6].
分佈式模式須要使用 Hadoop Distributed File System (HDFS).能夠參見 HDFS需求和指導來得到關於安裝HDFS的指導。在操做Hbase以前,你要確認HDFS能夠正常運做。
在咱們安裝以後,你須要確認你的僞分佈式模式或者 徹底分佈式模式的配置是否正確。這兩個模式能夠使用同一個驗證腳本Section 1.3.2.3, 「運行和確認你的安裝」。
僞分佈式模式是一個相對簡單的分佈式模式。這個模式是用來測試的。不能把這個模式用於生產環節,也不能用於測試性能。
你確認HDFS安裝成功以後,就能夠先編輯 conf/hbase-site.xml
。在這個文件你能夠加入本身的配置,這個配置會覆蓋 Section 3.1.1, 「HBase 默認配置」 and Section 1.3.2.2.2.3, 「HDFS客戶端配置」. 運行Hbase須要設置hbase.rootdir
屬性.該屬性是指Hbase在HDFS中使用的目錄的位置。例如,要想 /hbase
目錄,讓namenode 監聽locahost的9000端口,只有一份數據拷貝(HDFS默認是3份拷貝)。能夠在 hbase-site.xml
寫上以下內容
... hbase.rootdir hdfs://localhost:9000/hbase The directory shared by RegionServers. dfs.replication 1 The replication count for HLog & HFile storage. Should not be greater than HDFS datanode count. ...
讓Hbase本身建立 hbase.rootdir
目錄,若是你本身建這個目錄,會有一個warning,Hbase會試圖在裏面進行migration操做,可是缺乏必須的文件。
上面咱們綁定到 localhost
. 也就是說除了本機,其餘機器連不上Hbase。因此你須要設置成別的,才能使用它。
如今能夠跳到 Section 1.3.2.3, 「運行和確認你的安裝」 來運行和確認你的僞分佈式模式安裝了。 [7]
要想運行徹底分佈式模式,你要進行以下配置,先在 hbase-site.xml
, 加一個屬性 hbase.cluster.distributed
設置爲 true
而後把 hbase.rootdir
設置爲HDFS的NameNode的位置。 例如,你的namenode運行在namenode.example.org,端口是9000 你指望的目錄是 /hbase
,使用以下的配置
... hbase.rootdir hdfs://namenode.example.org:9000/hbase The directory shared by RegionServers. hbase.cluster.distributed true The mode the cluster will be in. Possible values are false: standalone and pseudo-distributed setups with managed Zookeeper true: fully-distributed with unmanaged Zookeeper Quorum (see hbase-env.sh) ...
regionservers
徹底分佈式模式的還須要修改conf/regionservers
. 在 Section 1.3.3.1.2, 「regionservers
」 列出了你但願運行的所有 HRegionServer,一行寫一個host (就像Hadoop裏面的 slaves
同樣). 列在這裏的server會隨着集羣的啓動而啓動,集羣的中止而中止.
一個分佈式運行的Hbase依賴一個zookeeper集羣。全部的節點和客戶端都必須可以訪問zookeeper。默認的狀況下Hbase會管理一個zookeep集羣。這個集羣會隨着Hbase的啓動而啓動。固然,你也能夠本身管理一個zookeeper集羣,但須要配置Hbase。你須要修改conf/hbase-env.sh
裏面的HBASE_MANAGES_ZK
來切換。這個值默認是true的,做用是讓Hbase啓動的時候同時也啓動zookeeper.
當Hbase管理zookeeper的時候,你能夠經過修改zoo.cfg
來配置zookeeper,一個更加簡單的方法是在 conf/hbase-site.xml
裏面修改zookeeper的配置。Zookeep的配置是做爲property寫在 hbase-site.xml
裏面的。option的名字是 hbase.zookeeper.property
. 打個比方, clientPort
配置在xml裏面的名字是 hbase.zookeeper.property.clientPort
. 全部的默認值都是Hbase決定的,包括zookeeper, 參見 Section 3.1.1, 「HBase 默認配置」. 能夠查找 hbase.zookeeper.property
前綴,找到關於zookeeper的配置。 [8]
對於zookeepr的配置,你至少要在 hbase-site.xml
中列出zookeepr的ensemble servers,具體的字段是 hbase.zookeeper.quorum
. 該這個字段的默認值是 localhost
,這個值對於分佈式應用顯然是不能夠的. (遠程鏈接沒法使用).
你運行一個zookeeper也是能夠的,可是在生產環境中,你最好部署3,5,7個節點。部署的越多,可靠性就越高,固然只能部署奇數個,偶數個是不能夠的。你須要給每一個zookeeper 1G左右的內存,若是可能的話,最好有獨立的磁盤。 (獨立磁盤能夠確保zookeeper是高性能的。).若是你的集羣負載很重,不要把Zookeeper和RegionServer運行在同一臺機器上面。就像DataNodes 和 TaskTrackers同樣
打個比方,Hbase管理着的ZooKeeper集羣在節點 rs{1,2,3,4,5}.example.com, 監聽2222 端口(默認是2181),並確保conf/hbase-env.sh
文件中 HBASE_MANAGE_ZK
的值是 true
,再編輯 conf/hbase-site.xml
設置 hbase.zookeeper.property.clientPort
和 hbase.zookeeper.quorum
。你還能夠設置 hbase.zookeeper.property.dataDir
屬性來把ZooKeeper保存數據的目錄地址改掉。默認值是 /tmp
,這裏在重啓的時候會被操做系統刪掉,能夠把它修改到 /user/local/zookeeper
.
... hbase.zookeeper.property.clientPort 2222 Property from ZooKeeper's config zoo.cfg. The port at which the clients will connect. hbase.zookeeper.quorum rs1.example.com,rs2.example.com,rs3.example.com,rs4.example.com,rs5.example.com Comma separated list of servers in the ZooKeeper Quorum. For example, "host1.mydomain.com,host2.mydomain.com,host3.mydomain.com". By default this is set to localhost for local and pseudo-distributed modes of operation. For a fully-distributed setup, this should be set to a full list of ZooKeeper quorum servers. If HBASE_MANAGES_ZK is set in hbase-env.sh this is the list of servers which we will start/stop ZooKeeper on. hbase.zookeeper.property.dataDir /usr/local/zookeeper Property from ZooKeeper's config zoo.cfg. The directory where the snapshot is stored. ...
讓Hbase使用一個現有的不被Hbase託管的Zookeep集羣,須要設置 conf/hbase-env.sh
文件中的HBASE_MANAGES_ZK
屬性爲 false
... # Tell HBase whether it should manage it's own instance of Zookeeper or not. export HBASE_MANAGES_ZK=false
接下來,指明Zookeeper的host和端口。能夠在 hbase-site.xml
中設置, 也能夠在Hbase的CLASSPATH
下面加一個zoo.cfg
配置文件。 HBase 會優先加載 zoo.cfg
裏面的配置,把hbase-site.xml
裏面的覆蓋掉.
當Hbase託管ZooKeeper的時候,Zookeeper集羣的啓動是Hbase啓動腳本的一部分。但如今,你須要本身去運行。你能夠這樣作
${HBASE_HOME}/bin/hbase-daemons.sh {start,stop} zookeeper
你能夠用這條命令啓動ZooKeeper而不啓動Hbase. HBASE_MANAGES_ZK
的值是 false
, 若是你想在Hbase重啓的時候不重啓ZooKeeper,你能夠這樣作
對於獨立Zoopkeeper的問題,你能夠在 Zookeeper啓動獲得幫助.
若是你但願Hadoop集羣上作HDFS 客戶端配置 ,例如你的HDFS客戶端的配置和服務端的不同。按照以下的方法配置,HBase就能看到你的配置信息:
在hbase-env.sh
裏將HBASE_CLASSPATH
環境變量加上HADOOP_CONF_DIR
。
在${HBASE_HOME}/conf
下面加一個 hdfs-site.xml
(或者 hadoop-site.xml
) ,最好是軟鏈接
若是你的HDFS客戶端的配置很少的話,你能夠把這些加到 hbase-site.xml
上面.
例如HDFS的配置 dfs.replication
.你但願複製5份,而不是默認的3份。若是你不照上面的作的話,Hbase只會複製3份。
首先確認你的HDFS是運行着的。你能夠運行HADOOP_HOME
中的 bin/start-hdfs.sh
來啓動HDFS.你能夠經過put命令來測試放一個文件,而後有get命令來讀這個文件。一般狀況下Hbase是不會運行mapreduce的。因此比不須要檢查這些。
若是你本身管理ZooKeeper集羣,你須要確認它是運行着的。若是是Hbase託管,ZoopKeeper會隨Hbase啓動。
用以下命令啓動Hbase:
bin/start-hbase.sh這個腳本在
HBASE_HOME
目錄裏面。
你如今已經啓動Hbase了。Hbase把log記在 logs
子目錄裏面. 當Hbase啓動出問題的時候,能夠看看Log.
Hbase也有一個界面,上面會列出重要的屬性。默認是在Master的60010端口上H (HBase RegionServers 會默認綁定 60020端口,在端口60030上有一個展現信息的界面 ).若是Master運行在 master.example.org
,端口是默認的話,你能夠用瀏覽器在 http://master.example.org:60010
看到主界面. .
一旦Hbase啓動,參見Section 1.2.3, 「Shell 練習」能夠看到如何建表,插入數據,scan你的表,還有disable這個表,最後把它刪掉。
能夠在Hbase Shell中止Hbase
$ ./bin/stop-hbase.shstopping hbase...............
中止操做須要一些時間,你的集羣越大,停的時間可能會越長。若是你正在運行一個分佈式的操做,要確認在Hbase完全中止以前,Hadoop不能停.
這裏是一個10節點的Hbase的簡單示例,這裏的配置都是基本的,節點名爲 example0
, example1
... 一直到 example9
. HBase Master 和 HDFS namenode 運做在同一個節點 example0
上. RegionServers 運行在節點 example1
-example9
. 一個 3-節點 ZooKeeper 集羣運行在example1
, example2
, 和 example3
,端口保持默認. ZooKeeper 的數據保存在目錄 /export/zookeeper
. 下面咱們展現主要的配置文件-- hbase-site.xml
, regionservers
, 和 hbase-env.sh
-- 這些文件能夠在 conf
目錄找到.
hbase-site.xml
hbase.zookeeper.quorum example1,example2,example3 The directory shared by RegionServers. hbase.zookeeper.property.dataDir /export/zookeeper Property from ZooKeeper's config zoo.cfg. The directory where the snapshot is stored. hbase.rootdir hdfs://example0:9000/hbase The directory shared by RegionServers. hbase.cluster.distributed true The mode the cluster will be in. Possible values are false: standalone and pseudo-distributed setups with managed Zookeeper true: fully-distributed with unmanaged Zookeeper Quorum (see hbase-env.sh)
regionservers
這個文件把RegionServer的節點列了下來。在這個例子裏面咱們讓全部的節點都運行RegionServer,除了第一個節點 example1
,它要運行 HBase Master 和 HDFS namenode
example1 example3 example4 example5 example6 example7 example8 example9
hbase-env.sh
下面咱們用diff 命令來展現 hbase-env.sh
文件相比默認變化的部分. 咱們把Hbase的堆內存設置爲4G而不是默認的1G.
$ git diff hbase-env.shdiff --git a/conf/hbase-env.sh b/conf/hbase-env.shindex e70ebc6..96f8c27 100644--- a/conf/hbase-env.sh+++ b/conf/hbase-env.sh@@ -31,7 +31,7 @@ export JAVA_HOME=/usr/lib//jvm/java-6-sun/ # export HBASE_CLASSPATH= # The maximum amount of heap to use, in MB. Default is 1000.-# export HBASE_HEAPSIZE=1000+export HBASE_HEAPSIZE=4096 # Extra Java runtime options. # Below are what we set by default. May only work with SUN JVM.
你能夠使用 rsync 來同步 conf
文件夾到你的整個集羣.
[1] See CHANGES.txt in branch-0.20-append to see list of patches involved adding append on the Hadoop 0.20 branch.
[2] See Jack Levin's major hdfs issues note up on the user list.
[3] 這樣的需求對於數據庫應用來講是很常見的,例如Oracle。 Setting Shell Limits for the Oracle User in Short Guide to install Oracle 10 on Linux.
[4] A useful read setting config on you hadoop cluster is Aaron Kimballs' Configuration Parameters: What can you just ignore?
[5] 參見 Hadoop HDFS: Deceived by Xciever for an informative rant on xceivering.
[6] 這兩個命名法來自於Hadoop.
[7] See Pseudo-distributed mode extras for notes on how to start extra Masters and RegionServers when running pseudo-distributed.
[8] For the full list of ZooKeeper configurations, see ZooKeeper's zoo.cfg
. HBase does not ship with a zoo.cfg
so you will need to browse the conf
directory in an appropriate ZooKeeper download.
Table of Contents
參見 Section 1.3.1, 「須要的軟件」, 須要特別注意有關Hadoop 版本的信息.
0.90.x 版本的HBase能夠在 HBase 0.20.x 或者 HBase 0.89.x的數據上啓動. 不須要轉換數據文件, HBase 0.89.x 和 0.90.x 的region目錄名是不同的 -- 老版本用md5 hash 而不是jenkins hash 來命名region-- 這就意味着,一旦啓動,不再能回退到 HBase 0.20.x.
在升級的時候,必定要將hbase-default.xml
從你的 conf
目錄刪掉。 0.20.x 版本的配置對於 0.90.x HBase不是最佳的. hbase-default.xml
如今已經被打包在 HBase jar 裏面了. 若是你想看看這個文件內容,你能夠在src目錄下 src/main/resources/hbase-default.xml
或者在 Section 3.1.1, 「HBase 默認配置」看到.
最後,若是從0.20.x升級,須要在shell裏檢查 .META.
schema . 過去,咱們推薦用戶使用16KB的 MEMSTORE_FLUSHSIZE
. 在shell中運行 hbase> scan '-ROOT-'
. 會顯示當前的.META.
schema. 檢查 MEMSTORE_FLUSHSIZE
的大小. 看看是否是 16KB (16384)? 若是是的話,你須要修改它(默認的值是 64MB (67108864)) 運行腳本 bin/set_meta_memstore_size.rb
. 這個腳本會修改 .META.
schema. 若是不運行的話,集羣會比較慢[9] .
Table of Contents
Hbase的配置系統和Hadoop同樣。在conf/hbase-env.sh
配置系統的部署信息和環境變量。 -- 這個配置會被啓動shell使用 -- 而後在XML文件裏配置信息,覆蓋默認的配置。告知Hbase使用什麼目錄地址,ZooKeeper的位置等等信息。 [10] .
當你使用分佈式模式的時間,當你編輯完一個文件以後,記得要把這個文件複製到整個集羣的conf
目錄下。Hbase不會幫你作這些,你得用 rsync.
hbase-site.xml
和 hbase-default.xml
正如Hadoop放置HDFS的配置文件hdfs-site.xml
,Hbase的配置文件是 conf/hbase-site.xml
. 你能夠在 Section 3.1.1, 「HBase 默認配置」找到配置的屬性列表。你也能夠看有代碼裏面的hbase-default.xml
文件,他在src/main/resources
目錄下。
不是全部的配置都在 hbase-default.xml
出現.只要改了代碼,配置就有可能改變,因此惟一瞭解這些被改過的配置的辦法是讀源代碼自己。
要注意的是,要重啓集羣才能是配置生效。
該文檔是用hbase默認配置文件生成的,文件源是hbase-default.xml
(因翻譯須要,被譯者修改爲中文註釋).
hbase.rootdir
這個目錄是region server的共享目錄,用來持久化Hbase。URL須要是'徹底正確'的,還要包含文件系統的scheme。例如,要表示hdfs中的'/hbase'目錄,namenode 運行在namenode.example.org的9090端口。則須要設置爲hdfs://namenode.example.org:9000/hbase。默認狀況下Hbase是寫到/tmp的。不改這個配置,數據會在重啓的時候丟失。
默認: file:///tmp/hbase-${user.name}/hbase
hbase.master.port
Hbase的Master的端口.
默認: 60000
hbase.cluster.distributed
Hbase的運行模式。false是單機模式,true是分佈式模式。若爲false,Hbase和Zookeeper會運行在同一個JVM裏面。
默認: false
hbase.tmp.dir
本地文件系統的臨時文件夾。能夠修改到一個更爲持久的目錄上。(/tmp會在重啓時清楚)
默認: /tmp/hbase-${user.name}
hbase.master.info.port
HBase Master web 界面端口. 設置爲-1 意味着你不想讓他運行。
默認: 60010
hbase.master.info.bindAddress
HBase Master web 界面綁定的端口
默認: 0.0.0.0
hbase.client.write.buffer
HTable客戶端的寫緩衝的默認大小。這個值越大,須要消耗的內存越大。由於緩衝在客戶端和服務端都有實例,因此須要消耗客戶端和服務端兩個地方的內存。獲得的好處是,能夠減小RPC的次數。能夠這樣估算服務器端被佔用的內存: hbase.client.write.buffer * hbase.regionserver.handler.count
默認: 2097152
hbase.regionserver.port
HBase RegionServer綁定的端口
默認: 60020
hbase.regionserver.info.port
HBase RegionServer web 界面綁定的端口 設置爲 -1 意味這你不想與運行 RegionServer 界面.
默認: 60030
hbase.regionserver.info.port.auto
Master或RegionServer是否要動態搜一個能夠用的端口來綁定界面。當hbase.regionserver.info.port已經被佔用的時候,能夠搜一個空閒的端口綁定。這個功能在測試的時候頗有用。默認關閉。
默認: false
hbase.regionserver.info.bindAddress
HBase RegionServer web 界面的IP地址
默認: 0.0.0.0
hbase.regionserver.class
RegionServer 使用的接口。客戶端打開代理來鏈接region server的時候會使用到。
默認: org.apache.hadoop.hbase.ipc.HRegionInterface
hbase.client.pause
一般的客戶端暫停時間。最多的用法是客戶端在重試前的等待時間。好比失敗的get操做和region查詢操做等都極可能用到。
默認: 1000
hbase.client.retries.number
最大重試次數。例如 region查詢,Get操做,Update操做等等均可能發生錯誤,須要重試。這是最大重試錯誤的值。
默認: 10
hbase.client.scanner.caching
當調用Scanner的next方法,而值又不在緩存裏的時候,從服務端一次獲取的行數。越大的值意味着Scanner會快一些,可是會佔用更多的內存。當緩衝被佔滿的時候,next方法調用會愈來愈慢。慢到必定程度,可能會致使超時。例如超過了hbase.regionserver.lease.period。
默認: 1
hbase.client.keyvalue.maxsize
一個KeyValue實例的最大size.這個是用來設置存儲文件中的單個entry的大小上界。由於一個KeyValue是不能分割的,因此能夠避免由於數據過大致使region不可分割。明智的作法是把它設爲能夠被最大region size整除的數。若是設置爲0或者更小,就會禁用這個檢查。默認10MB。
默認: 10485760
hbase.regionserver.lease.period
客戶端租用HRegion server 期限,即超時閥值。單位是毫秒。默認狀況下,客戶端必須在這個時間內發一條信息,不然視爲死掉。
默認: 60000
hbase.regionserver.handler.count
RegionServers受理的RPC Server實例數量。對於Master來講,這個屬性是Master受理的handler數量
默認: 10
hbase.regionserver.msginterval
RegionServer 發消息給 Master 時間間隔,單位是毫秒
默認: 3000
hbase.regionserver.optionallogflushinterval
將Hlog同步到HDFS的間隔。若是Hlog沒有積累到必定的數量,到了時間,也會觸發同步。默認是1秒,單位毫秒。
默認: 1000
hbase.regionserver.regionSplitLimit
region的數量到了這個值後就不會在分裂了。這不是一個region數量的硬性限制。可是起到了必定指導性的做用,到了這個值就該中止分裂了。默認是MAX_INT.就是說不阻止分裂。
默認: 2147483647
hbase.regionserver.logroll.period
提交commit log的間隔,無論有沒有寫足夠的值。
默認: 3600000
hbase.regionserver.hlog.reader.impl
HLog file reader 的實現.
默認: org.apache.hadoop.hbase.regionserver.wal.SequenceFileLogReader
hbase.regionserver.hlog.writer.impl
HLog file writer 的實現.
默認: org.apache.hadoop.hbase.regionserver.wal.SequenceFileLogWriter
hbase.regionserver.thread.splitcompactcheckfrequency
region server 多久執行一次split/compaction 檢查.
默認: 20000
hbase.regionserver.nbreservationblocks
儲備的內存block的數量(譯者注:就像石油儲備同樣)。當發生out of memory 異常的時候,咱們能夠用這些內存在RegionServer中止以前作清理操做。
默認: 4
hbase.zookeeper.dns.interface
當使用DNS的時候,Zookeeper用來上報的IP地址的網絡接口名字。
默認: default
hbase.zookeeper.dns.nameserver
當使用DNS的時候,Zookeepr使用的DNS的域名或者IP 地址,Zookeeper用它來肯定和master用來進行通信的域名.
默認: default
hbase.regionserver.dns.interface
當使用DNS的時候,RegionServer用來上報的IP地址的網絡接口名字。
默認: default
hbase.regionserver.dns.nameserver
當使用DNS的時候,RegionServer使用的DNS的域名或者IP 地址,RegionServer用它來肯定和master用來進行通信的域名.
默認: default
hbase.master.dns.interface
當使用DNS的時候,Master用來上報的IP地址的網絡接口名字。
默認: default
hbase.master.dns.nameserver
當使用DNS的時候,RegionServer使用的DNS的域名或者IP 地址,Master用它來肯定用來進行通信的域名.
默認: default
hbase.balancer.period
Master執行region balancer的間隔。
默認: 300000
hbase.regions.slop
當任一regionserver有average + (average * slop)個region是會執行Rebalance
默認: 0
hbase.master.logcleaner.ttl
Hlog存在於.oldlogdir 文件夾的最長時間, 超過了就會被 Master 的線程清理掉.
默認: 600000
hbase.master.logcleaner.plugins
LogsCleaner服務會執行的一組LogCleanerDelegat。值用逗號間隔的文本表示。這些WAL/HLog cleaners會按順序調用。能夠把先調用的放在前面。你能夠實現本身的LogCleanerDelegat,加到Classpath下,而後在這裏寫下類的全稱。通常都是加在默認值的前面。
默認: org.apache.hadoop.hbase.master.TimeToLiveLogCleaner
hbase.regionserver.global.memstore.upperLimit
單個region server的所有memtores的最大值。超過這個值,一個新的update操做會被掛起,強制執行flush操做。
默認: 0.4
hbase.regionserver.global.memstore.lowerLimit
當強制執行flush操做的時候,當低於這個值的時候,flush會中止。默認是堆大小的 35% . 若是這個值和 hbase.regionserver.global.memstore.upperLimit 相同就意味着當update操做由於內存限制被掛起時,會盡可能少的執行flush(譯者注:一旦執行flush,值就會比下限要低,再也不執行)
默認: 0.35
hbase.server.thread.wakefrequency
service工做的sleep間隔,單位毫秒。 能夠做爲service線程的sleep間隔,好比log roller.
默認: 10000
hbase.hregion.memstore.flush.size
當memstore的大小超過這個值的時候,會flush到磁盤。這個值被一個線程每隔hbase.server.thread.wakefrequency檢查一下。
默認: 67108864
hbase.hregion.preclose.flush.size
當一個region中的memstore的大小大於這個值的時候,咱們又觸發了close.會先運行「pre-flush」操做,清理這個須要關閉的memstore,而後將這個region下線。當一個region下線了,咱們沒法再進行任何寫操做。若是一個memstore很大的時候,flush操做會消耗不少時間。"pre-flush"操做意味着在region下線以前,會先把memstore清空。這樣在最終執行close操做的時候,flush操做會很快。
默認: 5242880
hbase.hregion.memstore.block.multiplier
若是memstore有hbase.hregion.memstore.block.multiplier倍數的hbase.hregion.flush.size的大小,就會阻塞update操做。這是爲了預防在update高峯期會致使的失控。若是不設上界,flush的時候會花很長的時間來合併或者分割,最壞的狀況就是引起out of memory異常。(譯者注:內存操做的速度和磁盤不匹配,須要等一等。原文彷佛有誤)
默認: 2
hbase.hregion.memstore.mslab.enabled
體驗特性:啓用memStore分配本地緩衝區。這個特性是爲了防止在大量寫負載的時候堆的碎片過多。這能夠減小GC操做的頻率。(GC有可能會Stop the world)(譯者注:實現的原理至關於預分配內存,而不是每個值都要從堆裏分配)
默認: false
hbase.hregion.max.filesize
最大HStoreFile大小。若某個Column families的HStoreFile增加達到這個值,這個Hegion會被切割成兩個。 Default: 256M.
默認: 268435456
hbase.hstore.compactionThreshold
當一個HStore含有多於這個值的HStoreFiles(每個memstore flush產生一個HStoreFile)的時候,會執行一個合併操做,把這HStoreFiles寫成一個。這個值越大,須要合併的時間就越長。
默認: 3
hbase.hstore.blockingStoreFiles
當一個HStore含有多於這個值的HStoreFiles(每個memstore flush產生一個HStoreFile)的時候,會執行一個合併操做,update會阻塞直到合併完成,直到超過了hbase.hstore.blockingWaitTime的值
默認: 7
hbase.hstore.blockingWaitTime
hbase.hstore.blockingStoreFiles所限制的StoreFile數量會致使update阻塞,這個時間是來限制阻塞時間的。當超過了這個時間,HRegion會中止阻塞update操做,不過合併還有沒有完成。默認爲90s.
默認: 90000
hbase.hstore.compaction.max
每一個「小」合併的HStoreFiles最大數量。
默認: 10
hbase.hregion.majorcompaction
一個Region中的全部HStoreFile的major compactions的時間間隔。默認是1天。 設置爲0就是禁用這個功能。
默認: 86400000
hbase.mapreduce.hfileoutputformat.blocksize
MapReduce中HFileOutputFormat能夠寫 storefiles/hfiles. 這個值是hfile的blocksize的最小值。一般在Hbase寫Hfile的時候,bloocksize是由table schema(HColumnDescriptor)決定的,可是在mapreduce寫的時候,咱們沒法獲取schema中blocksize。這個值越小,你的索引就越大,你隨機訪問須要獲取的數據就越小。若是你的cell都很小,並且你須要更快的隨機訪問,能夠把這個值調低。
默認: 65536
hfile.block.cache.size
分配給HFile/StoreFile的block cache佔最大堆(-Xmx setting)的比例。默認是20%,設置爲0就是不分配。
默認: 0.2
hbase.hash.type
哈希函數使用的哈希算法。能夠選擇兩個值:: murmur (MurmurHash) 和 jenkins (JenkinsHash). 這個哈希是給 bloom filters用的.
默認: murmur
hbase.master.keytab.file
HMaster server驗證登陸使用的kerberos keytab 文件路徑。(譯者注:Hbase使用Kerberos實現安全)
默認:
hbase.master.kerberos.principal
例如. "hbase/_HOST@EXAMPLE.COM". HMaster運行須要使用 kerberos principal name. principal name 能夠在: user/hostname@DOMAIN 中獲取. 若是 "_HOST" 被用作hostname portion,須要使用實際運行的hostname來替代它。
默認:
hbase.regionserver.keytab.file
HRegionServer驗證登陸使用的kerberos keytab 文件路徑。
默認:
hbase.regionserver.kerberos.principal
例如. "hbase/_HOST@EXAMPLE.COM". HRegionServer運行須要使用 kerberos principal name. principal name 能夠在: user/hostname@DOMAIN 中獲取. 若是 "_HOST" 被用作hostname portion,須要使用實際運行的hostname來替代它。在這個文件中必需要有一個entry來描述 hbase.regionserver.keytab.file
默認:
zookeeper.session.timeout
ZooKeeper 會話超時.Hbase把這個值傳遞改zk集羣,向他推薦一個會話的最大超時時間。詳見http://hadoop.apache.org/zookeeper/docs/current/zookeeperProgrammers.html#ch_zkSessions "The client sends a requested timeout, the server responds with the timeout that it can give the client. "。 單位是毫秒
默認: 180000
zookeeper.znode.parent
ZooKeeper中的Hbase的根ZNode。全部的Hbase的ZooKeeper會用這個目錄配置相對路徑。默認狀況下,全部的Hbase的ZooKeeper文件路徑是用相對路徑,因此他們會都去這個目錄下面。
默認: /hbase
zookeeper.znode.rootserver
ZNode 保存的 根region的路徑. 這個值是由Master來寫,client和regionserver 來讀的。若是設爲一個相對地址,父目錄就是 ${zookeeper.znode.parent}.默認情形下,意味着根region的路徑存儲在/hbase/root-region-server.
默認: root-region-server
hbase.zookeeper.quorum
Zookeeper集羣的地址列表,用逗號分割。例如:"host1.mydomain.com,host2.mydomain.com,host3.mydomain.com".默認是localhost,是給僞分佈式用的。要修改才能在徹底分佈式的狀況下使用。若是在hbase-env.sh設置了HBASE_MANAGES_ZK,這些ZooKeeper節點就會和Hbase一塊兒啓動。
默認: localhost
hbase.zookeeper.peerport
ZooKeeper節點使用的端口。詳細參見:http://hadoop.apache.org/zookeeper/docs/r3.1.1/zookeeperStarted.html#sc_RunningReplicatedZooKeeper
默認: 2888
hbase.zookeeper.leaderport
ZooKeeper用來選擇Leader的端口,詳細參見:http://hadoop.apache.org/zookeeper/docs/r3.1.1/zookeeperStarted.html#sc_RunningReplicatedZooKeeper
默認: 3888
hbase.zookeeper.property.initLimit
ZooKeeper的zoo.conf中的配置。 初始化synchronization階段的ticks數量限制
默認: 10
hbase.zookeeper.property.syncLimit
ZooKeeper的zoo.conf中的配置。 發送一個請求到得到認可之間的ticks的數量限制
默認: 5
hbase.zookeeper.property.dataDir
ZooKeeper的zoo.conf中的配置。 快照的存儲位置
默認: ${hbase.tmp.dir}/zookeeper
hbase.zookeeper.property.clientPort
ZooKeeper的zoo.conf中的配置。 客戶端鏈接的端口
默認: 2181
hbase.zookeeper.property.maxClientCnxns
ZooKeeper的zoo.conf中的配置。 ZooKeeper集羣中的單個節點接受的單個Client(以IP區分)的請求的併發數。這個值能夠調高一點,防止在單機和僞分佈式模式中出問題。
默認: 2000
hbase.rest.port
HBase REST server的端口
默認: 8080
hbase.rest.readonly
定義REST server的運行模式。能夠設置成以下的值: false: 全部的HTTP請求都是被容許的 - GET/PUT/POST/DELETE. true:只有GET請求是被容許的
默認: false
hbase-env.sh
在這個文件裏面設置HBase環境變量。好比能夠配置JVM啓動的堆大小或者GC的參數。你還可在這裏配置Hbase的參數,如Log位置,niceness(譯者注:優先級),ssh參數還有pid文件的位置等等。打開文件conf/hbase-env.sh
細讀其中的內容。每一個選項都是有詳盡的註釋的。你能夠在此添加本身的環境變量。
這個文件的改動系統Hbase重啓才能生效。
log4j.properties
編輯這個文件能夠改變Hbase的日誌的級別,輪滾策略等等。
這個文件的改動系統Hbase重啓才能生效。 日誌級別的更改會影響到HBase UI
下面咱們會列舉重要 的配置. 這個章節講述必須的配置和那些值得一看的配置。(譯者注:淘寶的博客也有本章節的內容,HBase性能調優,很詳盡)。
參見 Section 1.3.1, 「須要的軟件」. 這裏列舉了運行Hbase至少兩個必須的配置: i.e. Section 1.3.1.6, 「 ulimit
和 nproc
」 和 Section 1.3.1.7, 「dfs.datanode.max.xcievers
」.
zookeeper.session.timeout
這個默認值是3分鐘。這意味着一旦一個server宕掉了,Master至少須要3分鐘才能察覺到宕機,開始恢復。你可能但願將這個超時調短,這樣Master就能更快的察覺到了。在你調這個值以前,你須要確認你的JVM的GC參數,不然一個長時間的GC操做就可能致使超時。(當一個RegionServer在運行一個長時間的GC的時候,你可能想要重啓並恢復它).
要想改變這個配置,能夠編輯 hbase-site.xml
, 將配置部署到所有集羣,而後重啓。
咱們之因此把這個值調的很高,是由於咱們不想一天到晚在論壇裏回答新手的問題。「爲何我在執行一個大規模數據導入的時候Region Server死掉啦」,一般這樣的問題是由於長時間的GC操做引發的,他們的JVM沒有調優。咱們是這樣想的,若是一我的對Hbase不很熟悉,不能指望他知道全部,打擊他的自信心。等到他逐漸熟悉了,他就能夠本身調這個參數了。
hbase.regionserver.handler.count
這個設置決定了處理用戶請求的線程數量。默認是10,這個值設的比較小,主要是爲了預防用戶用一個比較大的寫緩衝,而後還有不少客戶端併發,這樣region servers會垮掉。有經驗的作法是,當請求內容很大(上MB,如大puts, 使用緩存的scans)的時候,把這個值放低。請求內容較小的時候(gets, 小puts, ICVs, deletes),把這個值放大。
當客戶端的請求內容很小的時候,把這個值設置的和最大客戶端數量同樣是很安全的。一個典型的例子就是一個給網站服務的集羣,put操做通常不會緩衝,絕大多數的操做是get操做。
把這個值放大的危險之處在於,把全部的Put操做緩衝意味着對內存有很大的壓力,甚至會致使OutOfMemory.一個運行在內存不足的機器的RegionServer會頻繁的觸發GC操做,漸漸就能感覺到停頓。(由於全部請求內容所佔用的內存無論GC執行幾遍也是不能回收的)。一段時間後,集羣也會受到影響,由於全部的指向這個region的請求都會變慢。這樣就會拖累集羣,加重了這個問題。
Hbase有一個合理的保守的配置,這樣能夠運做在全部的機器上。若是你有臺大內存的集羣-Hbase有8G或者更大的heap,接下來的配置可能會幫助你 TODO.(譯者注:原文到此爲止,汗)
你能夠考慮使用Lzo壓縮,這個能夠無縫集成,而且在大多數狀況下能夠提供性能。
Hbase是Apache的協議,而LZO是GPL的協議。Hbase不能自帶LZO,所以LZO須要在安裝Hbase以前安裝。參見 使用 LZO 壓縮介紹瞭如何在Hbase中使用LZO
一個常見的問題是,用戶在一開始使用LZO的時候會很好,可是數月過去,管理員在給集羣添加集羣的時候,他們忘記了LZO的事情。在0.90.0版本以後,咱們會運行失敗,但也有可能不。 請你要閱讀這一段[11].
還要在本書的尾部參見 Appendix B, HBase中的壓縮 .
更大的Region能夠使你集羣上的Region的總數量較少。 通常來言,更少的Region能夠使你的集羣運行更加流暢。(你能夠本身隨時手工將大Region切割,這樣單個熱點Region就會被分佈在集羣的更多節點上)。默認狀況下單個Region是256MB.你能夠設置爲1G。有些人使用更大的,4G甚至更多。能夠調整hbase-site.xml
中的 hbase.hregion.max.filesize
屬性.
除了讓Hbase自動切割你的Region,你也能夠手動切割。 [12] 隨着數據量的增大,splite會被持續執行。若是你須要知道你如今有幾個region,好比長時間的debug或者作調優,你須要手動切割。經過跟蹤日誌來了解region級的問題是很難的,由於他在不停的切割和重命名。data offlineing bug和未知量的region會讓你沒有辦法。若是一個 HLog
或者 StoreFile
因爲一個奇怪的bug,Hbase沒有執行它。等到一天以後,你才發現這個問題,你能夠確保如今的regions和那個時候的同樣,這樣你就能夠restore或者replay這些數據。你還能夠調優你的合併算法。若是數據是均勻的,隨着數據增加,很容易致使split / compaction瘋狂的運行。由於全部的region都是差很少大的。用手的切割,你就能夠交錯執行定時的合併和切割操做,下降IO負載。
爲何我關閉自動split呢?由於自動的splite是配置文件中的 hbase.hregion.max.filesize
決定的. 你把它設置成ILong.MAX_VALUE
是不推薦的作法,要是你忘記了手工切割怎麼辦.推薦的作法是設置成100GB,一旦到達這樣的值,至少須要一個小時執行 major compactions。
那什麼是最佳的在pre-splite regions的數量呢。這個決定於你的應用程序了。你能夠先從低的開始,好比每一個server10個pre-splite regions.而後花時間觀察數據增加。有太少的region至少比出錯好,你能夠以後再rolling split.一個更復雜的答案是這個值是取決於你的region中的最大的storefile。隨着數據的增大,這個也會跟着增大。 你能夠當這個文件足夠大的時候,用一個定時的操做使用Store
的合併選擇算法(compact selection algorithm)來僅合併這一個HStore。若是你不這樣作,這個算法會啓動一個 major compactions,不少region會受到影響,你的集羣會瘋狂的運行。須要注意的是,這樣的瘋狂合併操做是數據增加形成的,而不是手動分割操做決定的。
若是你 pre-split 致使 regions 很小,你能夠經過配置HConstants.MAJOR_COMPACTION_PERIOD
把你的major compaction參數調大
若是你的數據變得太大,能夠使用org.apache.hadoop.hbase.util.RegionSplitter
腳原本執行鍼對所有集羣的一個網絡IO安全的rolling split操做。
由於Hbase的Master有可能轉移,全部客戶端須要訪問ZooKeeper來得到如今的位置。ZooKeeper會保存這些值。所以客戶端必須知道Zookeeper集羣的地址,不然作不了任何事情。一般這個地址存在 hbase-site.xml
裏面,客戶端能夠從CLASSPATH
取出這個文件.
若是你是使用一個IDE來運行Hbase客戶端,你須要將conf/
放入你的 classpath,這樣 hbase-site.xml
就能夠找到了,(或者把hbase-site.xml放到 src/test/resources
,這樣測試的時候能夠使用).
Hbase客戶端最小化的依賴是 hbase, hadoop, log4j, commons-logging, commons-lang, 和 ZooKeeper ,這些jars 須要能在 CLASSPATH
中找到。
下面是一個基本的客戶端 hbase-site.xml
例子:
hbase.zookeeper.quorum example1,example2,example3 The directory shared by region servers.
hbase-site.xml
的內容的Java客戶端使用的配置信息是被映射在一個HBaseConfiguration 實例中. HBaseConfiguration有一個工廠方法, HBaseConfiguration.create();
,運行這個方法的時候,他會去CLASSPATH
,下找hbase-site.xml
,讀他發現的第一個配置文件的內容。 (這個方法還會去找hbase-default.xml
; hbase.X.X.X.jar
裏面也會有一個an hbase-default.xml). 不使用任何hbase-site.xml
文件直接經過Java代碼注入配置信息也是能夠的。例如,你能夠用編程的方式設置ZooKeeper信息,只要這樣作:
Configuration config = HBaseConfiguration.create();config.set("hbase.zookeeper.quorum", "localhost"); // Here we are running zookeeper locally
若是有多ZooKeeper實例,你能夠使用逗號列表。(就像在hbase-site.xml
文件中作得同樣). 這個 Configuration
實例會被傳遞到 HTable, 之類的實例裏面去.
[10] Be careful editing XML. Make sure you close all elements.Run your file through xmllint or similarto ensure well-formedness of your document after an edit session.
[11] 參見 Section B.2, 「 hbase.regionserver.codecs
」 能夠看到關於LZO安裝的具體信息,幫助你放在安裝失敗。
[12] What follows is taken from the javadoc at the head of the org.apache.hadoop.hbase.util.RegionSplitter
tool added to HBase post-0.90.0 release.
Table of Contents
Hbase Shell is 在(J)Ruby的IRB的基礎上加上了HBase的命令。任何你能夠在IRB裏作的事情均可在在Hbase Shell中作。
你能夠這樣來運行HBase Shell:
$ ./bin/hbase shell
輸入 help 就會返回Shell的命令列表和選項。能夠看看在Help文檔尾部的關於如何輸入變量和選項。尤爲要注意的是表名,行,列名必需要加引號。
參見 Section 1.2.3, 「Shell 練習」能夠看到Shell的基本使用例子。
若是要使用腳本,能夠看Hbase的bin
目錄.在裏面找到後綴爲 *.rb
的腳本.要想運行這個腳本,要這樣
$ ./bin/hbase org.jruby.Main PATH_TO_SCRIPT
就能夠了
irbrc
能夠在你本身的Home目錄下建立一個.irbrc
文件. 在這個文件里加入自定義的命令。有一個有用的命令就是記錄命令歷史,這樣你就能夠把你的命令保存起來。
$ more .irbrc require 'irb/ext/save-history' IRB.conf[:SAVE_HISTORY] = 100 IRB.conf[:HISTORY_FILE] = "#{ENV['HOME']}/.irb-save-history"
能夠參見 ruby 關於 .irbrc
的文檔來學習更多的關於IRB的配置方法。
能夠將日期'08/08/16 20:56:29'從hbase log 轉換成一個 timestamp, 操做以下:
hbase(main):021:0> import java.text.SimpleDateFormat hbase(main):022:0> import java.text.ParsePosition hbase(main):023:0> SimpleDateFormat.new("yy/MM/dd HH:mm:ss").parse("08/08/16 20:56:29", ParsePosition.new(0)).getTime() => 1218920189000
也能夠逆過來操做。
hbase(main):021:0> import java.util.Date hbase(main):022:0> Date.new(1218920189000).toString() => "Sat Aug 16 20:56:29 UTC 2008"
要想把日期格式和Hbase log格式徹底相同,能夠參見文檔 SimpleDateFormat.
你能夠將shell切換成debug模式。這樣能夠看到更多的信息。 -- 例如能夠看到命令異常的stack trace:
hbase> debug
想要在shell中看到 DEBUG 級別的 logging ,能夠在啓動的時候加上 -d 參數.
$ ./bin/hbase shell -d
Table of Contents
能夠參考 發佈 Maven Artifacts的信息.要想讓全部的組件正確運行,關鍵在於配置好mvn release plugin。確保你在運行mvn release:perform以前使用的是正確的分支版本。這點很是的重要,要手寫${HBASE_HOME}
下的release.properties文件,而後執行release:perform.。你須要編輯它,這樣才能將他指向一個正確的SVN地址。(譯者注:能夠使用cloudera)
若是你出現了以下的問題,是由於你須要在pom.xml裏編輯版本而後加上 -SNAPSHOT
。
[INFO] Scanning for projects...[INFO] Searching repository for plugin with prefix: 'release'.[INFO] ------------------------------------------------------------------------[INFO] Building HBase[INFO] task-segment: [release:prepare] (aggregator-style)[INFO] ------------------------------------------------------------------------[INFO] [release:prepare {execution: default-cli}][INFO] ------------------------------------------------------------------------[ERROR] BUILD FAILURE[INFO] ------------------------------------------------------------------------[INFO] You don't have a SNAPSHOT project in the reactor projects list.[INFO] ------------------------------------------------------------------------[INFO] For more information, run Maven with the -e switch[INFO] ------------------------------------------------------------------------[INFO] Total time: 3 seconds[INFO] Finished at: Sat Mar 26 18:11:07 PDT 2011[INFO] Final Memory: 35M/423M[INFO] -----------------------------------------------------------------------
Table of Contents
參見 HBASE-3678 Add Eclipse-based Apache Formatter to HBase Wiki能夠看到一個eclipse的格式化文件,能夠幫你把編碼轉換成符合Hbase的格式。 這個issue還包含有使用這個formatter的指導。
咱們在Hbase中使用JUnit 4. 若是你但願跑一個最小化的HDFS, ZooKeeper, HBase, 或者 MapReduce 測試,能夠checkoutHBaseTestingUtility
. Alex Baranau of Sematext 闡述了怎麼使用它 HBase Case-Study: Using HBaseTestingUtility for Local Testing and Development (2010).
有些時候你不須要運行一個徹底的running server單元測試。好比一些操做org.apache.hadoop.hbase.Server
實例的方法或者使用 org.apache.hadoop.hbase.master.MasterServices
接口而不是 org.apache.hadoop.hbase.master.HMaster
類的應用. 這些狀況下,你能夠沒必要使用 mocked Server
實例. 好比:
(譯者注:原文到此爲止)
Table of Contents
關於 HBase 和 MapReduce詳見 javadocs. 下面是一些附加的幫助文檔.
當 MapReduce job的HBase table 使用TableInputFormat爲數據源格式的時候,他的splitter會給這個table的每一個region一個map。所以,若是一個table有100個region,就有100個map-tasks,不論須要scan多少個column families 。
要想使HBase做爲MapReduce的source,Job須要使用TableMapReduceUtil來配置,以下所示...
Job job = ...; Scan scan = new Scan();scan.setCaching(500); // 1 is the default in Scan, which will be bad for MapReduce jobsscan.setCacheBlocks(false); // Now set other scan attrs... TableMapReduceUtil.initTableMapperJob( tableName, // input HBase table name scan, // Scan instance to control CF and attribute selection MyMapper.class, // mapper Text.class, // reducer key LongWritable.class, // reducer value job // job instance );
...mapper須要繼承於TableMapper...
public class MyMapper extends TableMapper {public void map(ImmutableBytesWritable row, Result value, Context context) throws InterruptedException, IOException {// process data for the row from the Result instance.
儘管現有的框架容許一個HBase table做爲一個MapReduce job的輸入,其餘的Hbase table能夠同時做爲普通的表被訪問。例如在一個MapReduce的job中,能夠在Mapper的setup方法中建立HTable實例。
public class MyMapper extends TableMapper { private HTable myOtherTable; @Override public void setup(Context context) { myOtherTable = new HTable("myOtherTable"); }
一般建議關掉針對HBase的MapReduce job的預測執行(speculative execution)功能。這個功能也能夠用每一個Job的配置來完成。對於整個集羣,使用預測執行意味着雙倍的運算量。這可不是你所但願的。
Table of Contents
有一個關於NSQL數據庫的優勢和肯定的介紹, No Relation: The Mixed Blessings of Non-Relational Databases. 推薦看一看.
能夠使用HBaseAdmin或者Chapter 4, The HBase Shell 來建立和編輯Hbase的schemas
如今Hbase並不能很好的處理兩個或者三個以上的column families,因此儘可能讓你的column families數量少一些。目前,flush和compaction操做是針對一個Region。因此當一個column family操做大量數據的時候會引起一個flush。那些不相關的column families也有進行flush操做,儘管他們沒有操做多少數據。Compaction操做如今是根據一個column family下的所有文件的數量觸發的,而不是根據文件大小觸發的。當不少的column families在flush和compaction時,會形成不少沒用的I/O負載(要想解決這個問題,須要將flush和compaction操做只針對一個column family)
儘可能在你的應用中使用一個Column family。只有你的全部查詢操做只訪問一個column family的時候,能夠引入第二個和第三個column family.例如,你有兩個column family,但你查詢的時候老是訪問其中的一個,歷來不會兩個一塊兒訪問。
在Tom White的Hadoop: The Definitive Guide一書中,有一個章節描述了一個值得注意的問題:在一個集羣中,一個導入數據的進程一動不動,因此的client都在等待一個region(就是一個節點),過了一會後,變成了下一個region...若是使用了單調遞增或者時序的key就會形成這樣的問題。詳情能夠參見IKai畫的漫畫monotonically increasing values are bad。使用了順序的key會將本沒有順序的數據變得有順序,把負載壓在一臺機器上。因此要儘可能避免時間戳或者(e.g. 1, 2, 3)這樣的key。
若是你須要導入時間順序的文件(如log)到Hbase中,能夠學習OpenTSDB的作法。他有一個頁面來描述他的schema.OpenTSDB的Key的格式是[metric_type][event_timestamp],乍一看,彷佛違背了不將timestamp作key的建議,可是他並無將timestamp做爲key的一個關鍵位置,有成百上千的metric_type就足夠將壓力分散到各個region了。
在Hbase中,值是做爲一個cell保存在系統的中的,要定位一個cell,須要row,column name和timestamp.一般狀況下,若是你的row和column的名字要是太大(甚至比value的大小還要大)的話,你可能會遇到一些有趣的狀況。例如Marc Limotte 在 HBASE-3551(recommended!)尾部提到的現象。在Hbase的存儲文件Section 12.3.4.2, 「StoreFile (HFile)」中,有一個索引用來方便value的隨機訪問,可是訪問一個cell的座標要是太大的話,會佔用很大的內存,這個索引會被用盡。因此要想解決,能夠設置一個更大的block size,固然也能夠使用更小的column name `
行的版本的數量是HColumnDescriptor設置的,每一個column family能夠單獨設置,默認是3.這個設置是很重要的,在Chapter 11, 數據模型有描述,由於Hbase是不會去覆蓋一個值的,他只會在後面在追加寫,用timestamp來區分、過早的版本會在執行major compaction的時候刪除。這個版本的值能夠根據具體的應用增長減小。
Table of Contents
hbase.regionserver.blockCacheCount
hbase.regionserver.blockCacheFree
hbase.regionserver.blockCacheHitRatio
hbase.regionserver.blockCacheSize
hbase.regionserver.compactionQueueSize
hbase.regionserver.fsReadLatency_avg_time
hbase.regionserver.fsReadLatency_num_ops
hbase.regionserver.fsSyncLatency_avg_time
hbase.regionserver.fsSyncLatency_num_ops
hbase.regionserver.fsWriteLatency_avg_time
hbase.regionserver.fsWriteLatency_num_ops
hbase.regionserver.memstoreSizeMB
hbase.regionserver.regions
hbase.regionserver.requests
hbase.regionserver.storeFileIndexSizeMB
hbase.regionserver.stores
hbase.regionserver.storeFiles
參見 Metrics 能夠得到一個enable Metrics emission的指導。
hbase.regionserver.blockCacheCount
內存中的Block cache item數量。這個是存儲文件(HFiles)的緩存中的數量。
hbase.regionserver.blockCacheFree
內存中的Block cache memory 剩餘 (單位 bytes).
hbase.regionserver.blockCacheHitRatio
Block cache 命中率(0 到 100). TODO: 描述當cacheBlocks=false時對這個值得影響
hbase.regionserver.blockCacheSize
內存中的Block cache 大小 (單位 bytes)
hbase.regionserver.compactionQueueSize
compaction隊列的大小. 這個值是須要進行compaction的region數目
hbase.regionserver.fsReadLatency_avg_time
文件系統延遲 (ms). 這個值是平均讀HDFS的延遲時間
hbase.regionserver.fsReadLatency_num_ops
TODO
hbase.regionserver.fsSyncLatency_avg_time
文件系統同步延遲(ms)
hbase.regionserver.fsSyncLatency_num_ops
TODO
hbase.regionserver.fsWriteLatency_avg_time
文件系統寫延遲(ms)
hbase.regionserver.fsWriteLatency_num_ops
TODO
hbase.regionserver.memstoreSizeMB
全部的RegionServer的memstore大小 (MB)
hbase.regionserver.regions
RegionServer服務的regions數量
hbase.regionserver.requests
讀寫請求的所有數量。請求是指RegionServer的RPC數量,所以一次Get一個狀況,一個帶緩存的Scan也是一個請求。一個批量load是一個Hfile一個請求。
hbase.regionserver.storeFileIndexSizeMB
當前RegionServer的storefile索引的總大小(MB)
hbase.regionserver.stores
RegionServer打開的stores數量。一個stores對應一個column family。例如,一個表有3個region在這個RegionServer上,對應一個 column family就會有3個store.
hbase.regionserver.storeFiles
RegionServer打開的存儲文件(HFile)數量。這個值必定大於等於store的數量。
參見 跨集羣複製.
Table of Contents
簡單來講,應用程序是以表的方式在Hbase存儲數據的。表是由行和列構成的,因此的列是從屬於某一個column family的。行和列的交叉點稱之爲cell,cell是版本化的。cell的內容是不可分割的字節數組。
表的row key也是一段字節數組,因此任何東西均可以保存進去,不管是字符串或者數字。Hbase的表是按key排序的,排序方式之針對字節的。因此的表都必需要有主鍵-key.
下面 是根據BigTable 論文稍加修改的例子。 有一個名爲webtable
的表,包含兩個column family:contents
和anchor
.在這個例子裏面,anchor
有兩個列 (anchor:cssnsi.com
, anchor:my.look.ca
),contents
僅有一列(contents:html
)
一個列名是有它的column family前綴和qualifier鏈接而成。例如列contents:html是column family contents
加冒號(:
)加 qualifierhtml
組成的。
Table 11.1. 表 webtable
Row Key | Time Stamp | ColumnFamily contents |
ColumnFamily anchor |
---|---|---|---|
"com.cnn.www" | t9 | anchor:cnnsi.com = "CNN" |
|
"com.cnn.www" | t8 | anchor:my.look.ca = "CNN.com" |
|
"com.cnn.www" | t6 | contents:html = "..." |
|
"com.cnn.www" | t5 | contents:html = "..." |
|
"com.cnn.www" | t3 | contents:html = "..." |
儘管在概念視圖裏,表能夠被當作是一個稀疏的行的集合。但在物理上,它的是區分column family 存儲的。新的columns能夠不通過聲明直接加入一個column family.
Table 11.2. ColumnFamily anchor
Row Key | Time Stamp | Column Family anchor |
---|---|---|
"com.cnn.www" | t9 | anchor:cnnsi.com = "CNN" |
"com.cnn.www" | t8 | anchor:my.look.ca = "CNN.com" |
Table 11.3. ColumnFamily contents
Row Key | Time Stamp | ColumnFamily "contents:" |
---|---|---|
"com.cnn.www" | t6 | contents:html = "..." |
"com.cnn.www" | t5 | contents:html = "..." |
"com.cnn.www" | t3 | contents:html = "..." |
值得注意的是在上面的概念視圖中空白cell在物理上是不存儲的,由於根本沒有必要存儲。所以若一個請求爲要獲取t8
時間的contents:html
,他的結果就是空。類似的,若請求爲獲取t9
時間的anchor:my.look.ca
,結果也是空。可是,若是不指明時間,將會返回最新時間的行,每一個最新的都會返回。例如,若是請求爲獲取row key爲"com.cnn.www",沒有指明時間戳的話,活動的結果是t6
下的contents:html,t9
下的anchor:cnnsi.com
和t8
下anchor:my.look.ca
。
表是在schema聲明的時候定義的。
row key是不可分割的字節數組。行是按字典排序由低到高存儲在表中的。一個空的數組是用來標識表空間的起始或者結尾。
在Hbase是column family一些列的集合。一個column family全部列成員是有着相同的前綴。好比,列courses:history 和 courses:math都是 column family courses的成員.冒號(:)是column family的分隔符,用來區分前綴和列名。column 前綴必須是可打印的字符,剩下的部分(稱爲qualify),能夠又任意字節數組組成。column family必須在表創建的時候聲明。column就不須要了,隨時能夠新建。
在物理上,一個的column family成員在文件系統上都是存儲在一塊兒。由於存儲優化都是針對column family級別的,這就意味着,一個colimn family的全部成員的是用相同的方式訪問的。
A {row, column, version} 元組就是一個Hbase中的一個 cell
。Cell的內容是不可分割的字節數組。
一個 {row, column, version} 元組是Hbase中的一個cell
.可是有可能會有不少的cell的row和column是相同的,能夠使用version來區分不一樣的cell.
rows和column key是用字節數組表示的,version則是用一個長整型表示。這個long的值使用 java.util.Date.getTime()
或者 System.currentTimeMillis()
產生的。這就意味着他的含義是「當前時間和1970-01-01 UTC的時間差,單位毫秒。」
在Hbase中,版本是按倒序排列的,所以當讀取這個文件的時候,最早找到的是最近的版本。
有些人不是很理解Hbase的 cell
意思。一個常見的問題是:
下面咱們介紹下在Hbase中版本是如何工做的。[15].
在這一章咱們來仔細看看在Hbase的各個主要操做中版本起到了什麼做用。
Gets實在Scan的基礎上實現的。能夠詳細參見下面的討論 Get 一樣能夠用 Scan來描述.
默認狀況下,若是你沒有指定版本,當你使用Get
操做的時候,會返回最近版本的Cell(該Cell多是最新寫入的,但不能保證)。默認的操做能夠這樣修改:
若是想要返回返回兩個以上的把版本,參見Get.setMaxVersions()
若是想要返回的版本不僅是最近的,參見 Get.setTimeRange()
要向查詢的最新版本要小於或等於給定的這個值,這就意味着給定的'最近'的值能夠是某一個時間點。能夠使用0到你想要的時間來設置,還要把max versions設置爲1.
下面的Get操做會只得到最新的一個版本。
Get get = new Get(Bytes.toBytes("row1")); Result r = htable.get(get); byte[] b = r.getValue(Bytes.toBytes("cf"), Bytes.toBytes("attr")); // returns current version of value
下面的Get操做會得到最近的3個版本。
Get get = new Get(Bytes.toBytes("row1")); get.setMaxVersions(3); // will return last 3 versions of row Result r = htable.get(get); byte[] b = r.getValue(Bytes.toBytes("cf"), Bytes.toBytes("attr")); // returns current version of value List kv = r.getColumn(Bytes.toBytes("cf"), Bytes.toBytes("attr")); // returns all versions of this column
一個Put操做會給一個cell
,建立一個版本,默認使用當前時間戳,固然你也能夠本身設置時間戳。這就意味着你能夠把時間設置在過去或者將來,或者隨意使用一個Long值。
要想覆蓋一個現有的值,就意味着你的row,column和版本必須徹底相等。
下面的Put操做不指明版本,因此Hbase會用當前時間做爲版本。
Put put = new Put(Bytes.toBytes(row)); put.add(Bytes.toBytes("cf"), Bytes.toBytes("attr1"), Bytes.toBytes( data)); htable.put(put);
下面的Put操做,指明瞭版本。
Put put = new Put( Bytes.toBytes(row )); long explicitTimeInMs = 555; // just an example put.add(Bytes.toBytes("cf"), Bytes.toBytes("attr1"), explicitTimeInMs, Bytes.toBytes(data)); htable.put(put);
當你進行delete操做的是,有兩種方式來肯定要刪除的版本。
刪除全部比當前早的版本。
刪除指定的版本。
一個刪除操做能夠刪除一行,也能夠是一個column family,或者僅僅刪除一個column。你也能夠刪除指明的一個版本。若你沒有指明,默認狀況下是刪除比當前時間早的版本。
刪除操做的實現是建立一個刪除標記。例如,咱們想要刪除一個版本,或者默認是currentTimeMillis
。就意味着「刪除比這個版本更早的全部版本」.Hbase不會去改那些數據,數據不會當即從文件中刪除。他使用刪除標記來屏蔽掉這些值。[16]若你知道的版本比數據中的版本晚,就意味着這一行中的全部數據都會被刪除。
關於版本還有一些bug(或者稱之爲未實現的功能),計劃在下個版本實現。
刪除標記操做可能會標記以後put的數據。[17].須要值得注意的是,當寫下一個刪除標記後,只有下一個major compaction操做發起以後,這個刪除標記纔會消失。設想一下,當你寫下一個刪除標記-「刪除全部<= 時間T的數據」。但以後,你又執行了一個Put操做,版本<= T。這樣就算這個Put發生在刪除以後,他的數據也算是打上了刪除標記。這個Put並不會失敗,可是你須要注意的是這個操做沒有任何做用。只有一個major compaction執行只有,一切纔會恢復正常。若是你的Put操做一直使用升序的版本,這個錯誤就不會發生。可是也有可能出現這樣的狀況,你刪除以後,
「設想一下,你一個cell有三個版本t1,t2和t3。你的maximun-version設置是2.當你請求獲取所有版本的時候,只會返回兩個,t2和t3。若是你將t2和t3刪除,就會返回t1。可是若是在刪除以前,發生了major compaction操做,那麼什麼值都很差返回了。[18]」
[13] 目前,只有最新的那個是能夠獲取到的。.
[14] 能夠
[15] See HBASE-2406 for discussion of HBase versions. Bending time in HBase makes for a good read on the version, or time, dimension in HBase. It has more detail on versioning than is provided here. As of this writing, the limiitation Overwriting values at existing timestamps mentioned in the article no longer holds in HBase. This section is basically a synopsis of this article by Bruno Dumon.
[16] 當Hbase執行一次major compaction,標記刪除的數據會被實際的刪除,刪除標記也會被刪除。
[17] HBASE-2256
[18] See Garbage Collection in Bending time in HBase
Table of Contents
Hbase客戶端的 HTable類負責尋找相應的RegionServers來處理行。他是先查詢 .META.
和 -ROOT
目錄表。而後再肯定region的位置。定位到所須要的區域後,客戶端會直接 去訪問相應的region(不通過master),發起讀寫請求。這些信息會緩存在客戶端,這樣就不用每發起一個請求就去查一下。若是一個region已經廢棄(緣由多是master load balance或者RegionServer死了),客戶端就會從新進行這個步驟,決定要去訪問的新的地址。
管理集羣操做是經由HBaseAdmin發起的
關於鏈接的配置信息,參見Section 3.7, 「鏈接Hbase集羣的客戶端配置和依賴」.
HTable不是線程安全的。建議使用同一個HBaseConfiguration實例來建立HTable實例。這樣能夠共享ZooKeeper和socket實例。例如,最好這樣作:
HBaseConfiguration conf = HBaseConfiguration.create();HTable table1 = new HTable(conf, "myTable");HTable table2 = new HTable(conf, "myTable");
而不是這樣:
HBaseConfiguration conf1 = HBaseConfiguration.create();HTable table1 = new HTable(conf1, "myTable");HBaseConfiguration conf2 = HBaseConfiguration.create();HTable table2 = new HTable(conf2, "myTable");
若是你想知道的更多的關於Hbase客戶端connection的知識,能夠參照: HConnectionManager.
若關閉了HTable中的 Section 13.6.1, 「AutoFlush」,Put
操做會在寫緩衝填滿的時候向RegionServer發起請求。默認狀況下,寫緩衝是2MB.在Htable被廢棄以前,要調用close()
, flushCommits()
操做,這樣寫緩衝就不會丟失。
要想更好的細粒度控制 Put
或Delete
的批量操做,能夠參考Htable中的batch 方法.
本章節都是再講Regions.
Regions是由每一個Column Family的Store組成。
Region的大小是一個棘手的問題,須要考量以下幾個因素。
Regions是可用性和分佈式的最基本單位
HBase經過將region切分在許多機器上實現分佈式。也就是說,你若是有16GB的數據,只分了2個region, 你卻有20臺機器,有18臺就浪費了。
region數目太多就會形成性能降低,如今比之前好多了。可是對於一樣大小的數據,700個region比3000個要好。
region數目太少就會妨礙可擴展性,下降並行能力。有的時候致使壓力不夠分散。這就是爲何,你向一個10節點的Hbase集羣導入200MB的數據,大部分的節點是idle的。
RegionServer中1個region和10個region索引須要的內存量沒有太多的差異。
最好是使用默認的配置,能夠把熱的表配小一點(或者受到split熱點的region把壓力分散到集羣中)。若是你的cell的大小比較大(100KB或更大),就能夠把region的大小調到1GB。
RegionServer的Splits操做是不可見的,由於Master不會參與其中。RegionServer切割region的步驟是,先將該region下線,而後切割,將其子region加入到元信息中,再將他們加入到本來的RegionServer中,最後彙報Master.參見Section 3.6.6, 「管理 Splitting」來手動管理切割操做。
當沒有任何region在進行轉換的時候,Hbase會按期執行一個load balance。他會將移動region進行集羣的負載均衡。能夠配置運行時間間隔。
一個Store包含了一個MemStore和若干個StoreFile(HFile).一個Store能夠定位到一個column family中的一個region.
MemStores是Store中的內存Store,能夠進行修改操做。修改的內容是KeyValues。當flush的是,現有的memstore會生成快照,而後清空。在執行快照的時候,Hbase會繼續接收修改操做,保存在memstore外面,直到快照完成。
hfile文件格式是基於BigTable [2006]論文中的SSTable。構建在Hadoop的tfile上面(直接使用了tfile的單元測試和壓縮工具)。 Schubert Zhang's的博客HFile: A Block-Indexed File Format to Store Sorted Key-Value Pairs詳細介紹了Hbases的hfile。Matteo Bertozzi也作了詳細的介紹HBase I/O: HFile。
要想看到hfile內容的文本化版本,你能夠使用org.apache.hadoop.hbase.io.hfile.HFile
工具。能夠這樣用:
$ ${HBASE_HOME}/bin/hbase org.apache.hadoop.hbase.io.hfile.HFile
例如,你想看文件 hdfs://10.81.47.41:9000/hbase/TEST/1418428042/DSMP/4759508618286845475
的內容, 就執行以下的命令:
$ ${HBASE_HOME}/bin/hbase org.apache.hadoop.hbase.io.hfile.HFile -v -f hdfs://10.81.47.41:9000/hbase/TEST/1418428042/DSMP/4759508618286845475
若是你沒有輸入-v,就僅僅能看到一個hfile的彙總信息。其餘功能的用法能夠看HFile
的文檔。
有兩種類型的壓縮:minor和major。minor壓縮一般會將數個小的相鄰的文件合併成一個大的。Minor不會刪除打上刪除標記的數據,也不會刪除過時的數據,Major壓縮會刪除過時的數據。有些時候minor壓縮就會將一個store中的所有文件壓縮,實際上這個時候他自己就是一個major壓縮。對於一個minor壓縮是如何壓縮的,能夠參見ascii diagram in the Store source code.
在執行一個major壓縮以後,一個store只會有一個sotrefile,一般狀況下這樣能夠提供性能。注意:major壓縮將會將store中的數據所有重寫,在一個負載很大的系統中,這個操做是很傷的。因此在大型系統中,一般會本身Section 3.6.6, 「管理 Splitting」。
每一個RegionServer會將更新(Puts, Deletes) 先記錄到Write Ahead Log中(WAL),而後將其更新在Section 12.3.4, 「Store」的Section 12.3.4.1, 「MemStore」裏面。這樣就保證了Hbase的寫的可靠性。若是沒有WAL,當RegionServer宕掉的時候,MemStore尚未flush,StoreFile尚未保存,數據就會丟失。HLog 是Hbase的一個WAL實現,一個RegionServer有一個HLog實例。
WAL 保存在HDFS 的/hbase/.logs/
裏面,每一個region一個文件。
要想知道更多的信息,能夠訪問維基百科 Write-Ahead Log 的文章.
TODO (describe).
TODO
hbase.hlog.split.skip.errors
默認設置爲 true
,在split執行中發生的任何錯誤會被記錄,有問題的WAL會被移動到Hbase rootdir
目錄下的.corrupt
目錄,接着進行處理。若是設置爲 false
,異常會被拋出,split會記錄錯誤。[19]
若是咱們在分割日誌的時候發生EOF,就是hbase.hlog.split.skip.errors
設置爲 false
,咱們也會進行處理。一個EOF會發生在一行一行讀取Log,可是Log中最後一行彷佛只寫了一半就中止了。若是在處理過程當中發生了EOF,咱們還會繼續處理,除非這個文件是要處理的最後一個文件。[20]
[19] See HBASE-2958 When hbase.hlog.split.skip.errors is set to false, we fail the split but thats it. We need to do more than just fail split if this flag is set.
[20] 要想知道背景知識, 參見 HBASE-2643 Figure how to deal with eof splitting logs
Table of Contents
hbase.regionserver.handler.count
hfile.block.cache.size
hbase.regionserver.global.memstore.upperLimit
hbase.regionserver.global.memstore.lowerLimit
hbase.hstore.blockingStoreFiles
hbase.hregion.memstore.block.multiplier
能夠從 wiki Performance Tuning看起。這個文檔講了一些主要的影響性能的方面:RAM, 壓縮, JVM 設置, 等等。而後,能夠看看下面的補充內容。
在RegionServer打開RPC-level的日誌對於深度的優化是有好處的。一旦打開,日誌將噴涌而出。因此不建議長時間打開,只能看一小段時間。要想啓用RPC-level的職責,能夠使用RegionServer UI點擊Log Level。將 org.apache.hadoop.ipc
的日誌級別設爲DEBUG
。而後tail RegionServer的日誌,進行分析。
要想關閉,只要把日誌級別設爲INFO
就能夠了.
在這個PPT Avoiding Full GCs with MemStore-Local Allocation Buffers, Todd Lipcon描述列在Hbase中常見的兩種stop-the-world的GC操做,尤爲是在loading的時候。一種是CMS失敗的模式(譯者注:CMS是一種GC的算法),另外一種是老一代的堆碎片致使的。要想定位第一種,只要將CMS執行的時間提早就能夠了,加入-XX:CMSInitiatingOccupancyFraction
參數,把值調低。能夠先從60%和70%開始(這個值調的越低,觸發的GC次數就越多,消耗的CPU時間就越長)。要想定位第二種錯誤,Todd加入了一個實驗性的功能,在Hbase 0.90.x中這個是要明確指定的(在0.92.x中,這個是默認項),將你的Configuration
中的hbase.hregion.memstore.mslab.enabled
設置爲true。詳細信息,能夠看這個PPT.
Hbase中region的數目能夠根據Section 3.6.5, 「更大的 Regions」調整.也能夠參見 Section 12.3.1, 「Region大小」
對於大型的系統,你須要考慮管理壓縮和分割
生產環境中的系統須要在column family的定義中使用Section 3.6.4, 「LZO 壓縮」之類的壓縮。
hbase.regionserver.handler.count
參見hbase.regionserver.handler.count
.這個參數的本質是設置一個RegsionServer能夠同時處理多少請求。 若是定的過高,吞吐量反而會下降;若是定的過低,請求會被阻塞,得不到響應。你能夠打開RPC-level日誌讀Log,來決定對於你的集羣什麼值是合適的。(請求隊列也是會消耗內存的)
hfile.block.cache.size
參見 hfile.block.cache.size
. 對於RegionServer進程的內存設置。
hbase.regionserver.global.memstore.upperLimit
參見 hbase.regionserver.global.memstore.upperLimit
. 這個內存設置是根據RegionServer的須要來設定。
hbase.regionserver.global.memstore.lowerLimit
參見 hbase.regionserver.global.memstore.lowerLimit
. 這個內存設置是根據RegionServer的須要來設定。
hbase.hstore.blockingStoreFiles
參見hbase.hstore.blockingStoreFiles
. 若是在RegionServer的Log中block,提升這個值是有幫助的。
hbase.hregion.memstore.block.multiplier
參見 hbase.hregion.memstore.block.multiplier
. 若是有足夠的RAM,提升這個值。
若是你的數據老是往一個region寫。你能夠再看看處理時序數據 這一章.
若是能夠的話,儘可能使用批量導入工具,參見 Bulk Loads.不然就要詳細看看下面的內容。
默認狀況下Hbase建立Table會新建一個region。執行批量導入,意味着全部的client會寫入這個region,直到這個region足夠大,以致於分裂。一個有效的提升批量導入的性能的方式,是預建立空的region。最好稍保守一點,由於過多的region會實實在在的下降性能。下面是一個預建立region的例子。(注意:這個例子裏須要根據應用的key進行調整。):
public static boolean createTable(HBaseAdmin admin, HTableDescriptor table, byte[][] splits)throws IOException { try { admin.createTable( table, splits ); return true; } catch (TableExistsException e) { logger.info("table " + table.getNameAsString() + " already exists"); // the table already exists... return false; }}public static byte[][] getHexSplits(String startKey, String endKey, int numRegions) { byte[][] splits = new byte[numRegions-1][]; BigInteger lowestKey = new BigInteger(startKey, 16); BigInteger highestKey = new BigInteger(endKey, 16); BigInteger range = highestKey.subtract(lowestKey); BigInteger regionIncrement = range.divide(BigInteger.valueOf(numRegions)); lowestKey = lowestKey.add(regionIncrement); for(int i=0; i < numRegions-1;i++) { BigInteger key = lowestKey.add(regionIncrement.multiply(BigInteger.valueOf(i))); byte[] b = String.format("%016x", key).getBytes(); splits[i] = b; } return splits;}
當你進行大量的Put的時候,要確認你的HTable的setAutoFlush是關閉着的。不然的話,每執行一個Put就要想RegionServer發一個請求。經過 htable.add(Put)
和 htable.add( Put)
來將Put添加到寫緩衝中。若是 autoFlush = false
,要等到寫緩衝都填滿的時候纔會發起請求。要想顯式的發起請求,能夠調用flushCommits
。在HTable
實例上進行的close
操做也會發起flushCommits
若是Hbase的輸入源是一個MapReduce Job,要確保輸入的Scan的setCaching
值要比默認值0要大。使用默認值就意味着map-task每一行都會去請求一下region-server。能夠把這個值設爲500,這樣就能夠一次傳輸500行。固然這也是須要權衡的,過大的值會同時消耗客戶端和服務端很大的內存,不是越大越好。
當Scan用來處理大量的行的時候(尤爲是做爲MapReduce的輸入),要注意的是選擇了什麼字段。若是調用了 scan.addFamily
,這個column family的全部屬性都會返回。若是隻是想過濾其中的一小部分,就指定那幾個column,不然就會形成很大浪費,影響性能。
這與其說是提升性能,倒不如說是避免發生性能問題。若是你忘記了關閉ResultScanners,會致使RegionServer出現問題。因此必定要把ResultScanner包含在try/catch 塊中...
Scan scan = new Scan();// set attrs...ResultScanner rs = htable.getScanner(scan);try { for (Result r = rs.next(); r != null; r = rs.next()) { // process result...} finally { rs.close(); // always close the ResultScanner!}htable.close();
Scan實例能夠在RegionServer中使用塊緩存,能夠由setCacheBlocks
方法控制。若是Scan是MapReduce的輸入源,要將這個值設置爲 false
。對於常常讀到的行,就建議使用塊緩衝。
當scan一個表的時候, 若是僅僅須要row key(不須要no families, qualifiers, values 和 timestamps),在加入FilterList的時候,要使用Scanner的setFilter
方法的時候,要填上MUST_PASS_ALL
操做參數(譯者注:至關於And操做符)。一個FilterList要包含一個 FirstKeyOnlyFilter 和一個 KeyOnlyFilter.經過這樣的filter組合,就算在最壞的狀況下,RegionServer只會從磁盤讀一個值,同時最小化客戶端的網絡帶寬佔用。
Table of Contents
Bloom filters 是在 HBase-1200 Add bloomfilters上面開發的.[21][22] (譯者注:Bloom Filter是一個算法,能夠用來快速確認一個Row Key或者值是否在一個Hfile裏面。)
能夠在column family的選項的配置Blooms.能夠經過Hbase Shell,也能夠用Java代碼操做 org.apache.hadoop.hbase.HColumnDescriptor
.
HColumnDescriptor
配置使用 HColumnDescriptor.setBloomFilterType(NONE | ROW | ROWCOL)
來控制每一個column family的Blooms這種。默認值是 NONE
,若是值是ROW
,就會在插入的時候去Hash這個row,加入到Bloom中去。若是值是ROWCOL
,就Hash這個row,column family和column family qualifer。(譯者注,ROW是哈希row key)
io.hfile.bloom.enabled
全局關閉開關當有些東西出錯的時候,Configuration
中的io.hfile.bloom.enabled
是一個關閉的開關。 默認是 true
.
io.hfile.bloom.error.rate
io.hfile.bloom.error.rate
= 平均錯誤率。默認是 1%.減小一半(如 .5%),就意味着每一個bloom entry加一個bit.
io.hfile.bloom.max.fold
io.hfile.bloom.max.fold
= 保證最低的fold率。大多數人不應修改這個值,默認是7,就是說能夠摺疊到本來大小的1/128。參見 Development Process中的文檔 BloomFilters in HBase得到更多關於這個配置的信息。
Bloom filters在StoreFile
加入了一個entry.包括 通常的 FileInfo
數據結構和兩個額外entries到StoreFile
的元數據部分中。
StoreFile
中的BloomFilter, FileInfo
數據結構BLOOM_FILTER_TYPE
FileInfo
有一個 BLOOM_FILTER_TYPE
entry,能夠被設置爲 NONE
, ROW
或者 ROWCOL.
StoreFile
元數據中的BloomFilter entriesBLOOM_FILTER_META
BLOOM_FILTER_META
保存了Bloom的大小,使用的Hash算法等信息。他的大小的很小。 StoreFile.Reader
加載的時候會緩存進去。
BLOOM_FILTER_DATA
BLOOM_FILTER_DATA
是實際的bloomfiter數據。按需獲取,保存在LRU緩存中(若是緩存是開啓的,默認開啓)。
[21] For description of the development process -- why static blooms rather than dynamic -- and for an overview of the unique properties that pertain to blooms in HBase, as well as possible future directions, see the Development Process section of the document BloomFilters in HBase attached to HBase-1200.
[22] The bloom filters described here are actually version two of blooms in HBase. In versions up to 0.19.x, HBase had a dynamic bloom option based on work done by the European Commission One-Lab Project 034819. The core of the HBase bloom work was later pulled up into Hadoop to implement org.apache.hadoop.io.BloomMapFile. Version 1 of HBase blooms never worked that well. Version 2 is a rewrite from scratch though again it starts with the one-lab work.
Table of Contents
首先能夠看看master的log。一般狀況下,他老是一行一行的重複信息。若是不是這樣,說明有問題,能夠Google或是用search-hadoop.com來搜索遇到的exception。
一個錯誤一般不是單獨出如今Hbase中的,一般是某一個地方發生了異常,而後對其餘的地方發生影響。處處都是exception和stack straces。遇到這樣的錯誤,最好的辦法是查日誌,找到最初的異常。例如Region會在abort的時候打印一下信息。Grep這個Dump就有可能找到最初的異常信息。
RegionServer的自殺是很「正常」的。當一些事情發生錯誤的,他們就會自殺。若是ulimit和xcievers(最重要的兩個設定,詳見Section 1.3.1.6, 「 ulimit
和 nproc
」)沒有修改,HDFS將沒法運轉正常,在HBase看來,HDFS死掉了。假想一下,你的MySQL忽然沒法訪問它的文件系統,他會怎麼作。一樣的事情會發生在Hbase和HDFS上。還有一個形成RegionServer切腹(譯者注:居然用日文詞)自殺的常見的緣由是,他們執行了一個長時間的GC操做,這個時間超過了ZooKeeper的session timeout。關於GC停頓的詳細信息,參見Todd Lipcon的 3 part blog post by Todd Lipcon 和上面的 Section 13.1.1.1, 「長時間GC停頓」.
重要日誌的位置( 是啓動服務的用戶, 是機器的名字)
NameNode: $HADOOP_HOME/logs/hadoop- -namenode- .log
DataNode: $HADOOP_HOME/logs/hadoop- -datanode- .log
JobTracker: $HADOOP_HOME/logs/hadoop- -jobtracker- .log
TaskTracker: $HADOOP_HOME/logs/hadoop- -jobtracker- .log
HMaster: $HBASE_HOME/logs/hbase- -master- .log
RegionServer: $HBASE_HOME/logs/hbase- -regionserver- .log
ZooKeeper: TODO
對於單節點模式,Log都會在一臺機器上,可是對於生產環境,都會運行在一個集羣上。
NameNode的日誌在NameNode server上。HBase Master 一般也運行在NameNode server上,ZooKeeper一般也是這樣。
對於小一點的機器,JobTracker也一般運行在NameNode server上面。
每一臺DataNode server有一個HDFS的日誌,Region有一個Hbase日誌。
每一個DataNode server還有一份TaskTracker的日誌,來記錄MapReduce的Task信息。
search-hadoop.com將全部的 mailing lists 和 JIRA創建了索引。用它來找Hadoop/HBase的問題很方便。
tail
是一個命令行工具,能夠用來看日誌的尾巴。加入的"-f"參數後,就會在數據更新的時候本身刷新。用它來看日誌很方便。例如,一個機器須要花不少時間來啓動或關閉,你能夠tail他的master log(也能夠是region server的log)。
top
是一個很重要的工具來看你的機器各個進程的資源佔用狀況。下面是一個生產環境的例子:
top - 14:46:59 up 39 days, 11:55, 1 user, load average: 3.75, 3.57, 3.84Tasks: 309 total, 1 running, 308 sleeping, 0 stopped, 0 zombieCpu(s): 4.5%us, 1.6%sy, 0.0%ni, 91.7%id, 1.4%wa, 0.1%hi, 0.6%si, 0.0%stMem: 24414432k total, 24296956k used, 117476k free, 7196k buffersSwap: 16008732k total, 14348k used, 15994384k free, 11106908k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 15558 hadoop 18 -2 3292m 2.4g 3556 S 79 10.4 6523:52 java 13268 hadoop 18 -2 8967m 8.2g 4104 S 21 35.1 5170:30 java 8895 hadoop 18 -2 1581m 497m 3420 S 11 2.1 4002:32 java…
這裏你能夠看到系統的load average在最近5分鐘是3.75,意思就是說這5分鐘裏面平均有3.75個線程在CPU時間的等待隊列裏面。一般來講,最完美的狀況是這個值和CPU和核數相等,比這個值低意味着資源閒置,比這個值高就是過載了。這是一個重要的概念,要想理解的更多,能夠看這篇文章 http://www.linuxjournal.com/article/9001.
處理負載,咱們能夠看到系統已經幾乎使用了他的所有RAM,其中大部分都是用於OS cache(這是一件好事).Swap只使用了一點點KB,這正是咱們指望的,若是數值很高的話,就意味着在進行交換,這對Java程序的性能是致命的。另外一種檢測交換的方法是看Load average是否太高(load average太高還多是磁盤損壞或者其它什麼緣由致使的)。
默認狀況下進程列表不是頗有用,咱們能夠看到3個Java進程使用了111%的CPU。要想知道哪一個進程是什麼,能夠輸入"c",每一行就會擴展信息。輸入「1」能夠顯示CPU的每一個核的具體情況。
jps
是JDK集成的一個工具,能夠用來看當前用戶的Java進程id。(若是是root,能夠看到全部用戶的id),例如:
hadoop@sv4borg12:~$ jps1322 TaskTracker17789 HRegionServer27862 Child1158 DataNode25115 HQuorumPeer2950 Jps19750 ThriftServer18776 jmx
按順序看
你能夠看到這個進程啓動是所有命令行信息。
hadoop@sv4borg12:~$ ps aux | grep HRegionServerhadoop 17789 155 35.2 9067824 8604364 ? S
jstack
是一個最重要(除了看Log)的java工具,能夠看到具體的Java進程的在作什麼。能夠先用Jps看到進程的Id,而後就能夠用jstack。他會按線程的建立順序顯示線程的列表,還有這個線程在作什麼。下面是例子:
這個主線程是一個RegionServer正在等master返回什麼信息。
"regionserver60020" prio=10 tid=0x0000000040ab4000 nid=0x45cf waiting on condition [0x00007f16b6a96000..0x00007f16b6a96a70] java.lang.Thread.State: TIMED_WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x00007f16cd5c2f30> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:198) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:1963) at java.util.concurrent.LinkedBlockingQueue.poll(LinkedBlockingQueue.java:395) at org.apache.hadoop.hbase.regionserver.HRegionServer.run(HRegionServer.java:647) at java.lang.Thread.run(Thread.java:619) The MemStore flusher thread that is currently flushing to a file:"regionserver60020.cacheFlusher" daemon prio=10 tid=0x0000000040f4e000 nid=0x45eb in Object.wait() [0x00007f16b5b86000..0x00007f16b5b87af0] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Object.java:485) at org.apache.hadoop.ipc.Client.call(Client.java:803) - locked <0x00007f16cb14b3a8> (a org.apache.hadoop.ipc.Client$Call) at org.apache.hadoop.ipc.RPC$Invoker.invoke(RPC.java:221) at $Proxy1.complete(Unknown Source) at sun.reflect.GeneratedMethodAccessor38.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.apache.hadoop.io.retry.RetryInvocationHandler.invokeMethod(RetryInvocationHandler.java:82) at org.apache.hadoop.io.retry.RetryInvocationHandler.invoke(RetryInvocationHandler.java:59) at $Proxy1.complete(Unknown Source) at org.apache.hadoop.hdfs.DFSClient$DFSOutputStream.closeInternal(DFSClient.java:3390) - locked <0x00007f16cb14b470> (a org.apache.hadoop.hdfs.DFSClient$DFSOutputStream) at org.apache.hadoop.hdfs.DFSClient$DFSOutputStream.close(DFSClient.java:3304) at org.apache.hadoop.fs.FSDataOutputStream$PositionCache.close(FSDataOutputStream.java:61) at org.apache.hadoop.fs.FSDataOutputStream.close(FSDataOutputStream.java:86) at org.apache.hadoop.hbase.io.hfile.HFile$Writer.close(HFile.java:650) at org.apache.hadoop.hbase.regionserver.StoreFile$Writer.close(StoreFile.java:853) at org.apache.hadoop.hbase.regionserver.Store.internalFlushCache(Store.java:467) - locked <0x00007f16d00e6f08> (a java.lang.Object) at org.apache.hadoop.hbase.regionserver.Store.flushCache(Store.java:427) at org.apache.hadoop.hbase.regionserver.Store.access$100(Store.java:80) at org.apache.hadoop.hbase.regionserver.Store$StoreFlusherImpl.flushCache(Store.java:1359) at org.apache.hadoop.hbase.regionserver.HRegion.internalFlushcache(HRegion.java:907) at org.apache.hadoop.hbase.regionserver.HRegion.internalFlushcache(HRegion.java:834) at org.apache.hadoop.hbase.regionserver.HRegion.flushcache(HRegion.java:786) at org.apache.hadoop.hbase.regionserver.MemStoreFlusher.flushRegion(MemStoreFlusher.java:250) at org.apache.hadoop.hbase.regionserver.MemStoreFlusher.flushRegion(MemStoreFlusher.java:224) at org.apache.hadoop.hbase.regionserver.MemStoreFlusher.run(MemStoreFlusher.java:146)
一個處理線程是在等一些東西(例如put, delete, scan...):
"IPC Server handler 16 on 60020" daemon prio=10 tid=0x00007f16b011d800 nid=0x4a5e waiting on condition [0x00007f16afefd000..0x00007f16afefd9f0] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x00007f16cd3f8dd8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:158) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1925) at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:358) at org.apache.hadoop.hbase.ipc.HBaseServer$Handler.run(HBaseServer.java:1013)
有一個線程正在忙,在遞增一個counter(這個階段是正在建立一個scanner來讀最新的值):
"IPC Server handler 66 on 60020" daemon prio=10 tid=0x00007f16b006e800 nid=0x4a90 runnable [0x00007f16acb77000..0x00007f16acb77cf0] java.lang.Thread.State: RUNNABLE at org.apache.hadoop.hbase.regionserver.KeyValueHeap. (KeyValueHeap.java:56) at org.apache.hadoop.hbase.regionserver.StoreScanner. (StoreScanner.java:79) at org.apache.hadoop.hbase.regionserver.Store.getScanner(Store.java:1202) at org.apache.hadoop.hbase.regionserver.HRegion$RegionScanner. (HRegion.java:2209) at org.apache.hadoop.hbase.regionserver.HRegion.instantiateInternalScanner(HRegion.java:1063) at org.apache.hadoop.hbase.regionserver.HRegion.getScanner(HRegion.java:1055) at org.apache.hadoop.hbase.regionserver.HRegion.getScanner(HRegion.java:1039) at org.apache.hadoop.hbase.regionserver.HRegion.getLastIncrement(HRegion.java:2875) at org.apache.hadoop.hbase.regionserver.HRegion.incrementColumnValue(HRegion.java:2978) at org.apache.hadoop.hbase.regionserver.HRegionServer.incrementColumnValue(HRegionServer.java:2433) at sun.reflect.GeneratedMethodAccessor20.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.apache.hadoop.hbase.ipc.HBaseRPC$Server.call(HBaseRPC.java:560) at org.apache.hadoop.hbase.ipc.HBaseServer$Handler.run(HBaseServer.java:1027)
還有一個線程在從HDFS獲取數據。
"IPC Client (47) connection to sv4borg9/10.4.24.40:9000 from hadoop" daemon prio=10 tid=0x00007f16a02d0000 nid=0x4fa3 runnable [0x00007f16b517d000..0x00007f16b517dbf0] java.lang.Thread.State: RUNNABLE at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method) at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:215) at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:65) at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:69) - locked <0x00007f17d5b68c00> (a sun.nio.ch.Util$1) - locked <0x00007f17d5b68be8> (a java.util.Collections$UnmodifiableSet) - locked <0x00007f1877959b50> (a sun.nio.ch.EPollSelectorImpl) at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:80) at org.apache.hadoop.net.SocketIOWithTimeout$SelectorPool.select(SocketIOWithTimeout.java:332) at org.apache.hadoop.net.SocketIOWithTimeout.doIO(SocketIOWithTimeout.java:157) at org.apache.hadoop.net.SocketInputStream.read(SocketInputStream.java:155) at org.apache.hadoop.net.SocketInputStream.read(SocketInputStream.java:128) at java.io.FilterInputStream.read(FilterInputStream.java:116) at org.apache.hadoop.ipc.Client$Connection$PingInputStream.read(Client.java:304) at java.io.BufferedInputStream.fill(BufferedInputStream.java:218) at java.io.BufferedInputStream.read(BufferedInputStream.java:237) - locked <0x00007f1808539178> (a java.io.BufferedInputStream) at java.io.DataInputStream.readInt(DataInputStream.java:370) at org.apache.hadoop.ipc.Client$Connection.receiveResponse(Client.java:569) at org.apache.hadoop.ipc.Client$Connection.run(Client.java:477)
這裏是一個RegionServer死了,master正在試着恢復。
"LeaseChecker" daemon prio=10 tid=0x00000000407ef800 nid=0x76cd waiting on condition [0x00007f6d0eae2000..0x00007f6d0eae2a70]-- java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Object.java:485) at org.apache.hadoop.ipc.Client.call(Client.java:726) - locked <0x00007f6d1cd28f80> (a org.apache.hadoop.ipc.Client$Call) at org.apache.hadoop.ipc.RPC$Invoker.invoke(RPC.java:220) at $Proxy1.recoverBlock(Unknown Source) at org.apache.hadoop.hdfs.DFSClient$DFSOutputStream.processDatanodeError(DFSClient.java:2636) at org.apache.hadoop.hdfs.DFSClient$DFSOutputStream. (DFSClient.java:2832) at org.apache.hadoop.hdfs.DFSClient.append(DFSClient.java:529) at org.apache.hadoop.hdfs.DistributedFileSystem.append(DistributedFileSystem.java:186) at org.apache.hadoop.fs.FileSystem.append(FileSystem.java:530) at org.apache.hadoop.hbase.util.FSUtils.recoverFileLease(FSUtils.java:619) at org.apache.hadoop.hbase.regionserver.wal.HLog.splitLog(HLog.java:1322) at org.apache.hadoop.hbase.regionserver.wal.HLog.splitLog(HLog.java:1210) at org.apache.hadoop.hbase.master.HMaster.splitLogAfterStartup(HMaster.java:648) at org.apache.hadoop.hbase.master.HMaster.joinCluster(HMaster.java:572) at org.apache.hadoop.hbase.master.HMaster.run(HMaster.java:503)
OpenTSDB是一個Ganglia的很好的替代品,由於他使用Hbase來存儲全部的時序而不須要採樣。使用OpenTSDB來監控你的Hbase是一個很好的實踐
這裏有一個例子,集羣正在同時進行上百個compaction,嚴重影響了IO性能。(TODO: 在這裏插入compactionQueueSize的圖片)(譯者注:囧)
給集羣構建一個圖表監控是一個很好的實踐。包括集羣和每臺機器。這樣就能夠快速定位到問題。例如,在StumbleUpon,每一個機器有一個圖表監控,包括OS和Hbase,涵蓋全部的重要的信息。你也能夠登陸到機器上,獲取更多的信息。
clusterssh+top,感受是一個窮人用的監控系統,可是他確實頗有效,當你只有幾臺機器的是,很好設置。啓動clusterssh後,你就會每臺機器有個終端,還有一個終端,你在這個終端的操做都會反應到其餘的每個終端上。 這就意味着,你在一天機器執行「top」,集羣中的全部機器都會給你所有的top信息。你還能夠這樣tail所有的log,等等。
當從客戶端到RegionServer的RPC請求超時。例如若是Scan.setCacheing的值設置爲500,RPC請求就要去獲取500行的數據,每500次.next()
操做獲取一次。由於數據是以大塊的形式傳到客戶端的,就可能形成超時。將這個 serCacheing的值調小是一個解決辦法,可是這個值要是設的過小就會影響性能。
由於LZO壓縮算法須要在集羣中的每臺機器都要安裝,這是一個啓動失敗的常見錯誤。若是你得到了以下信息
11/02/20 01:32:15 ERROR lzo.GPLNativeCodeLoader: Could not load native gpl libraryjava.lang.UnsatisfiedLinkError: no gplcompression in java.library.path at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1734) at java.lang.Runtime.loadLibrary0(Runtime.java:823) at java.lang.System.loadLibrary(System.java:1028)
就意味着你的壓縮庫出現了問題。參見配置章節的 LZO compression configuration.
參見快速入門的章節ulimit and nproc configuration.
這個時常會出如今DataNode的日誌中。
參見快速入門章節的 xceivers configuration.
參見快速入門章節的 ulimit and nproc configuration.
若是你收到了以下的消息
2009-02-24 10:01:33,516 WARN org.apache.hadoop.hbase.util.Sleeper: We slept xxx ms, ten times longer than scheduled: 100002009-02-24 10:01:33,516 WARN org.apache.hadoop.hbase.util.Sleeper: We slept xxx ms, ten times longer than scheduled: 150002009-02-24 10:01:36,472 WARN org.apache.hadoop.hbase.regionserver.HRegionServer: unable to report to master for xxx milliseconds - retrying
或者看到了全GC壓縮操做,你可能正在執行一個全GC。
這個錯誤有多是OS的文件句柄溢出,也多是網絡故障致使節點沒法訪問。
參見快速入門章節 ulimit and nproc configuration,檢查你的網絡。
Table of Contents
這裏咱們列舉一些Hbase管理,分析,修理和Debug的工具。
在Hbase集羣上運行 hbck
$ ./bin/hbase hbck
這個命令的輸出是 OK 或者 INCONSISTENCY. 若是你的集羣彙報inconsistencies,加上-details 看更多的詳細信息。若是inconsistencies,多運行hbck 幾回,由於inconsistencies多是暫時的。 (集羣正在啓動或者region正在split)。加上-fix能夠修復inconsistency(這是一個實驗性的功能)
HLog
工具HLog
的main方法提供了手動 切割和dump的方法。會把WALs或者splite的結果的內容保存在recovered.edits
目錄下
你能夠使用
$ ./bin/hbase org.apache.hadoop.hbase.regionserver.wal.HLog --dump hdfs://example.org:9000/hbase/.logs/example.org,60020,1283516293161/10.10.21.10%3A60020.1283973724012
來得到一個WAL文件內容的文本化的Dump。若是返回碼部位0,說明文件有錯誤,全部你能夠用這個命令來看文件是否健康,將命令重定向到/dev/null
,檢查返回碼就能夠了。
類似的,你能夠將一個log切割,運行以下命令:
$ ./bin/hbase org.apache.hadoop.hbase.regionserver.wal.HLog --split hdfs://example.org:9000/hbase/.logs/example.org,60020,1283516293161/
你能夠在Hbase的特定的節點上運行下面的腳原本中止RegionServer:
$ ./bin/hbase-daemon.sh stop regionserver
RegionServer會首先關閉全部的region而後把它本身關閉,在中止的過程當中,RegionServer的會向Zookeeper報告說他已通過期了。master會發現RegionServer已經死了,會把它看成崩潰的server來處理。他會將region分配到其餘的節點上去。
若是在運行load balancer的時候,一個節點要關閉, 則Load Balancer和Master的recovery可能會爭奪這個要下線的Regionserver。爲了不這個問題,先將load balancer中止,參見下面的 Load Balancer.
RegionServer下線有一個缺點就是其中的Region會有好一會離線。Regions是被按順序關閉的。若是一個server上有不少region,從第一個region會被下線,到最後一個region被關閉,而且Master確認他已經死了,該region才能夠上線,整個過程要花很長時間。在Hbase 0.90.2中,咱們加入了一個功能,可讓節點逐漸的擺脫他的負載,最後關閉。HBase 0.90.2加入了 graceful_stop.sh
腳本,能夠這樣用,
$ ./bin/graceful_stop.sh Usage: graceful_stop.sh [--config &conf-dir>] [--restart] [--reload] [--thrift] [--rest] &hostname> thrift If we should stop/start thrift before/after the hbase stop/start rest If we should stop/start rest before/after the hbase stop/start restart If we should restart after graceful stop reload Move offloaded regions back on to the stopped server debug Move offloaded regions back on to the stopped server hostname Hostname of server we are to stop
要下線一臺RegionServer能夠這樣作
$ ./bin/graceful_stop.sh HOSTNAME
這裏的HOSTNAME
是RegionServer的host you would decommission.
HOSTNAME
傳遞到graceful_stop.sh
的HOSTNAME
必須和hbase使用的hostname一致,hbase用它來區分RegionServers。能夠用master的UI來檢查RegionServers的id。一般是hostname,也多是FQDN。無論Hbase使用的哪個,你能夠將它傳到 graceful_stop.sh
腳本中去,目前他還不支持使用IP地址來推斷hostname。因此使用IP就會發現server不在運行,也沒有辦法下線了。
graceful_stop.sh
腳本會一個一個將region從RegionServer中移除出去,以減小改RegionServer的負載。他會先移除一個region,而後再將這個region安置到一個新的地方,再移除下一個,直到所有移除。最後graceful_stop.sh
腳本會讓RegionServer stop.,Master會注意到RegionServer已經下線了,這個時候全部的region已經從新部署好。RegionServer就能夠乾乾淨淨的結束,沒有WAL日誌須要分割。
當執行graceful_stop腳本的時候,要將Region Load Balancer關掉(不然balancer和下線腳本會在region部署的問題上存在衝突):
hbase(main):001:0> balance_switch falsetrue0 row(s) in 0.3590 seconds
上面是將balancer關掉,要想開啓:
hbase(main):001:0> balance_switch truefalse0 row(s) in 0.3590 seconds
你還可讓這個腳本重啓一個RegionServer,不改變上面的Region的位置。要想保留數據的位置,你能夠依次重啓(Rolling Restart),就像這樣:
$ for i in `cat conf/regionservers|sort`; do ./bin/graceful_stop.sh --restart --reload --debug $i; done &> /tmp/log.txt &
Tail /tmp/log.txt
來看腳本的運行過程.上面的腳本只對RegionServer進行操做。要確認load balancer已經關掉。還須要在以前更新master。下面是一段依次重啓的僞腳本,你能夠借鑑它:
確認你的版本,保證配置已經rsync到整個集羣中。若是版本是0.90.2,須要打上HBASE-3744 和 HBASE-3756兩個補丁。
運行hbck確保你的集羣是一致的
$ ./bin/hbase hbck
當發現不一致的時候,能夠修復他。
重啓Master:
$ ./bin/hbase-daemon.sh stop master; ./bin/hbase-daemon.sh start master
關閉region balancer:
$ echo "balance_switch false" | ./bin/hbase
在每一個RegionServer上運行graceful_stop.sh
:
$ for i in `cat conf/regionservers|sort`; do ./bin/graceful_stop.sh --restart --reload --debug $i; done &> /tmp/log.txt &
若是你在RegionServer還開起來thrift和rest server。還須要加上--thrift or --rest 選項 (參見 graceful_stop.sh
腳本的用法).
再次重啓Master.這會把已經死亡的server列表清空,從新開啓balancer.
運行 hbck 保證集羣是一直的
Table of Contents
HBase有一個用來測試壓縮新的工具。要想運行它,輸入/bin/hbase org.apache.hadoop.hbase.util.CompressionTest
. 就會有提示這個工具的具體用法
hbase.regionserver.codecs
若是你的安裝錯誤,就會測試不成功,或者沒法啓動。能夠在你的hbase-site.xml
加上配置 hbase.regionserver.codecs
值你須要的codecs。例如,若是 hbase.regionserver.codecs
的值是 lzo,gz
同時lzo不存在或者沒有正確安裝, RegionServer在啓動的時候會提示配置錯誤。
當一臺新機器加入到集羣中的時候,管理員必定要注意,這臺新機器有可能要安裝特定的壓縮解碼器。
參見上面的 Section 3.6.4, 「LZO 壓縮」
相對於LZO,GZIP的壓縮率更高可是速度更慢。在某些特定狀況下,壓縮率是優先考量的。Java會使用Java自帶的GZIP,除非Hadoop的本地庫在CLASSPATH中。在這種狀況下,最好使用本地壓縮器。(若是本地庫不存在,能夠在Log看到不少Got brand-new compressor。參見Q: )
C.1. 通常問題 |
|
Hbase還有其餘的FAQs嗎? |
|
能夠在Hbase的wiki HBase Wiki FAQ 和 Troubleshooting 看到更多的FAQ. |
|
HBase 支持 SQL嗎? |
|
不支持。能夠經過Hive的SQL-ish來支持,該功能還在開發中。可是Hive是基於MapReduce的,對於低延遲的應用並不適合。參見Chapter 11, 數據模型,能夠看到Hbase客戶端的例子。 |
|
HBase是如何工做在HDFS上的? |
|
HDFS是一個爲大文件設計的分佈式文件系統。他的文檔明確說了,它不是一個通用的文件系統,文件不支持快速的記錄查找。另外一方面,HBase是創建在HDFS之上,而且支持大表快速記錄查找(更新)。這有時候會混淆概念。參見Chapter 11, 數據模型 和 Chapter 12, 架構,來了解更多Hbase的目標。 |
|
爲何日誌的最後一行是'2011-01-10 12:40:48,407 INFO org.apache.hadoop.io.compress.CodecPool: Got brand-new compressor'? |
|
由於咱們沒有使用本地的壓縮類庫。參見 HBASE-1900 Put back native support when hadoop 0.21 is released.將Hadoop的本地類庫拷貝到Hbase下面(或者作軟連接)就能夠了 |
|
C.2. EC2 |
|
爲何個人鏈接EC2上的集羣的遠程Java鏈接不能工做? |
|
根據用戶列表,參見: Remote Java client connection into EC2 instance. |
|
C.3. 構建 HBase |
|
當我build的時候,爲何遇到 |
|
忽略他。這不是一個錯誤。這是officially ugly . |
|
C.4. Runtime |
|
爲何我在Hbase loading的是看到了停頓 |
|
若是啓用了壓縮,參見用戶列表 Long client pauses with compression. |
|
爲何個人RegionServer會忽然掛住? |
|
若是你使用了一個老式的JVM (< 1.6.0_u21?)?你能夠看看thread dump,是否是線程都BLOCKED可是沒有一個hold着鎖。參見 HBASE 3622 Deadlock in HBaseServer (JVM bug?). 在Hbase的 |
|
爲何我看到RegionServer的數量是實際的兩倍。一半使用域名,一半使用IP。 |
|
修正你的DNS。在Hbase 0.92.x以前的版本,反向DNS和正向DNS須要返回一致。參見 HBASE 3431 Regionserver is not using the name given it by the master; double entry in master listing of servers 得到詳細信息. |
|
C.5. 我如何在Hbase中創建 |
|
二級索引? |
|
對於在Hbase中維護一個二級索引的問題,有一個用戶的指導。參見David Butler在 HBase, mail # user - Stargate+hbase的信息。 |
TODO: YCSB不能不少的增長集羣負載.
TODO: 若是給Hbase安裝
Ted Dunning重作了YCSV,這個是用maven管理了,加入了覈實工做量的功能。參見 Ted Dunning's YCSB.