目錄
6.4. 修改conf/log4j.properties 6
6.5.1. hbase.master.info.port 8
6.5.2. hbase.master.info.bindAddress 8
6.5.3. hbase.hregion.majorcompaction 8
6.5.4. zookeeper.session.timeout 9
13.10. 是否可直接kill掉RegionServer進程? 26
13.12. RowKey和RegionServer不一致問題 27
2)Region&MemStore&StoreFile 31
3)JVM GC(Garbage Collection,垃圾回收) 34
本文將HBase-2.2.1安裝在Hadoop-3.1.2上,關於Hadoop-3.1.2的安裝,請參見《基於zookeeper-3.5.5安裝hadoop-3.1.2》一文。安裝環境爲64位CentOS-Linux 7.2版本。
本文將在HBase官方提供的quickstart.html文件的指導下進行,在docs/getting_started目錄下可找到quickstart.html,或直接瀏覽在線的:http://hbase.apache.org/book/quickstart.html。
安裝使用外置的ZooKeeper,有關ZooKeeper的安裝,請參見《基於zookeeper-3.5.5安裝hadoop-3.1.2》一文。
關於分佈式安裝,請瀏覽:http://hbase.apache.org/book/standalone_dist.html#distributed,關於HBase使用外置的ZooKeeper配置,請瀏覽:http://hbase.apache.org/book/zookeeper.html。所有在線的文檔,均會出現在二進制安裝包解壓後的docs目錄下。
縮寫 |
全寫 |
說明 |
JVM |
Java Virtual Matchine |
Java虛擬機 |
jps |
JVM Process Status |
Java虛擬機進程狀態工具 |
HDFS |
Hadoop Distributed File System |
Hadoop分佈式文件系統 |
HBase |
Hadoop Database |
Hadoop數據庫 |
WAL |
Write-Ahead Log |
預寫日誌,類似於MySQL的binlog |
RS |
Region Server |
|
zk |
Zookeeper |
|
mr |
Mapreduce |
|
rs |
RegionServer |
|
DistCp |
Distributed Copy |
分佈式複製 |
RFA |
RollingFileAppender |
Log4j的一種日誌器類型,文件大小到達指定大小時產生一個新的文件 |
DRFA |
DailyRollingFileAppender |
Log4j的一種日誌器類型,每天產生一個日誌文件 |
|
安裝用戶名 |
運行用戶名 |
安裝和運行用戶組名 |
HBase |
hbase |
hbase |
supergroup |
Hadoop |
hadoop |
hadoop |
|
Zookeeper |
zk |
zk |
Hadoop的默認用戶組名爲supergroup,爲避免一些權限問題,所以最好HBase也置於相同用戶組,以減少後續的麻煩。當然也可以在安裝Hadoop時,改變配置項dfs.permissions.supergroup值來設置用戶組,但不管如何,最好是同一用戶組。
一般建立HBase和Hadoop共享同一個Zookeeper集羣,所以獨立安裝部署Zookeeper集羣。
爲何Zookeeper的安裝運行用戶名爲zk,而不是zookeeper?這是因爲當用戶名超過8個字符時,ps等一些命令的結果將不顯示用戶名,替代的是用戶ID。
|
安裝目錄 |
HBase |
/data/hbase |
Hadoop |
/data/hadoop |
Zookeeper |
/data/zookeeper |
2888 |
ZooKeeper,如果是Leader,用來監聽Follower的連接 |
3888 |
ZooKeeper,用於Leader選舉 |
2181 |
ZooKeeper,用來監聽客戶端的連接 |
16010 |
hbase.master.info.port,HMaster的http端口 |
16000 |
hbase.master.port,HMaster的RPC端口 |
16030 |
hbase.regionserver.info.port,HRegionServer的http端口 |
16020 |
hbase.regionserver.port,HRegionServer的RPC端口 |
8080 |
hbase.rest.port,HBase REST server的端口 |
9095 |
hbase.thrift.info.port,HBase Thrift Server的http端口號 |
官網:http://hbase.apache.org/,在這裏即可找到下載HBase的鏈接。
下載國內映像站點:http://mirror.bit.edu.cn/apache/hbase/,HBase-2.2.1版本的下載網址:http://mirror.bit.edu.cn/apache/hbase/2.2.1/。選擇下載hbase-2.2.1-bin.tar.gz。
在一臺機器上修改好,再批量複製到集羣中的其它節點。使用批量命令工具mooon_ssh和批量上傳文件工具mooon_upload即可達到目的。
可選的,如果Master到RegionServers間沒有設置免密碼登錄,或者不會使用到start-hbase.sh和stop-hbase.sh,則可保留RegionServers文件爲空。
regionservers類似於Hadoop的slaves文件,不需要在RegionServer機器上執行些修改。
將所有HRegionServers的IP或主機名一行一行的例舉在在regionservers文件中,注意必須一行一個,不能一行多個。本文配置如下:
hadoop@test_64:~/hbase/conf> cat regionservers 192.168.31.30 192.168.31.31 192.168.31.32 |
需要在所有機器上做同樣的操作,可以藉助scp命令,先配置好一臺,然後複製過去,主要修改內容如下。
- 設置JAVA_HOME
# The java implementation to use. Java 1.6 required. export JAVA_HOME=/data/jdk |
上述/data/jdk是JDK的安裝目錄。
- 設置HADOOP_HOME
export HADOOP_HOME=/data/hadoop |
- 設置HBASE_CLASSPATH
# Extra Java CLASSPATH elements. Optional. export HBASE_CLASSPATH=$HADOOP_HOME/etc/hadoop |
這個設置是不是有點讓人迷惑?CLASSPATH怎麼指向了hadoop的conf目錄?這個設置是讓hbase能找到hadoop,名字確實沒取好。
除此之外,還可以考慮在hbase的conf目錄下建立hadoop的hdfs-site.xml軟鏈接。
- 設置HBASE_MANAGES_ZK
# Tell HBase whether it should manage it's own instance of Zookeeper or not. export HBASE_MANAGES_ZK=false |
如果HBASE_MANAGES_ZK值爲true,則表示使用HBase自帶的ZooKeeper,建議單獨部署ZooKeeper,這樣便於ZooKeeper同時爲其它系統提供服務。
- 設置JVM
JVM項 |
值 |
說明 |
HBASE_THRIFT_OPTS |
export HBASE_THRIFT_OPTS="$HBASE_THRIFT_OPTS -Xmx2048m -Xms2048m" |
HBase Thrift JVM設置,-Xmx指定最大堆佔用的內存,-Xms指定起始時分析的堆內存,如果物理內存爲32G,可以考慮設置爲2048m。 |
SERVER_GC_OPTS |
開始GC日誌 |
可用來分析線程的停頓時長等,有三處SERVER_GC_OPTS,只需要取消任意一註釋即可。 |
如果希望命令行執行“hbase shell”時不打屏INFO和WARN級別日誌,可修改hbase-env.sh中的“HBASE_ROOT_LOGGER”。
# HBASE_ROOT_LOGGER=INFO,DRFA HBASE_ROOT_LOGGER=OFF,DRFA |
hbase.log.dir=/data/hbase/log |
- 設置Cleaner的日誌級別:
log4j.logger.org.apache.hadoop.hbase.master.cleaner.CleanerChore=DEBUG |
hbase-site.xml是HBase的配置文件。默認的hbase-site.xml是空的,如下所示:
<?xml version="1.0"?> <?xml-stylesheet type="text/xsl" href="configuration.xsl"?> <!-- /** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ --> <configuration> </configuration> |
沒關係,就用它。不要用docs目錄下的hbase-default.xml,這個會讓你看得難受。
編輯hbase-site.xml,添加如下內容(摘自standalone_dist.html,搜索“Fully-distributed”):
<configuration> <property> <name>hbase.rootdir</name> <value>hdfs://hadoop10102:8020/hbase</value> <description>The directory shared by RegionServers.</description> </property>
<property> <name>hbase.cluster.distributed</name> <value>true</value> <description>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) </description> </property>
<property> <name>hbase.zookeeper.quorum</name> <value>hadoop10108,hadoop10109,hadoop10110,hadoop10111,hadoop10112</value> <description>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. </description> </property>
<property> <name>hbase.master.maxclockskew</name> <value>600000</value> <description>Time(ms) difference of regionserver from master</description> </property> </configuration> |
“hbase.zookeeper.quorum”可以填寫IP列表。hdfs://172.25.40.171:9001對應hdfs-site.xml中的“dfs.namenode.rpc-address”。“hbase.zookeeper.quorum”配置爲ZooKeeper集羣各節點主機名或IP。
如果HDFS是cluster模式,那麼建議hbase.rootdir請改成集羣方式,如:
<property> <name>hbase.rootdir</name> <value>hdfs://test/hbase</value> </property> |
即值爲hdfs-site.xml中的dfs.nameservices值,再加上hbase目錄。上述示例中的test,實際爲hdfs-site.xml中的dfs.nameservices的值,core-site.xml中的fs.defaultFS也用到了。
更多的信息,可以瀏覽:http://hbase.apache.org/book/config.files.html。
用於指定HMaster的http端口。
用於指定HMaster的http的IP地址,如果不設定該值,可能使用IPv6地址。
MajorCompaction間隔時間,單位爲毫秒,如果爲0表示手工執行MajorCompaction。HBase爲防止小文件過多,在必要時通過Compaction合併小文件,由兩類Compaction組成:一是MinorCompaction,二是MajorCompaction。
MajorCompaction對所有StoreFile進行合併操作,而MinorCompaction只對部分StoreFile進行合併。
默認值爲604800000毫秒,表示每7天執行一次MajorCompaction操作。MajorCompaction時性能影響十分嚴重,一般關閉自動MajorCompaction,而採取空閒時手工完成。
在HBase shell中手工MajorCompation:
major_compact 'tablename' |
或命令行中執行:
echo "tablename"|hbase shell |
major_compact使用方法:
Examples: Compact all regions in a table: // 合併整個表 hbase> major_compact 't1' hbase> major_compact 'ns1:t1' Compact an entire region: // 合併一個Region hbase> major_compact 'r1' Compact a single column family within a region: // 合併一個Region的一個列族 hbase> major_compact 'r1', 'c1' Compact a single column family within a table: // 合併一個表的一個列族 hbase> major_compact 't1', 'c1' |
默認爲90秒(90000ms),RegionServer和ZooKeeper間的超時時長。當達到超時時間後,RegionServer會被ZooKeeper從RegionServer集羣列表中清除,同時HBase Master會收到清除通知,然後HBase Master會對這臺RegionServer的Region做Balance,讓其它RegionServer接管,該參數決定了RegionServer在多長時間內可完成Failover。
參數名 |
默認值 |
說明 |
hbase.regionserver.thrift.port |
9090 |
ThriftServer的服務端口號 |
hbase.regionserver.thrift.http |
false |
是否爲HTTP模式。注意要麼是HTTP模式,要麼是非HTTP模式,不能同時是HTTP模式,又是其它模式。 |
hbase.thrift.ssl.enabled |
false |
ThriftServer是否啓用SSL |
hbase.master.hfilecleaner.ttl |
300000 |
單位爲毫秒,默認5分鐘,爲org.apache.hadoop.hbase.master.cleaner.CleanerChore所使用,僅源代碼文件StorefileRefresherChore.java和TimeToLiveHFileCleaner.java直接使用了hbase.master.hfilecleaner.ttl。如果使用ExportSnapshot集羣間遷移數據,則該值要比最大表的遷移時間長,否則遷移過程中已遷移的表文件可能被刪除,如果看到錯誤“Can't find hfile”,一般是這個原因,新版本將修復該BUG,此BUG由HBASE-21511引入。 |
hbase.cleaner.scan.dir.concurrent.size |
|
Cleaner線程數係數 |
hbase.hregion.majorcompaction |
604800000 |
單位爲毫秒,默認爲7天,Major Compact的週期,值爲0時表示關閉自動Major Compact |
hbase.hregion.majorcompaction.jetter |
0.2 |
防止RegionServer在同一時間進行Major Compact |
hbase.hstore.compactionThreshold |
3 |
Minor Compact的最少文件數 |
hbase.hstore.compaction.max |
10 |
表示一次Minor Compact中最多選取10個StoreFile |
hbase.hregion.max.filesize |
10737418240 |
默認爲10G,StoreFile達到此大小時分裂 |
hbase.hregion.memstore.flush.size |
134217728 |
單位爲字節,默認爲整128M,當一個MemStore達到該大小時,即Flush到HDFS生成HFile文件。 |
hbase.hregion.memstore.block.multiplier |
4 |
hbase-common /org/apache/hadoop/hbase/HConstants.java 係數值,當一個Region的大小達到(hbase.hregion.memstore.block.multiplier*hbase.hregion.memstore.flush.size)時,會阻塞該Region的寫操作,並強制Flush。在Flush成功後纔會恢復寫操作,這個時候可看到錯誤“RegionTooBusyException: Over memstore limit”。 |
hbase.regionserver.global.memstore.upperLimit(老) hbase.regionserver.global.memstore.size(新) |
0.4 |
hbase-server /org/apache/hadoop/hbase/io/util/MemorySizeUtil.java 浮點值,RegionServer全局memstore的大小。 當RegionServer的memstore超過這個比率,該RegionServer的所有update都會被阻塞,所以應當避免RegionServer出現memstore總大小超過upperLimit。 |
hbase.regionserver.global.memstore.lowerLimit(老) hbase.regionserver.global.memstore.size.lower.limit(新) |
0.95 |
hbase-server /org/apache/hadoop/hbase/io/util/MemorySizeUtil.java 浮點值,當RegionServer的memstore超過這個比率時,即使沒有Region達到Flush,MemstoreFlusher也會挑選一個Region去Flush。 |
hbase.hstore.compaction.kv.max |
10 |
Compact時每次從HFile中讀取的KV數 |
hbase.hstore.blockingStoreFiles |
10 |
當StoreFile文件數超過該值時,則在Flush前先進行Split或Compact,並阻塞Flush操作。直到完成或達到hbase.hstore.blockingWaitTime指定的時間後纔可以Flush。當RegionServer日誌大量出現“has too many store files; delaying flush up to”時表示需要調整該值,一般可以調大些,比如調成100。 |
hbase.hstore.blockingWaitTime |
90000 |
單位爲毫秒,默認爲90秒 |
hbase.hregion.memstore.mslab.enabled |
true |
MemStore-Local Allocation Buffer,是否開啓mslab,作用是減少因內存碎片導致的Full GC |
hbase.regionserver.regionSplitLimit |
1000 |
單臺RegionServer管理的最多Region個數 |
hbase.regionserver.logroll.period |
3600000 |
單位爲毫秒,默認爲1小時,WAL文件滾動時間間隔 |
hbase.server.thread.wakefrequency |
10000 |
定時檢查是否需要Compact,檢查週期爲:(hbase.server.thread.wakefrequency*hbase.server.compactchecker.interval.multiplier) |
hbase.server.compactchecker.interval.multiplier |
1000 |
定時檢查是否需要Compact,檢查週期爲:(hbase.server.thread.wakefrequency*hbase.server.compactchecker.interval.multiplier) |
hbase.thrift.info.port |
9095 |
信息WEB端口,如果值小於0,則不會開啓WEB |
hbase.thrift.info.bindAddress |
0.0.0.0 |
信息WEB地址,默認爲“0.0.0.0” |
hbase.regionserver.hlog.blocksize |
|
WALUtil.java 當WAL的大小達到 (hbase.regionserver.hlog.blocksize *hbase.regionserver.maxlogs)時,觸發Flush |
hbase.regionserver.maxlogs |
|
AbstractFSWAL.java |
hbase.regionserver.logroll.multiplier |
|
AbstractFSWAL.java 係數值,注意區分 hbase.hregion.memstore.block.multiplier |
停止Master,只需要將下列的start改成stop即可。
hbase-daemon.sh start master |
停止RegionServer,只需要將下列的start改成stop即可。
hbase-daemon.sh start regionserver |
HBase有兩個版本的ThriftServer,對應兩套不同的不兼容的接口實現:thrift和thrift2,其中thrift2是後加入的。從HBase2.X開始,兩個版本除接口不同,其它是共享的。
啓動ThriftServer使用如下語句,而停止ThriftServer只需將start改成stop即可。
hbase-daemon.sh start thrift2 --framed -nonblocking |
正式環境一般不要使用Java版本的“-nonblocking”模式,因爲它是單線程的。而應當使用“-hsha”或“-threadedselector”,推薦使用併發最強的“-threadedselector”模式。
有關“hbase thrift2”的參數,可執行“hbase thrift2 --help”查看到,“hbase thrift”也類似。
- Hsha模式
hbase-daemon.sh start thrift2 --framed -hsha --workers 30或 hbase-daemon.sh start thrift2 --framed -hsha -w 30或 hbase thrift2 --framed -hsha -w 30 |
注意,參數是“-hsha”,而不是“--hsha”,其中“-f”和“--framed”等價,“-w”和“--workers”等價。
- ThreadedSelector模式
hbase-daemon.sh start thrift2 --framed -threadedselector -s 10 -m 10 -w 50或 hbase thrift2 --framed -threadedselector -s 10 -m 10 -w 50 |
其中,-s”和“--selectors”等價,“-m”和“--minWorkers”等價。
- 錯誤“Cannot get replica 0 location for”
此錯誤表示有請求訪問了不存在的HBase表。
ERROR [thrift-worker-18] client.AsyncRequestFutureImpl: Cannot get replica 0 location for |
- 錯誤“ExecutorService rejected execution”
隊列大小偏小,啓動ThriftServer時指定隊列大小:“-q 10000”或“--queue -10000”。
WARN [Thread-16] server.TThreadedSelectorServer: ExecutorService rejected execution! java.util.concurrent.RejectedExecutionException: Task org.apache.thrift.server.Invocation@1642f20a rejected from org.apache.hadoop.hbase.thrift.THBaseThreadPoolExecutor@7cc22596[Running, pool size = 20, active threads = 20, queued tasks = 1000, completed tasks = 32792177] |
- 錯誤“RegionTooBusyException: Over memstore limit”
錯誤相關配置項:hbase.hregion.memstore.block.multiplier和hbase.hregion.memstore.flush.size,前者默認值爲4,後者默認值爲128MB。出錯此錯誤時,可考慮將hbase.hregion.memstore.block.multiplier調大爲8。
INFO [thrift-worker-2] client.RpcRetryingCallerImpl: RegionTooBusyException: Over memstore limit=512.0M, regionName=f146450279edde75342d003affa36be6, server=hadoop003,16020,1572244447374 at org.apache.hadoop.hbase.regionserver.HRegion.checkResources(HRegion.java:4421) at org.apache.hadoop.hbase.regionserver.HRegion.put(HRegion.java:3096) at org.apache.hadoop.hbase.regionserver.RSRpcServices.mutate(RSRpcServices.java:2877) |
- 錯誤“client.RpcRetryingCallerImpl: Exception: Over memstore limit”
錯誤相關配置項:hbase.hregion.memstore.block.multiplier和hbase.hregion.memstore.flush.size,前者默認值爲4,後者默認值爲128MB。
INFO [thrift-worker-24] client.RpcRetryingCallerImpl: Exception: Over memstore limit=512.0M, regionName=f80b7247cce17f3faac8731212ce43ba, server=hadoop003,16020,1572244447374 at org.apache.hadoop.hbase.regionserver.HRegion.checkResources(HRegion.java:4421) at org.apache.hadoop.hbase.regionserver.HRegion.put(HRegion.java:3096) at org.apache.hadoop.hbase.regionserver.RSRpcServices.mutate(RSRpcServices.java:2877) 。。。 , details=row '13871489517670268' on table 'test' at region=test,13628864449,1572513486889.f80b7247cce17f3faac8731212ce43ba., hostname=hadoop003,16020,1572244447374, seqNum=10634659, see https://s.apache.org/timeout |
默認端口號爲8080,可使用命令行參數“-p”或“--port”指定爲其它值。
bin/hbase-daemon.sh start rest -p 8080 |
簡單訪問示例(假設在10.143.136.232上啓動了HBase rest server):
- 查看HBase版本:
http://10.143.136.232:8080/version/cluster
- 查看集羣狀態
http://10.143.136.232:8080/status/cluster
- 列出所有非系統表
- 列出表test的所有regions
http://10.143.136.232:8080/test/regions
- 取rowkey爲100000797550117的整行數據(返回結果需要base64解密)
http://10.143.136.232:8080/test/100000797550117
- 取rowkey爲100000797550117,列族cf1下列field0列的數據(返回結果需要base64解密)
http://10.143.136.232:8080/test/100000797550117/cf1:field0
更多請瀏覽:
http://hbase.apache.org/book.html#_rest
Endpoint |
HTTP Verb |
說明 |
示例 |
/version/cluster |
GET |
查看HBase版本 |
curl -vi -X GET \ -H "Accept: text/xml" \ "http://example.com:8000/version/cluster" |
/status/cluster |
GET |
查看集羣狀態 |
curl -vi -X GET \ -H "Accept: text/xml" \ "http://example.com:8000/status/cluster" |
/ |
GET |
列出所有的非系統表 |
curl -vi -X GET \ -H "Accept: text/xml" \ "http://example.com:8000/" |
注:可瀏覽器中直接打開,如:http://10.143.136.232:8080/version/cluster。
Endpoint |
HTTP Verb |
說明 |
示例 |
/namespaces |
GET |
列出所有namespaces |
curl -vi -X GET \ -H "Accept: text/xml" \ "http://example.com:8000/namespaces/" |
/namespaces/namespace |
GET |
查看指定namespace的說明 |
curl -vi -X GET \ -H "Accept: text/xml" \ "http://example.com:8000/namespaces/special_ns" |
/namespaces/namespace |
POST |
創建一個新的namespace |
curl -vi -X POST \ -H "Accept: text/xml" \ "example.com:8000/namespaces/special_ns" |
/namespaces/namespace/tables |
GET |
列出指定namespace下的所有表 |
curl -vi -X GET \ -H "Accept: text/xml" \ "http://example.com:8000/namespaces/special_ns/tables" |
/namespaces/namespace |
PUT |
修改一個已存在的namespace |
curl -vi -X PUT \ -H "Accept: text/xml" \ "http://example.com:8000/namespaces/special_ns |
/namespaces/namespace |
DELETE |
刪除一個namespace,前提是該namespace已爲空 |
curl -vi -X DELETE \ -H "Accept: text/xml" \ "example.com:8000/namespaces/special_ns" |
注:斜體部分是需要輸入的。
Endpoint |
HTTP Verb |
說明 |
示例 |
/table/schema |
GET |
查看指定表的schema |
curl -vi -X GET \ -H "Accept: text/xml" \ "http://example.com:8000/users/schema" |
/table/schema |
POST |
使用schema創建一個新的表或修改已存在表的schema |
curl -vi -X POST \ -H "Accept: text/xml" \ -H "Content-Type: text/xml" \ -d '<?xml version="1.0" encoding="UTF-8"?><TableSchema name="users"><ColumnSchema name="cf" /></TableSchema>' \ "http://example.com:8000/users/schema" |
/table/schema |
PUT |
使用schema更新已存在的表 |
curl -vi -X PUT \ -H "Accept: text/xml" \ -H "Content-Type: text/xml" \ -d '<?xml version="1.0" encoding="UTF-8"?><TableSchema name="users"><ColumnSchema name="cf" KEEP_DELETED_CELLS="true" /></TableSchema>' \ "http://example.com:8000/users/schema" |
/table/schema |
DELETE |
刪除表 |
curl -vi -X DELETE \ -H "Accept: text/xml" \ "http://example.com:8000/users/schema" |
/table/regions |
GET |
列出表的所有regions |
curl -vi -X GET \ -H "Accept: text/xml" \ "http://example.com:8000/users/regions |
Endpoint |
HTTP Verb |
說明 |
示例 |
/table/row/column:qualifier/timestamp |
GET |
取指定表指定列族下指定列的指定時間戳的值,返回的值爲經過base64編碼的,因此使用時需要做base64解碼 |
curl -vi -X GET \ -H "Accept: text/xml" \ "http://example.com:8000/users/row1"
curl -vi -X GET \ -H "Accept: text/xml" \ "http://example.com:8000/users/row1/cf:a/1458586888395" |
/table/row/column:qualifier |
GET |
取指定表的指定列族下指定列的值 |
curl -vi -X GET \ -H "Accept: text/xml" \ "http://example.com:8000/users/row1/cf:a"
curl -vi -X GET \ -H "Accept: text/xml" \ "http://example.com:8000/users/row1/cf:a/" |
/table/row/column:qualifier/?v=number_of_versions |
GET |
取指定表的指定列族下指定列的指定版本值 |
curl -vi -X GET \ -H "Accept: text/xml" \ "http://example.com:8000/users/row1/cf:a?v=2" |
Endpoint |
HTTP Verb |
說明 |
示例 |
/table/scanner/ |
PUT |
創建一個scanner |
curl -vi -X PUT \ -H "Accept: text/xml" \ -H "Content-Type: text/xml" \ -d '<Scanner batch="1"/>' \ "http://example.com:8000/users/scanner/" |
/table/scanner/ |
PUT |
帶Filter創建一個scanner,過濾器可以寫在一個文本文件中,格式如: <Scanner batch="100"> <filter> { "type": "PrefixFilter", "value": "u123" } </filter> </Scanner> |
curl -vi -X PUT \ -H "Accept: text/xml" \ -H "Content-Type:text/xml" \ -d @filter.txt \ "http://example.com:8000/users/scanner/" |
/table/scanner/scanner-id |
GET |
取下一批數據,如果已無數據,則返回的HTTP代碼爲204 |
curl -vi -X GET \ -H "Accept: text/xml" \ "http://example.com:8000/users/scanner/145869072824375522207" |
table/scanner/scanner-id |
DELETE |
刪除指定的scanner,釋放資源 |
curl -vi -X DELETE \ -H "Accept: text/xml" \ "http://example.com:8000/users/scanner/145869072824375522207" |
Endpoint |
HTTP Verb |
說明 |
示例 |
/table/row_key |
PUT |
往指定表寫一行數據,注意行鍵、列族、列名和列值都必須採用base64編碼 |
curl -vi -X PUT \ -H "Accept: text/xml" \ -H "Content-Type: text/xml" \ -d '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><CellSet><Row key="cm93NQo="><Cell column="Y2Y6ZQo=">dmFsdWU1Cg==</Cell></Row></CellSet>' \ "http://example.com:8000/users/fakerow"
curl -vi -X PUT \ -H "Accept: text/json" \ -H "Content-Type: text/json" \ -d '{"Row":[{"key":"cm93NQo=", "Cell": [{"column":"Y2Y6ZQo=", "$":"dmFsdWU1Cg=="}]}]}'' \ "example.com:8000/users/fakerow" |
通過執行“hbase shell”進入命令行操作界面。詳細請瀏覽官方文檔:quickstart.html。
# 查看有哪些表 hbase(main):003:0> list
hbase(main):003:0> create 'test', 'cf' # 創建表test,一個列族cf 0 row(s) in 1.2200 seconds hbase(main):003:0> list 'test'
# 只看指定namespace下的表 list_namespace_tables 'default'
hbase(main):003:0> desc 'test' # 查看錶狀態
1 row(s) in 0.0550 seconds hbase(main):004:0> put 'test', 'row1', 'cf:a', 'value1' # 往表test的cf列族的a字段插入值value1 0 row(s) in 0.0560 seconds hbase(main):005:0> put 'test', 'row2', 'cf:b', 'value2' 0 row(s) in 0.0370 seconds hbase(main):006:0> put 'test', 'row3', 'cf:c', 'value3' 0 row(s) in 0.0450 seconds
hbase(main):007:0> scan 'test' # 掃描表test ROW COLUMN+CELL row1 column=cf:a, timestamp=1288380727188, value=value1 row2 column=cf:b, timestamp=1288380738440, value=value2 row3 column=cf:c, timestamp=1288380747365, value=value3 3 row(s) in 0.0590 seconds
# 帶條件scan hbase(main):007:0> scan 'test',{LIMIT=>1} hbase(main):007:0> scan 'test',{LIMIT=>1,STARTROW=>'0000'}
hbase(main):008:0> get 'test', 'row1' # 從表test取一行數據 COLUMN CELL cf:a timestamp=1288380727188, value=value1 1 row(s) in 0.0400 seconds
# 取某列的數據 get 'test', 'row1', 'cf1:col1' # 或者 get 'test', 'row1', {COLUMN=>'cf1:col1'}
語法: get <table>,<rowkey>,[<family:column>,....] scan <table>, {COLUMNS => [ <family:column>,.... ], LIMIT => num}
示例(在執行drop刪除一個表之前,需先使用disable禁止該表): scan 'ns1:t1', {COLUMNS => ['c1', 'c2'], LIMIT => 10, STARTROW => 20180906} hbase(main):012:0> disable 'test' 0 row(s) in 1.0930 seconds hbase(main):013:0> drop 'test' 0 row(s) in 0.0770 seconds
# 清空一個表 truncate 'test'
# 查錶行數用法1 count ‘test’
# 查錶行數用法2 count 'test',{INTERVAL=>10000}
# 刪除行中的某個列值 delete 't1','row1','cf1:col1'
# 刪除整行 deleteall 't1','row1'
# 退出hbase shell hbase(main):014:0> exit
# 預分區1:命令行指定EndKey create 'mytable','cf1',SPLITS=>['EndKey1','EndKey2','EndKey3']
# 預分區2:文件指定EndKey(mytable.splits文件每行一個EndKey) create 'mytable','cf1',SPLITS_FILE=>'mytable.splits'
# 對例族做Snappy壓縮 create 'mytable',{NAME=>'cf1',COMPRESSION=>'SNAPPY'},SPLITS=>['EndKey1','EndKey2','EndKey3']
# 分割策略分區 create 'mytable','cf1',{NUMREGIONS=>7,SPLITALGO=>'HexStringSplit'} |
查表行數第二種方法(非HBase shell命令,下列的test爲表名):
bin/hbase org.apache.hadoop.hbase.mapreduce.RowCounter 'test' |
- 查看命令的用法
hbase(main):007:0> help "count" # 查看count命令的用法 |
- 名字空間相關命令
hbase(main):007:0> create_namespace 'mynamespace' # 創建名字空間 hbase(main):007:0> delete_namespace 'mynamespace' # 刪除名字空間 hbase(main):007:0> list_namespace # 列出名字空間 |
- 別名方式
test=get_table "test" # 後續可以對象方式操作表"test" test.count # 統計表行數 test.scan # 掃描整張表 test.scan LIMIT=>1 # 有限掃描 t.scan LIMIT=>1,STARTROW=>"0" # 帶條件有限掃描 |
- import
以下命令均直接在HBase shell中運行,包括“import”部分:
import org.apache.hadoop.hbase.filter.SingleColumnValueFilter import org.apache.hadoop.hbase.filter.CompareFilter import org.apache.hadoop.hbase.util.Bytes # 包含所有列 scan 'test',{STARTROW =>'2016081100AA1600011516', STOPROW =>'2016081124ZZ1600011516',LIMIT=>2, FILTER=>SingleColumnValueFilter.new(Bytes.toBytes('cf1'),Bytes.toBytes('id'),CompareFilter::CompareOp.valueOf('EQUAL'),Bytes.toBytes('1299840901201608111600011516'))}
# 不包含過濾的列的其它所有列 import org.apache.hadoop.hbase.filter.SingleColumnValueExcludeFilter scan 'test',{STARTROW =>'2016081100AA1600011516', STOPROW =>'2016081124ZZ1600011516',LIMIT=>2, FILTER=>SingleColumnValueExcludeFilter.new(Bytes.toBytes('cf1'),Bytes.toBytes('id'),CompareFilter::CompareOp.valueOf('EQUAL'),Bytes.toBytes('1299840901201608111600011516'))}
# 預分區建表(splits是針對整個表的,而非某列族,因此獨立的{}) create 'test',{NAME => 'cf1', VERSIONS => 1},{SPLITS_FILE => 'splits.txt'} |
備HMaster可以有0到多個,配置和主HMaster完全相同,所以只需要複製一份已配置好的HMaster過去即可,然後同樣的命令啓動。啓動好後,一樣可以執行HBase shell命令。
爲啓用HBase的訪問控制,需在hbase-site.xml文件中增加如下兩個配置項:
<property> <name>hbase.coprocessor.master.classes</name> <value>org.apache.hadoop.hbase.security.access.AccessController</value> </property> <property> <name>hbase.coprocessor.region.classes</name> <value> org.apache.hadoop.hbase.security.token.TokenProvider,org.apache.hadoop.hbase.security.access.AccessController </value> </property> |
可以通過HBase shell進行權限管理,可以控制表(Table)和列族(Column Family)兩個級別的權限,superuser爲超級用戶:
grant <user> <permissions> <table> [ <column family> [ <column qualifier> ] ] |
permissions取值爲0或字母R、W、C和A的組合(R:read,W:write,C:create,A:admin)。
revoke <user> <table> [ <column family> [ <column qualifier> ] ] |
alter 'tablename', {OWNER => 'username'} |
查看用戶有哪些權限:user_permission <table>。
- HBase Web
- Master Web
- Region Web
查看Region的MemStore和StoreFile信息,可觀察到當MemStore的大小達到128M時即會Flush出新的StoreFile文件(以下test爲表名,包含一個列族cf1):
http://192.168.1.31:8080/region.jsp?name=72d8e0fec34a847d6e8c6ad62e6ec154
Region: test,196401049269744,1506394586723.72d8e0fec34a847d6e8c6ad62e6ec154. Column Family: cf1 Memstore size (MB): 48
Store Files
4 StoreFile(s) in set.
Store File Size (MB) Modification time hdfs://hadoop/hbase/data/default/test/72d8e0fec34a847d6e8c6ad62e6ec154/cf1/1d0a9744d1084de7b87629bad9459ac9 1041 Tue Sep 26 10:59:17 CST 2017 hdfs://hadoop/hbase/data/default/test/72d8e0fec34a847d6e8c6ad62e6ec154/cf1/56ab5f353fe94c15b183d4cf0880772a 206 Tue Sep 26 10:59:44 CST 2017 hdfs://hadoop/hbase/data/default/test/72d8e0fec34a847d6e8c6ad62e6ec154/cf1/a1b48379e66846a8b15bf42e830e0711 68 Tue Sep 26 10:59:52 CST 2017 hdfs://hadoop/hbase/data/default/test/72d8e0fec34a847d6e8c6ad62e6ec154/cf1/69595130c92c439ca939f366bcd2a843 68 Tue Sep 26 11:00:02 CST 2017 |
使用命令graceful_stop.sh,格式爲:
graceful_stop.sh --restart --reload --debug regionserver_hostname |
原理爲先move該RegionServer上所有的Region到其它RegionServer,然後再stop/restart該RegionServer。注意,該命令會關閉balancer,完成後再打開balancer:
Valid region move targets: hadoop-095,16020,1505315231353 hadoop-092,16020,1505315376659 hadoop-094,16020,1505389352958 hadoop-096,16020,1505459565691 [main] region_mover: Moving 60 region(s) from hadoop-091,16020,1505315285824 on 4 servers using 1 threads. thread-pool.rb:28] region_mover: Moving region ... (1 of 60) to ... for ... thread-pool.rb:28] region_mover: Moving region ... from ... to ... thread-pool.rb:28] region_mover: Moved region ... cost: 0.646 Reloaded hadoop-091 region(s) Restoring balancer state to true |
讓HMaster自動均衡和RegionServer間的Region數量命令(在HBase shell中執行,false爲關閉):
hbase(main):042:0> help "balance_switch" Enable/Disable balancer. Returns previous balancer state. Examples:
hbase> balance_switch true hbase> balance_switch false |
當重啓一個RegionServer後,會關閉balancer,命令“balance_switch true”返回上一次balance的狀態(true或false)。
當一個Region的大小超過hbase.hregion.max.filesize值(默認爲10GB)時,該Region會被自動分拆(Split)成兩個Region。
也可以主動分拆Region,主動分拆Region最簡單的方式是利用HBase web提供的Split功能,只需要輸入被分拆的Region Key即可,如要拆分名爲“test,03333333,1467613810867.38b8ef87bbf2f1715998911aafc8c7b3.”的Region,只需要輸入:test,03333333,1467613810867,然後點Split即可。
38b8ef87bbf2f1715998911aafc8c7b3爲Region的ENCODED名,是一個MD5值,即md5(test,03333333,1467613810867)的結果。
在hbase shell中操作爲:split 'regionName', 'splitKey'。進入HBase shell,直接執行split可以得到使用幫助:
hbase(main):041:0> help "split" Split entire table or pass a region to split individual region. With the second parameter, you can specify an explicit split key for the region. Examples: split 'TABLENAME' split 'REGIONNAME' split 'ENCODED_REGIONNAME' split 'TABLENAME', 'splitKey' split 'REGIONNAME', 'splitKey' split 'ENCODED_REGIONNAME', 'splitKey' |
-
- 合併Region
預分Region時,可能會產生一些過小或空的Region,這個時候可以考慮合併空的和過小的Region,HBase shell內置了合併region命令merge_region。
HBase shell通過調用lib/ruby目錄下的ruby腳本來完成許多命令,這些命令的腳本全用ruby編碼,均位於lib/ruby/shell/commands目錄下。不能直接運行lib/ruby/shell/commands目錄下的ruby腳本,它們只是各種功能的ruby模塊,需進入hbase shell環境後運行,文件名即爲命令名,不帶參數運行,可以得到用法,如:
hbase(main):039:0> help "merge_region" Merge two regions. Passing 'true' as the optional third parameter will force a merge ('force' merges regardless else merge will fail unless passed adjacent regions. 'force' is for expert use only).
You can pass the encoded region name or the full region name. The encoded region name is the hash suffix on region names: e.g. if the region name were TestTable,0094429456,1289497600452.527db22f95c8a9e0116f0cc13c680396. then the encoded region name portion is 527db22f95c8a9e0116f0cc13c680396
Examples:
hbase> merge_region 'FULL_REGIONNAME', 'FULL_REGIONNAME' hbase> merge_region 'FULL_REGIONNAME', 'FULL_REGIONNAME', true
hbase> merge_region 'ENCODED_REGIONNAME', 'ENCODED_REGIONNAME' hbase> merge_region 'ENCODED_REGIONNAME', 'ENCODED_REGIONNAME', true |
實際上,編碼的Region名ENCODED_REGIONNAME是一個MD5值。在線合併示例:
hbase(main):003:0> merge_region '000d96eef8380430d650c6936b9cef7d','b27a07c88dbbc070f716ee87fab15106' 0 row(s) in 0.0730 seconds |
hbase hfile -p -f /hbase/data/default/test/045ed11a1fdcd8bfa621f1160788a124/cf1/2502aeb799b84dda8340cdf4ad59e1f8
test是表名,045ed11a1fdcd8bfa621f1160788a124是Region name,2502aeb799b84dda8340cdf4ad59e1f8是hfile文件 |
運行輸出示例:
K: 471200000000798496948594841700001313/cf1:c1/1493957134206/Put/vlen=28/seqid=0 V: 1214271401201503056013176259 K: 471200000000798496948594841700001313/cf1:c2/1493957134206/Put/vlen=4/seqid=0 V: 110 K: 471200000000798496948594841700001313/cf1:c3/1493957134206/Put/vlen=3/seqid=0 V: ABC K: 471200000000798496948594841700001313/cf1:c4/1493957134206/Put/vlen=12/seqid=0 V: 16.12.57.1 K: 471200000000798496948594841700001313/cf1:c5/1493957134206/Put/vlen=28/seqid=0 V: 1214271401201503051700001313 K: 471200000000798496948594841700001313/cf1:c6/1493957134206/Put/vlen=0/seqid=0 V: K: 471200000000798496948594841700001313/cf1:c7/1493957134206/Put/vlen=19/seqid=0 V: 2015-09-05 12:05:15 K: 471200000000798496948594841700001313/cf1:c8/1493957134206/Put/vlen=3/seqid=0 V: bko |
當一個表的region在各RegionServer間分配不均的時候,可以做遷移,方法爲進入hbase的命令行界面,執行move命令遷移。
move命令的格式爲:
move '被遷region的ENCODED值','目標RegionServer全名' |
示例:
move 'bd118dd803bb4c8f8e28ea87ebec8335','hadoop-391,16020,1499860514933' |
在HMaster和RegionServer的Web界面均可看到RegionServer的全名。
使用hdfs命令,比如查看mytable這張表各region的大小,執行命令:
hdfs dfs -du hdfs:///hbase/data/default/mytable
即可看到各region大小,其中第一列爲region的大小:
306 hdfs:///hbase/data/default/mytable/.tabledesc 0 hdfs:///hbase/data/default/mytable/.tmp 2866280 hdfs:///hbase/data/default/mytable/023b0259adb715e3b4f6abecc1073ef3 2846541 hdfs:///hbase/data/default/mytable/2d2b9c6497e94a1f5227e9e4d26c4dc3 2911682 hdfs:///hbase/data/default/mytable/46e92458ce457ae69650013ca12e2415 2846062 hdfs:///hbase/data/default/mytable/6c1e8b29a5fc941434343dce11648e01 2846135 hdfs:///hbase/data/default/mytable/6c86670d1d3a2b23d9eee836efb959ca 2875079 hdfs:///hbase/data/default/mytable/7ee492fbc245a34a075e961f75e20f85 2846527 hdfs:///hbase/data/default/mytable/8b41e528bd529b123c9ce8d66816a21b 2846194 hdfs:///hbase/data/default/mytable/913f32ee373d382be3062562b87367fe 2846291 hdfs:///hbase/data/default/mytable/b9a1ef3d48f3fa45637473ae82d258c1 2912207 hdfs:///hbase/data/default/mytable/b9f3d37ce1c7a73035a517decde7ffec 2846121 hdfs:///hbase/data/default/mytable/bd118dd803bb4c8f8e28ea87ebec8335 2912197 hdfs:///hbase/data/default/mytable/c2c25cdc9376377c96b9d45768c7d793 2846253 hdfs:///hbase/data/default/mytable/c9e1362c88aeae241a5737989d2c8bf8 2911869 hdfs:///hbase/data/default/mytable/cf4f2bda053820b56db112929e077b74 2913065 hdfs:///hbase/data/default/mytable/e6ed2d434d3e0b8b59f859fdcb615a80 2912094 hdfs:///hbase/data/default/mytable/fec9c2376b0c3466c6f872aef3c3177d |
HBase WAL類似於MySQL的binlog,WAL工具位於庫文件hbase-server-X.Y.Z.jar中,導出和分拆WAL,執行方式:
$ hbase org.apache.hadoop.hbase.regionserver.wal.FSHLog Usage: FSHLog <ARGS> Arguments: --dump Dump textual representation of passed one or more files For example: FSHLog --dump hdfs://example.com:9000/hbase/.logs/MACHINE/LOGFILE --split Split the passed directory of WAL logs For example: FSHLog --split hdfs://example.com:9000/hbase/.logs/DIR |
示例:
$ hbase org.apache.hadoop.hbase.regionserver.wal.FSHLog --dump hdfs:///hbase/WALs/hadoop-203,16020,1493809707539/hadoop-203%2C16020%2C1493809707539.1506389208593 Writer Classes: ProtobufLogWriter Cell Codec Class: org.apache.hadoop.hbase.regionserver.wal.WALCellCodec Sequence=117 , region=f9c1b75be5fcb024a9cf74c47affb52e at write timestamp=Tue Sep 26 09:32:34 CST 2017 row=g-FMZffo5E36_sJCNx2BS4jJorpo-616451068748770146, column=cf1:js row=g-FMZffo5E36_sJCNx2BS4jJorpo-616451068748770146, column=cf1:lsud row=g-FMZffo5E36_sJCNx2BS4jJorpo-616451068748770146, column=cf1:at row=g-FMZffo5E36_sJCNx2BS4jJorpo-616451068748770146, column=cf1:rat Sequence=118 , region=f9c1b75be5fcb024a9cf74c47affb52e at write timestamp=Tue Sep 26 09:32:44 CST 2017 row=g-FMZffo5E36_sJCNx2BS4jJorpo-616451068748770160, column=cf1:js row=g-FMZffo5E36_sJCNx2BS4jJorpo-616451068748770160, column=cf1:lsud row=g-FMZffo5E36_sJCNx2BS4jJorpo-616451068748770160, column=cf1:at row=g-FMZffo5E36_sJCNx2BS4jJorpo-616451068748770160, column=cf1:rat Sequence=119 , region=f9c1b75be5fcb024a9cf74c47affb52e at write timestamp=Tue Sep 26 09:32:51 CST 2017 row=g-FMZffo5E36_sJCNx2BS4jJorpo-616451068748767888, column=cf1:js row=g-FMZffo5E36_sJCNx2BS4jJorpo-616451068748767888, column=cf1:lsud row=g-FMZffo5E36_sJCNx2BS4jJorpo-616451068748767888, column=cf1:at row=g-FMZffo5E36_sJCNx2BS4jJorpo-616451068748767888, column=cf1:rat |
如果同時做Split和Compact,建議先Compact後Split。Compact的目的是將一個Region下的所有StoreFile合併成一個StoreFile文件。
之後再對超過指定大小的Region進行Split操作,可修改參數hbase.hstore.compactionThreshold減少Compact頻率,通過設置較大的hbase.hregion.majorcompaction降低Major Compact頻率。
Major Compact操作方式:
hbase(main):001:0> major_compact
ERROR: wrong number of arguments (0 for 1)
Here is some help for this command: Run major compaction on passed table or pass a region row to major compact an individual region. To compact a single column family within a region specify the region name followed by the column family name. Examples: Compact all regions in a table: hbase> major_compact 't1' hbase> major_compact 'ns1:t1' Compact an entire region: hbase> major_compact 'r1' Compact a single column family within a region: hbase> major_compact 'r1', 'c1' Compact a single column family within a table: hbase> major_compact 't1', 'c1' |
- 示例1:合併表ID爲a6e65f0540bfcd1cb2740bb4b033d134的Region的列族cf2
hbase(main):003:0> major_compact 'a6e65f0540bfcd1cb2740bb4b033d134','cf2' 0 row(s) in 0.1990 seconds |
如果直接kill掉RegionServer進程,而不是通過graceful_stop.sh優雅退出,則只有經歷zookeeper.session.timeout指定的毫秒時間後,HMaster纔會將該RegionServer上的Region遷移至其它的RegionServer上。
可以簡單理解zookeeper.session.timeout爲RegionServer和HMaster間的心跳超時時間,但實際上兩者並不直接聯繫,而是通過ZooKeeper節點方式HMaster感知RegionServer超時。
實際上kill掉後立即重新啓動RegionServer,也是可以的。
在需要下線的RegionServer上執行graceful_stop.sh,停止RegionServer。在下線時,HBase會關閉Load Balance,因此在下線完成後需要進入HBase shell執行下:balance_switch true。
如果出現ROWKEY和RegionServer不一致,可以使用“hbase hbck -repair”進行修復,如果有空洞,使用“hbase hbck -repairHoles”。
快照方式支持跨版本遷移數據,比如源HBase集羣版本爲“Hadoop-2.7.3 + HBase-1.2.6”,目標HBase集羣版本爲“Hadoop-3.1.2 + HBase-2.2.1”。
以將HBase表test從集羣192.168.31.30遷移到192.168.32.30爲例。數據遷移除了採用快照方式下,還可以使用HBase層面的copyTable和export/import,以及HDFS層面的distcp。其中,export/import和copyTable兩種支持指定時間範圍的部分複製。
不帶參數執行,可得到相應的幫助,如:
hbase org.apache.hadoop.hbase.mapreduce.Export hbase org.apache.hadoop.hbase.mapreduce.Import hbase org.apache.hadoop.hbase.mapreduce.CopyTable hadoop distcp |
這一步在源集羣的HBase shell中完成,其中“test”爲表名,“test.snapshot”爲快照名。
snapshot 'test','test.snapshot' |
這一步直接在Linux shell中操作,可在目標集羣機器上操作,也可在源集羣機器上操作,建議在目標集羣上實施,遷移實際是一個MR過程(只有Map,沒有Reduce)。執行時,注意通過參數bandwidth控制好流量,遷移時流量會很大。
hbase org.apache.hadoop.hbase.snapshot.ExportSnapshot -snapshot test.snapshot -copy-from hdfs://192.168.31.30/hbase -copy-to hdfs://192.168.32.30/hbase -mappers 10 -bandwidth 50 |
注意一定要設置bandwidth參數,以控制遷移時的流量,通常流量會很大的,能夠喫滿萬兆網卡,如果不加以控制。還可指定遷移後文件在目標集羣中的Owner:
hbase org.apache.hadoop.hbase.snapshot.ExportSnapshot -overwrite -snapshot test.snapshot -copy-from hdfs://192.168.31.30/hbase -copy-to hdfs://192.168.32.30/hbase -mappers 10 -bandwidth 30 -chuser hbase -chgroup supergroup |
另外,還可以加上參數“-overwrite”:
hbase org.apache.hadoop.hbase.snapshot.ExportSnapshot -overwrite -snapshot test.snapshot -copy-from hdfs://192.168.31.30/hbase -copy-to hdfs://192.168.32.30/hbase -mappers 10 -bandwidth 50 |
在遷移過程中,如果遇到錯誤“Can't find hfile”,則應當將hbase.master.hfilecleaner.ttl的值調大,至少要比遷移時長大的值。
如果執行ExportSnapshot時報錯“Operation category READ is not supported in state standby”,表示ExportSnapshot的參數“-copy-to”指向了備NameNode,改成指向主NameNode後再執行。
根據快照名恢復快照,這一步在目標集羣的HBase shell中完成。
restore_snapshot ‘test.snapshot’ |
使用restore_snapshot的前提是表已被disable,否則需改用bulkload方式恢復快照。
hbase \ org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles \ -Dhbase.mapreduce.bulkload.max.hfiles.perRegion.perFamily=1024 \ hdfs://192.168.31.30/hbase/archive/datapath/tablename/filename \ tablename |
參數hbase.mapreduce.bulkload.max.hfiles.perRegion.perFamily指定在Load過程中每個Region下每個列族的hfile文件數上限,默認爲32。
BulkLoad是一個個文件逐個導入,所以處理起來要麻煩許多。BulkLoad時,可以考慮設置hbase.client.bulk.load.validate.hfile.format值爲false來加快Load效率。
delete_snapshot ‘test.snapshot’ |
list_snapshots |
附1:元數據
HBase在zookeeper上的目錄結構:
[zk: localhost:2181(CONNECTED) 0] ls /hbase [backup-masters, draining, flush-table-proc, hbaseid, master, master-maintenance, meta-region-server, namespace, online-snapshot, replication, rs, running, splitWAL, switch, table, table-lock] |
從0.96版本開始root-region-server被meta-region-server替代,原來的root被刪除了,新的meta像原來的root一樣,只有一個Region,不再會有多個Region。
從0.96版本開始引入了namespace,刪除了-ROOT-表,之前的.META.表被hbase:meta表替代,其中hbase爲namespace名。namespace可以認爲類似於MySQL中的DB名,用於對錶進行邏輯分組管理。
客戶端對hbase提供DML操作不需要訪問master,但DDL操作依賴master,在hbase shell中的list也依賴於master。
在主hbase master的web上,可以看到有三個系統表:hbase:meta、hbase:namespace和hbase:acl(如果沒開啓ACL,則無此表),注意hbase:namespace和hbase:acl的元數據也存儲在hbase:meta中,這可以通過在hbase shell中執行scan 'hbase:meta'觀察到。
hbase(main):015:0* scan 'hbase:meta',{LIMIT=>10} hbase:acl,,1460426731436.0bbdf170c309223c0ce830 column=info:regioninfo, timestamp=1460426830411, value={ENCODED => 0bbdf170c309223c0ce830facdff9edd, NAME => 'hbase:acl,,1460426731436.0bbdf facdff9edd. 170c309223c0ce830facdff9edd.', STARTKEY => '', ENDKEY => ''} hbase:acl,,1460426731436.0bbdf170c309223c0ce830 column=info:seqnumDuringOpen, timestamp=1461653766642, value=\x00\x00\x00\x00\x00\x00\x002 facdff9edd. hbase:acl,,1460426731436.0bbdf170c309223c0ce830 column=info:server, timestamp=1461653766642, value=hadoop-034:16020 facdff9edd. hbase:acl,,1460426731436.0bbdf170c309223c0ce830 column=info:serverstartcode, timestamp=1461653766642, value=1461653610096 |
第一列,即紅色串爲Region name;serverstartcode爲Regsion server加載region的時間;server爲Region server的IP和端口;regioninfo結構爲:
- ENCODED 爲Region name的MD5值
- NAME 爲Region name
- STARTKEY 爲空表示爲第一個Region
- ENDKEY 如果也爲空,則表示該表只有一個Region。
附2:基本概念
1)HBase和HDFS
HBase的表數據存儲在HDFS上,假設有一HBase表test,它的namespace爲abc(默認的namespace名爲default),則該表的HDFS路徑爲:hdfs:///hbase/data/abc/test,表名目錄之下爲各Regions的子目錄,每個Region均一個獨立的子目錄,如:
$ hdfs dfs -ls hdfs:///hbase/data/abc/test/ Found 7 items drwxr-xr-x - hadoop supergroup 0 2017-07-19 17:45 hdfs:///hbase/data/abc/test/.tabledesc drwxr-xr-x - hadoop supergroup 0 2017-07-19 17:45 hdfs:///hbase/data/abc/test/.tmp drwxr-xr-x - hadoop supergroup 0 2019-05-30 16:07 hdfs:///hbase/data/abc/test/37b03ca897147840c3676bb7d622af2f drwxr-xr-x - hadoop supergroup 0 2019-05-30 16:07 hdfs:///hbase/data/abc/test/8e52bcdc2b1292fabf6bc8ea8e8be8ba drwxr-xr-x - hadoop supergroup 0 2019-09-07 09:36 hdfs:///hbase/data/abc/test/ba6fa3def428d0d5e53a17d30c5fa7de drwxr-xr-x - hadoop supergroup 0 2019-09-07 09:36 hdfs:///hbase/data/abc/test/cdf6d4ff4dc0b6cf1c23e1db133dbfe1 drwxr-xr-x - hadoop supergroup 0 2018-04-17 23:05 hdfs:///hbase/data/abc/test/fb3b4847d6cf504aea3990859e2b8092 |
在Region目錄下,爲各列族的子目錄,每個列族均一個獨立的子目錄:
$ hdfs dfs -ls hdfs:///hbase/data/abc/test/fb3b4847d6cf504aea3990859e2b8092 Found 4 items -rw-r--r-- 3 hadoop supergroup 99 2018-04-17 23:05 hdfs:///hbase/data/abc/test/fb3b4847d6cf504aea3990859e2b8092/.regioninfo drwxr-xr-x - hadoop supergroup 0 2018-04-17 23:06 hdfs:///hbase/data/abc/test/fb3b4847d6cf504aea3990859e2b8092/.tmp drwxr-xr-x - hadoop supergroup 0 2018-04-17 23:06 hdfs:///hbase/data/abc/test/fb3b4847d6cf504aea3990859e2b8092/cf1 drwxr-xr-x - hadoop supergroup 0 2019-10-15 10:56 hdfs:///hbase/data/abc/test/fb3b4847d6cf504aea3990859e2b8092/recovered.edits |
從上不難發現,可很方便的查看一個表的大小或者Region的大小,只需使用命令“hdfs dfs -du”即可,比如:
$ hdfs dfs -du -h hdfs:///hbase/data/abc/ 4.7 G hdfs:///hbase/data/abc/test
$ hdfs dfs -du -h hdfs:///hbase/data/abc/test 287 hdfs:///hbase/data/abc/test/.tabledesc 0 hdfs:///hbase/data/abc/test/.tmp 167.1 M hdfs:///hbase/data/abc/test/37b03ca897147840c3676bb7d622af2f 137.3 M hdfs:///hbase/data/abc/test/8e52bcdc2b1292fabf6bc8ea8e8be8ba 2.6 G hdfs:///hbase/data/abc/test/ba6fa3def428d0d5e53a17d30c5fa7de 870.1 M hdfs:///hbase/data/abc/test/cdf6d4ff4dc0b6cf1c23e1db133dbfe1 1000.0 M hdfs:///hbase/data/abc/test/fb3b4847d6cf504aea3990859e2b8092 |
2)Region&MemStore&StoreFile
HBase的負載均衡單位爲Region,RegionServer負責操作Region,如加載Region到內存,提供讀寫、分拆和合並等。一個Region同一時刻只會被一個RegionServer操作,可以通過move命令在不同RegionServer間遷移。
一個Region由一個或多個Store組成,每個Store存儲一個列族(Column Family)。每個Store又由一個MemStore和0或多個StoreFile組成,其中StoreFile存儲在HDFS上(即HFile文件),MemStore存儲在內存中(可通過WAL日誌文件重放恢復MemStore)。
MemStore被Flush到HDFS即生成新的StoreFile,當StoreFile達到一定數量時觸發合併(Compact),Major Compact將所有的StoreFile合併成一個StoreFile文件。
如果沒有開啓WAL日誌(Write Ahead Log,類似於MySQL的binlog),則在MemSotre被Flush之前發生故障,會丟失MemStore部分數據。
Major Compact的作用是將一個Region同一列族下的所有StoreFile合併成一個大的StoreFile。不同列族對應不同StoreFile文件,如果只有一個列族則合併後只有一個StoreFile,如果有兩個列族則合併後有兩個StoreFile,依次類推。
3)StoreFile文件
可通過RegionServer的Web查看,如:
http://192.168.1.31:8080/region.jsp?name=78d2bddb0fdc2c735c79da68658f3011 |
假設Hadoop集羣名爲hadoop,表名爲test,Region ID爲78d2bddb0fdc2c735c79da68658f3011則StoreFile文件路徑可能類似如下:
hdfs://hadoop/hbase/data/default/test/78d2bddb0fdc2c735c79da68658f3011/cf1/4facea216b15471e9d6d85cf59bd9d8a hdfs://hadoop/hbase/data/default/test/78d2bddb0fdc2c735c79da68658f3011/cf1/404aea6371cb4722af91a07c10a3fcf3 |
可通過“hdfs dfs -ls”取得StoreFile文件大小,如:
$ hdfs dfs -ls hdfs://hadoop/hbase/data/default/test/78d2bddb0fdc2c735c79da68658f3011/cf1/4facea216b15471e9d6d85cf59bd9d8a -rw-r--r-- 3 zhangsan supergroup 6283978864 2017-09-24 12:47 hdfs://hadoop/hbase/data/default/test/78d2bddb0fdc2c735c79da68658f3011/cf1/4facea216b15471e9d6d85cf59bd9d8a |
4)Region name
Region name用來標識一個Region,它的格式爲:表名,StartKey,隨機生成的RegionID,如:
test,83--G40V6UdCnEHKSKqR_yjJo798594847946710200000795,1461323021820.d4cc7afbc2d6bf3843c121fedf4d696d. |
上述test爲表名,中間藍色串爲Startkey,最後紅色部分爲Region ID(注意包含了2個點號)。如果爲第一個Region,則StartKey爲空,比如變成這樣:
t_user,,1461549916081.f4e17b0d99f2d77da44ccb184812c345. |
附3:crontab監控腳本
使用這種方法,不需要在Master和Slaves節點間建立免密碼登錄關係,因爲相關進程由crontab拉起,並不需要顯示調用start-all.sh、start-dfs.sh、start-yarn.sh、start-hbase.sh等。
監控工具下載:
https://github.com/eyjian/libmooon/blob/master/shell/process_monitor.sh
監控工具使用示例:
PMONITOR=/usr/local/bin/process_monitor.sh JAVA=/usr/local/jdk/bin/java HBASE_DAEMON=/data/hbase/bin/hbase-daemon.sh
# 監控HBase Master(僅在 Master 上啓動) #* * * * * $PMONITOR "$JAVA -Dproc_master" "$HBASE_DAEMON start master"
# 監控HBase RegionServer(僅在 RegionServer 上啓動) #* * * * * $PMONITOR "$JAVA -Dproc_regionserver" "$HBASE_DAEMON start regionserver"
# 監控HBase ThriftServer2(一般和 RegionServer 共享相同機器) #* * * * * $PMONITOR "$JAVA -Dproc_thrift2" "$HBASE_DAEMON start thrift2 --framed -threadedselector -s 10 -m 20 -w 20"
# 監控HBase RESTServer(一般和 RegionServer 共享相同機器) #* * * * * $PMONITOR "$JAVA -Dproc_rest" "$HBASE_DAEMON start rest -p 8080" |
附4:批量操作工具
批量操作工具下載:
https://github.com/eyjian/libmooon/releases
其中,mooon_ssh爲批量命令工具,mooon_upload爲批量上傳文件工具。
批量操作工具使用示例:
# 設置環境變量 export H='192.168.1.21,192.168.1.22,192.168.1.23,192.168.1.24,192.168.1.25,192.168.1.26' export U=root export P=password export PORT=201810
# 上傳/etc/hosts和/etc/profile到:192.168.31.12,192.168.31.13,192.168.31.14,192.168.31.15 mooon_upload -s=/etc/hosts,/etc/profile -d=/etc
# 檢查/etc/profile文件是否一致 mooon_ssh -c='md5sum /etc/hosts' |
附5:JVM基礎知識
1)JPS命令
當執行jps命令時,如果看不到運行中的Java進程。假設用戶名爲test,則檢查目錄/tmp/hsperfdata_test的Owner和權限是否正確,如果權限不正確,則jps將看不到運行中的Java進程。
2)JVM內存
JVM內存由3部分組成:
|
作用 |
說明 |
新生代(Young) |
存活時間較短,一般存儲剛生成的一些對象 |
又分爲一個伊甸園(Eden)區,和兩個Survivor區,兩個Survivor區總有一個是空的。對新生代的垃圾回收叫做Minor GC,特點是次數頻繁,但每次回收時間較短。 對象在Survivor每經歷一次Minor GC,年齡就增長1歲,默認增長到15歲時就晉升到Old代。 |
老年代(Tenured) |
也叫舊生成(Old),存活時間較長,主要存儲在應用程序中生命週期較長的對象 |
對象優先在Eden上分配,但大對象直接在Old上分配。對老年代的垃圾回收叫做MajorGC或Full GC,特點是次數相對少,每次回收時間較長。 |
永久代(Perm) |
存儲meta和class的信息,JDK8已刪除永久代 |
永久代垃圾回收比較少,效率也比較低。因爲在JDK8中已無永久代,所以JVM參數“-XX:PermSize”和 “-XX:MaxPermSize”已作廢,代替的參數分別爲“-XX:MetaspaceSiz”和“-XX:MaxMetaspaceSize”。 |
3)JVM GC(Garbage Collection,垃圾回收)
當Eden空間不足時,即觸發Minor GC。Full GC的觸發條件爲:Old空間不足;Perm空間不足;統計得到的Minor GC晉升到Old的平均大小大於Old的剩餘空間。
回收策略 |
|
|
Serial |
串行收集器 |
串行單線程處理所有垃圾回收工作,適合小數據量的回收,使用“-XX:+UseSerialGC”打開。 |
Parrallel New Collector |
並行收集器 |
Serial的多線程版本,並行多線程處理,使用“-XX:+UseParallelOldGC”打開,用“-XX:ParallelGCThreads=<N>”指定垃圾回收線程數。 |
CMS(Concurrent Mark Sweep) |
併發收集器,響應時間優先回收器 |
併發多線程處理,使用“-XX:+UseConcMarkSweepGC”打開,只針對老年代。 |
4)並行和併發
並行 |
Parallel |
多條垃圾收集線程並行工作,應用線程處於等待狀態 |
併發 |
Concurrent |
垃圾收集線程與應用線程一段時間內同時工作,不是並行而是交替執行 |
5)JVM的CMS垃圾回收
CMS(Concurrent Mark Sweep)是一個併發使用標記的GC,以犧牲CPU吞吐量爲代價獲得最短回收停頓時間的垃圾回收器。
CMS不對堆(Heap)進行整理和壓縮,節約了垃圾回收停頓時間,但產生了空間碎片,增加了堆空間的浪費。
CMS雖然是老生代的GC,但仍然需要掃描新生代。
啓用方式:JVM參數加上“XX:+UseConcMarkSweepGC”,這個參數表示對於老年代的回收採用CMS,CMS採用“標記—清除”算法。
CMS分成以下幾個過程:
- 初始標記(STW initial mark)
需暫停JVM,官方的叫法STW(Stop The Word),這個過程雖然暫停了JVM,但很快完成。這個過程只標記GC ROOT可直接關聯的對象,不包括間接關聯的對象。
- 併發標記(Concurrent marking)
無停頓,應用程序的線程和併發標記的線程併發執行,本過程標記所有可達對象,通過GC ROOT TRACING可達到的對象是活着的對象。
- 併發預清理(Concurrent precleaning)
無停頓,這個過程也是併發的。
- 重新標記(STW remark)
這個過程也會暫停JVM,重新掃描堆中的對象,標記活着的對象,包含子過程Rescan。
- 併發清理(Concurrent sweeping)
無停頓,應用程序線程和收集器線程併發執行。
- 併發重置(Concurrent reset)
無停頓,重置CMS收集器的數據結構,等待下一次垃圾回收。
6)JVM內存參數
執行命令“java -X”可看到相關參數的說明,不同版本的JDK默認值不一定相同,可執行命令“java -XX:+PrintFlagsFinal -version | grep HeapSize”查看默認值。
參數名 |
參數說明 |
示例 |
-Xms |
初始Java堆大小,JVM啓動時分配的內存 |
-Xms256m |
-Xmx |
最大Java堆大小,運行時可分配的最大內存 |
-Xmx2048m |
-Xss |
Java線程堆棧大小,每個線程分配的內存大小 |
-Xss128m |
|
||
-XX:OnOutOfMemoryError |
內存溢出時的動作 |
-XX:OnOutOfMemoryError='kill -9 %p' |
-XX:+UseConcMarkSweepGC |
設置併發垃圾收集器 |
-XX:+UseConcMarkSweepGC |
-XX:+UseParallelGC |
設置並行垃圾收集器,同時運行在多CPU上,獨佔式收集器(收集過程中進程暫停STW),不能與CMS收集器一起。使用這個參數,新生代爲並行回收,老年代爲串行回收。 |
-XX:+UseParallelGC |
-XX:+UseSerialGC |
設置串行垃圾收集器,也是獨佔式收集器。使用這個參數,新生代和老年代都爲串行回收。 |
-XX:+UseSerialGC |
-XX:+UseParNewGC |
設置併發串行收集器,實際是串行垃圾回收器的多線程化,即串行垃圾回收器的多線程版本,也是獨佔式收集器。使用這個參數時,新生代爲並行回收,老年代仍是串行回收。 |
-XX:+UseParNewGC |
-XX:+UseParallelOldGC |
新生代和老年代都使用並行收集器 |
-XX:+UseParallelOldGC |
-XX:+UseConcMarkSweepGC |
老年代回收器,停頓(STW)減少,但吞吐量會降低。 |
-XX:+UseConcMarkSweepGC |
-XX:ParallelGCThreads |
設置並行收集線程數 |
-XX:ParallelGCThreads=10 |