HBase 基本入門篇

Java3y發表於2020-04-06

本文公眾號來源:美碼師

作者:美碼師
本文已收錄至我的GitHub

無論是 NoSQL,還是大資料領域,HBase 都是非常"炙熱"的一門資料庫。本文將對 HBase 做一些基礎性的介紹,旨在入門。

HBase 基本入門篇

一、簡介

HBase 是一個開源的、面向列的非關係型分散式資料庫,目前是Hadoop體系中非常關鍵的一部分。在最初,HBase是基於谷歌的 BigTable 原型實現的,許多技術來自於Fay Chang在2006年所撰寫的Google論文"BigTable"。與 BigTable基於Google檔案系統(File System)一樣,HBase則是基於HDFS(Hadoop的分散式檔案系統)之上而開發的。

HBase 採用 Java 語言實現,在其內部實現了BigTable論文提到的一些壓縮演算法、記憶體操作和布隆過濾器等,這些能力使得HBase 在海量資料儲存、高效能讀寫場景中得到了大量應用,如 Facebook 在 2010年11 月開始便一直選用 HBase來作為訊息平臺的儲存層技術。HBase 以 Apache License Version 2.0開源,這是一種對商業應用友好的協議,同時該專案當前也是Apache軟體基金會的頂級專案之一。

有什麼特性

  • 基於列式儲存模型,對於資料實現了高度壓縮,節省儲存成本

  • 採用 LSM 機制而不是B(+)樹,這使得HBase非常適合海量資料實時寫入的場景

  • 高可靠,一個資料會包含多個副本(預設是3副本),這得益於HDFS的複製能力,由RegionServer提供自動故障轉移的功能

  • 高擴充套件,支援分片擴充套件能力(基於Region),可實現自動、資料均衡

  • 強一致性讀寫,資料的讀寫都針對主Region上進行,屬於CP型的系統

  • 易操作,HBase提供了Java API、RestAPI/Thrift API等介面

  • 查詢最佳化,採用Block Cache 和 布隆過濾器來支援海量資料的快速查詢

與RDBMS的區別

對於傳統 RDBMS 來說,支援 ACID 事務是資料庫的基本能力,而 HBase 則使用行級鎖來保證寫操作的原子性,但是不支援多行寫操作的事務性,這主要是從靈活性和擴充套件性上做出的權衡。

ACID 要素包含 原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)以及永續性(Durability)


總體來說, HBase 與傳統關聯式資料庫的區別,如下表所示:

特性HBaseRDBMS
硬體架構類似於 Hadoop 的分散式叢集,硬體成本低廉傳統的多核系統,硬體成本昂貴
容錯性

由軟體架構實現,由於由多個節點組成

,所以不擔心一點或幾點當機

一般需要額外硬體裝置實現 HA 機制
資料庫大小PBGB、TB
資料排布方式稀疏的、分佈的多維的 Map以行和列組織
資料型別Bytes豐富的資料型別
事物支援ACID 只支援單個 Row 級別全面的 ACID 支援,對 Row 和表
查詢語言只支援 Java API (除非與其他框架一起使用,如 Phoenix、Hive)SQL
索引只支援 Row-key,除非與其他技術一起應用,如 Phoenix、Hive支援
吞吐量百萬查詢/每秒數千查詢/每秒


二、資料模型

下面,我們以關係型資料庫的一個資料表來演示 HBase 的不同之處。

先來看下面這張表:

ID裝置名狀態時間戳
1空調開啟20190712 10:05:01
2電視機關閉20190712 10:05:08

這裡記錄的是一些家庭裝置上報的狀態資料(DeviceState),其中包括裝置名、狀態、時間戳這些欄位。

在 HBase 中,資料是按照列族(Column Family,簡稱CF)來儲存的,也就是說對於不同的列會被分開儲存到不同的檔案。那麼對於上面的狀態資料表來說,在HBase中會被儲存為兩份:

列族1. 裝置名

Row-KeyCF:Column-KeyTimestampCell Value
1DeviceState:裝置名20190712 10:05:01空調
2DeviceState:裝置名20190712 10:05:08電視機

列族2. 狀態

Row-KeyCF:Column-KeyTimestampCell Value
1DeviceState:狀態20190712 10:05:01開啟
2DeviceState:狀態20190712 10:05:08關閉

這裡Row-key是唯一定位資料行的ID欄位,而Row-key 加上 CF、Column-Key,再加上一個時間戳才可以定位到一個單元格資料。其中時間戳用來表示資料行的版本, 在HBase中預設會有 3 個時間戳的版本資料,這意味著對同一條資料(同一個Rowkey關聯的資料)進行寫入時,最多可以儲存3個版本。

在查詢某一行的資料時,HBase需要同時從兩個列族(檔案)中進行查詢,最終將結果合併後返回給客戶端。 由此可見如果列族太多,則會影響讀取的效能,在設計時就需要做一些權衡。

由此可見,HBase的使用方式與關係型資料庫是大不相同的,在使用 HBase 時需要拋棄許多關係型資料庫的思維及做法,比如強型別、二級索引、表連線、觸發器等等。

然而 HBase 的靈活性及高度可伸縮性卻是傳統 RDBMS 無法比擬的。

三、安裝HBase

單機環境安裝

1. 準備JDK環境

確保環境上JDK已經裝好,可執行java -version確認:

host:/home/hbase # java -versionopenjdk version "1.8.0_201"OpenJDKRuntimeEnvironment(build 1.8.0_201-Huawei_JDK_V100R001C00SPC060B003-b10)OpenJDK64-BitServer VM (build 25.201-b10, mixed mode)


2. 下載軟體

官網的下載地址頁面:

選擇合適的版本,比如1.4.10。 下載後解壓:

wget 2.1.5/hbase-2.1.5-bin.tar.gztar -xzvf hbase-2.1.5-bin.tar.gzmkdir -p /opt/localmv hbase-2.1.5/opt/local/hbase

配置HBase執行命令路徑:

export HBASE_HOME=/opt/local/hbaseexport PATH=$PATH:$HBASE_HOME/bin


3. 配置軟體

vim conf/hbase-env.sh

#JDK安裝目錄export JAVA_HOME=/usr/local/jre1.8.0_201#配置hbase自己管理zookeeperexport HBASE_MANAGES_ZK=true

vim conf/hbase-site.xml

  1. <configuration>


  2. <!-- zookeeper埠  -->

  3. <property>

  4. <name>hbase.zookeeper.property.clientPort</name>

  5. <value>2182</value>                                                                                                                                          

  6. </property>


  7. <!--  HBase 資料儲存目錄 -->

  8. <property>

  9. <name>hbase.rootdir</name>

  10. <value>file:///opt/local/hbase/data</value>

  11. </property>


  12. <!-- 用於指定 ZooKeeper 資料儲存目錄 -->

  13. <property>

  14. <name>hbase.zookeeper.property.dataDir</name>

  15. <value>/opt/local/hbase/data/zookeeper</value>

  16. </property>


  17. <!-- 用於指定臨時資料儲存目錄 -->

  18. <property>

  19. <name>hbase.tmp.dir</name>

  20. <value>/opt/local/hbase/temp/hbase-${user.name}</value>

  21. </property>

  22. </configuration>

其中 hbase.rootdir hbase.zookeeper.property.dataDir 都用來指定資料存放的目錄,預設情況下hbase會使用/tmp目錄,這顯然是不合適的。配置了這兩個路徑之後,hbase會自動建立相應的目錄。

關於更多的引數設定可參考這裡

4. 啟動軟體

start-hbase.sh

此時檢視 logs/hbase-root-master-host-xxx.log,如下:

2019-07-1107:37:23,654 INFO  [localhost:33539.activeMasterManager] hbase.MetaMigrationConvertingToPB: hbase:meta doesn't have any entries to update.2019-07-11 07:37:23,654 INFO  [localhost:33539.activeMasterManager] hbase.MetaMigrationConvertingToPB: META already up-to date with PB serialization2019-07-11 07:37:23,664 INFO  [localhost:33539.activeMasterManager] master.AssignmentManager: Clean cluster startup. Assigning user regions2019-07-11 07:37:23,665 INFO  [localhost:33539.activeMasterManager] master.AssignmentManager: Joined the cluster in 11ms, failover=false2019-07-11 07:37:23,672 INFO  [localhost:33539.activeMasterManager] master.TableNamespaceManager: Namespace table not found. Creating...

檢查程式情況,發現程式已經啟動

ps -ef |grep hadooproot     1104911032207:37 pts/100:00:20/usr/local/jre1.8.0_201/bin/java -Dproc_master-XX:OnOutOfMemoryError=kill -9%p -XX:+UseConcMarkSweepGC-XX:PermSize=128m-XX:MaxPermSize=128m-XX:ReservedCodeCacheSize=256m-Dhbase.log.dir=/opt/local/hbase/logs -Dhbase.log.file=hbase-root-master-host-192-168-138-148.log-Dhbase.home.dir=/opt/local/hbase -Dhbase.id.str=root -Dhbase.root.logger=INFO,RFA -Dhbase.security.logger=INFO,RFAS org.apache.hadoop.hbase.master.HMaster startroot     1890730747007:50 pts/100:00:00 grep --color=auto hadoop

透過JPS(JDK自帶的檢查工具) 可以看到當前啟動的Java程式:

# jps5701Jps4826HMaster1311 jar

檢視 data目錄,發現生成了對應的檔案:

host:/opt/local/hbase/data # ls -lh .total 36Kdrwx------. 4 root root 4.0KJul1108:08 datadrwx------. 4 root root 4.0KJul1108:08 hbase-rw-r--r--. 1 root root   42Jul1108:08 hbase.id-rw-r--r--. 1 root root    7Jul1108:08 hbase.versiondrwx------. 2 root root 4.0KJul1108:08MasterProcWALsdrwx------. 2 root root 4.0KJul1108:08 oldWALsdrwx------. 3 root root 4.0KJul1108:08.tmpdrwx------. 3 root root 4.0KJul1108:08WALsdrwx------. 3 root root 4.0KJul1108:08 zookeeper

關於執行模式

HBase啟動時預設會使用單機模式,此時 Zookeeper和 HMaster/RegionServer 會執行在同一個JVM中。以standalone模式啟動的HBase會包含一個HMaster、RegionServer、Zookeeper例項,此時 HBase 會直接使用本地檔案系統而不是HDFS。

透過將 conf/hbase-site.xml中的 hbase.cluster.distributed 配置為true,就是叢集模式了。在這個模式下,你可以使用分散式環境進行部署,或者是"偽分散式"的多程式環境。

<configuration><property><name>hbase.cluster.distributed</name><value>true</value></property></configuration>

需要注意的是,如果以standalone啟動的話,HMaster、RegionServer埠都是隨機的,無法透過配置檔案指定。


四、基本使用

開啟HBase Shell

hbase shell

執行status命令

  1. Version2.1.5, r76ab087819fe82ccf6f531096e18ad1bed079651, WedJun516:48:11 PDT 2019


  2. hbase(main):001:0> status

  3. 1 active master, 0 backup masters, 1 servers, 0 dead, 2.0000 average load

這表示有一個Master在執行,一個RegionServer,每個RegionServer包含2個Region。

表操作

  • 建立DeviceState表

  1. hbase(main):002:0> create "DeviceState", "name:c1", "state:c2"


  2. => Hbase::Table- DeviceState

此時,已經建立了一個DeviceState表,包含name(裝置名稱)、state(狀態)兩個列。

檢視錶資訊

  1. hbase(main):003:0> list

  2. TABLE

  3. DeviceState

  4. 1 row(s) in0.0090 seconds


  5. => ["DeviceState"]


  6. hbase(main):003:0> describe "DeviceState"

  7. TableDeviceStateis ENABLED

  8. DeviceState

  9. COLUMN FAMILIES DESCRIPTION

  10. {NAME => 'name', BLOOMFILTER => 'ROW', VERSIONS => '1', IN_MEMORY => 'false', KEEP_DELETED_CELLS => 'FALSE', DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', COMPRESSIO

  11. N => 'NONE', MIN_VERSIONS => '0', BLOCKCACHE => 'true', BLOCKSIZE => '65536', REPLICATION_SCOPE => '0'}

  12. {NAME => 'state', BLOOMFILTER => 'ROW', VERSIONS => '1', IN_MEMORY => 'false', KEEP_DELETED_CELLS => 'FALSE', DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', COMPRESSI

  13. ON => 'NONE', MIN_VERSIONS => '0', BLOCKCACHE => 'true', BLOCKSIZE => '65536', REPLICATION_SCOPE => '0'}

  14. 2 row(s) in0.0870 seconds

  • 寫入資料

透過下面的命令,向DeviceState寫入兩條記錄。

由於有兩個列族,因此需要寫入四個單元格資料:

put "DeviceState", "row1", "name", "空調"put "DeviceState", "row1", "state", "開啟"put "DeviceState", "row2", "name", "電視機"put "DeviceState", "row2", "state", "關閉"
  • 查詢資料

查詢某行、某列

  1. hbase(main):012:0> get"DeviceState","row1"

  2. COLUMN                                      CELL

  3. name:                                      timestamp=1562834473008, value=\xE7\x94\xB5\xE8\xA7\x86\xE6\x9C\xBA

  4. state:                                     timestamp=1562834474630, value=\xE5\x85\xB3\xE9\x97\xAD

  5. 1 row(s) in0.0230 seconds


  6. hbase(main):013:0> get"DeviceState","row1", "name"

  7. COLUMN                                      CELL

  8. name:                                      timestamp=1562834473008, value=\xE7\x94\xB5\xE8\xA7\x86\xE6\x9C\xBA

  9. 1 row(s) in0.0200 seconds

掃描表

hbase(main):026:0> scan "DeviceState"ROW                                         COLUMN+CELL row1                                       column=name:, timestamp=1562834999374, value=\xE7\xA9\xBA\xE8\xB0\x83 row1                                       column=state:, timestamp=1562834999421, value=\xE6\x89\x93\xE5\xBC\x80 row2                                       column=name:, timestamp=1562834999452, value=\xE7\x94\xB5\xE8\xA7\x86\xE6\x9C\xBA row2                                       column=state:, timestamp=1562835001064, value=\xE5\x85\xB3\xE9\x97\xAD2 row(s) in0.0250 seconds

查詢數量

  1. hbase(main):014:0> count "DeviceState"

  2. 2 row(s) in0.0370 seconds


  3. => 1

  • 清除資料

刪除某列、某行

  1. delete"DeviceState", "row1", "name"

  2. 0 row(s) in0.0080 seconds


  3. hbase(main):003:0> deleteall "DeviceState", "row2"

  4. 0 row(s) in0.1290 seconds

清空整個表資料

hbase(main):021:0> truncate "DeviceState"Truncating'DeviceState' table (it may take a while):- Disabling table...- Truncating table...0 row(s) in3.5060 seconds

刪除表(需要先disable)

  1. hbase(main):006:0> disable "DeviceState"

  2. 0 row(s) in2.2690 seconds


  3. hbase(main):007:0> drop "DeviceState"

  4. 0 row(s) in1.2880 seconds


五、FAQ

  • A. 啟動時提示 ZK 埠監聽失敗:

    Could not start ZK at requested port of 2181. ZK was started at port: 2182. Aborting as clients (e.g. shell) will not be able to find this ZK quorum

原因

HBase需要啟動Zookeeper,而本地的2181埠已經被啟用(可能有其他Zookeeper例項)

解決辦法

conf/hbase-site.xml中修改hbase.zookeeper.property.clientPort的值,將其修改為2182,:

<configuration><property><name>hbase.zookeeper.property.clientPort</name><value>2182</value>                                                                                                                                           </property></configuration>
  • B. 啟動HBase Shell 時提示

    java.lang.UnsatisfiedLinkError

原因

在執行hbase shell期間,JRuby會在“java.io.tmpdir”路徑下建立一個臨時檔案,該路徑的預設值為“/tmp”。如果為“/tmp”目錄設定NOEXEC許可權,然後hbase shell會啟動失敗並丟擲“java.lang.UnsatisfiedLinkError”錯誤。

解決辦法

  1. 取消/tmp的noexec許可權(不推薦)

  2. 設定java.io.tmpdir變數,指向可用的路徑,編輯conf/hbase-env.sh檔案:
export HBASE_TMP_DIR=/opt/local/hbase/tempexport HBASE_OPTS="-XX:+UseConcMarkSweepGC -Djava.io.tmpdir=$HBASE_TMP_DIR"

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69900354/viewspace-2666268/,如需轉載,請註明出處,否則將追究法律責任。

相關文章