Linux環境HBase安裝配置
1. 認識HBase
(1) HBase介紹
- HBase = Hadoop database,Hadoop資料庫
- 開源資料庫
- 官網:hbase.apache.org/
- HBase源於Google的BigTable
- Apache HBase™是Hadoop資料庫,是一個分散式,可擴充套件的大資料儲存。
- 當需要對大資料進行隨機、實時讀/寫訪問時,請使用Apache HBase™。該專案的目標是託管非常大的表 - 數十億行X百萬列 - 在商品硬體叢集上。Apache HBase是一個開源的,分散式的,版本化的非關聯式資料庫nosql,模仿Google的Bigtable: Chang等人的結構化資料分散式儲存系統。正如Bigtable利用Google檔案系統提供的分散式資料儲存一樣,Apache HBase在Hadoop和HDFS之上提供類似Bigtable的功能。
- HBase可執行基於Yarn平臺的計算任務,但不擅長。
(2) HBase叢集角色
- HDFS:
- NameNode——主節點
- DataNode——資料儲存節點
- Yarn:
- ResourceManager——全域性的資源管理器
- NodeManager——分節點資源和工作管理員
- HBase:
- HMaster
- 負責Table表和RegionServer的監控管理工作
- 處理後設資料的變更
- 對HRegionServer進行故障轉移
- 空閒時對資料進行負載均衡處理
- 管理Region
- 藉助ZooKeeper釋出位置到客戶端
- HRegionServer
- 負責Table資料的實際讀寫
- 重新整理快取資料到HDFS
- 處理Region
- 可以進行資料壓縮
- 維護Hlog
- Region分片
- HMaster
(3) Hbase架構
- HRegionServer結構:
- HLog:儲存HBase的修改記錄
- HRegion:根據rowkey(行鍵,類似id)分割的表的分片
- Store:對應HBase表中的一個列族,可儲存多個欄位
- HFile:真正的儲存檔案
- MemStore:儲存當前的操作
- ZooKeeper:存放資料的後設資料資訊,負責維護RegionServer中儲存的後設資料資訊
- DFS Client:儲存資料資訊到HDFS叢集中
2. HBase-1.3.0安裝配置流程
(1) HBase準備
- Hadoop叢集環境
- ZooKeeper叢集環境
(2) 解壓HBase-1.3.0相關安裝包到目標目錄下:
tar -zxvf .tar.gz -C 目標目錄
(3) 修改配置檔案:
- 進入hbase/conf路徑:
vi hbase-env.sh
-
# The java implementation to use. Java 1.7+ required. export JAVA_HOME=jdk安裝路徑 # 註釋掉以下語句(jdk1.8中不需要這個配置) # export HBASE_MASTER_OPTS="$HBASE_MASTER_OPTS -XX:PermSize=128m -XX:MaxPermSize=128m" # export HBASE_REGIONSERVER_OPTS="$HBASE_REGIONSERVER_OPTS -XX:PermSize=128m -XX:MaxPermSize=128m" # Tell HBase whether it should manage it's own instance of Zookeeper or not. # 關閉HBase自帶的ZooKeeper export HBASE_MANAGES_ZK=false 複製程式碼
vi hbase-site.xml
-
<!-- 設定namenode所在位置(HDFS中存放的路徑) --> <property> <name>hbase.rootdir</name> <value>hdfs://bigdata01:9000/hbase</value> </property> <!-- 是否開啟叢集 --> <property> <name>hbase.cluster.distributed</name> <value>true</value> </property> <!-- HBase-0.9.8之前預設埠為60000 --> <property> <name>hbase.master.port</name> <value>16000</value> </property> <!-- zookeeper叢集的位置 --> <property> <name>hbase.zookeeper.quorum</name> <!-- 注意不要有空格 --> <value>bigdata01:2181,bigdata02:2181,bigdata03:2181</value> </property> <!-- hbase的後設資料資訊儲存在zookeeper的位置 --> <property> <name>hbase.zookeeper.property.dataDir</name> <value>/XXX/zookeeper-3.4.10/zkData</value> </property> 複製程式碼
vi regionservers
- 加入從節點主機名
(4) 解決依賴問題
- 進入hbase/lib路徑:
rm -rf hadoop-*
rm -rf zookeeper-*
- 把相關版本的zookeeper和hadoop的依賴包匯入到hbase/lib
(5) 軟連線hadoop配置
ln -s /XXX/hadoop/core-site.xml
ln -s /XXX/hadoop/hdfs-site.xml
(6) 拷貝配置好的HBase到其他機器上
scp -r hbase-1.3.0/ bigdata02:$PWD
scp -r hbase-1.3.0/ bigdata03:$PWD
(7) 配置環境變數:
- 修改配置檔案:
vi /etc/profile
- 增加以下內容:
export HBASE_HOME=/opt/module/hbase-1.3.0
export PATH=$PATH:$HBASE_HOME/bin
- 宣告環境變數:
source /etc/profile
(8) 啟動叢集
- 啟動主節點
hbase-daemon.sh start master
- 啟動從節點
hbase-daemon.sh start regionserver
(9) 關閉叢集
- 關閉主節點
hbase-daemon.sh stop master
- 關閉從節點
hbase-daemon.sh stop regionserver
(10) UI介面
3. HBase Shell操作
(1) 啟動終端
hbase shell
- 回退:
ctrl + <-
(2) 操作命令:
- 注意:
- 若報錯:
ERROR: Can't get master address from ZooKeeper; znode data == null
- 解決方案:虛擬機器掛起,會使zookeeper不穩定,進而造成hbase不穩定,若遇到報錯,重啟HBase叢集即可。
- 若報錯:
- 查詢表:
list
- 顯示HBase伺服器狀態:
status '主機名'
- 1 active master:存活的主節點
- 0 backup masters:備份的主節點
- 3 servers:從節點
- 0 dead:當機
- 0.6667 average load:平均載入時間
- 顯示當前使用者:
whoami
- 建立表:
create '表名', '列族1', '列族2'
- 檢視錶:
- 全表掃描:
scan '表名'
- 指定Rowkey掃描:
scan '表名', {STARTROW => 'Rowkey值', STOPROW => 'Rowkey值'}
- STOPROW為可選指令,值為實際檢視Rowkey+1
- 檢視錶結構:
describe '表名'
- 修改表結構資訊:
alter '表名', {NAME => '列族名', 變更欄位名 => ' '}
- 查詢指定資料資訊:
- 指定具體的rowkey:
get '表名', 'rowkey'
- 指定具體的列:
get '表名', 'rowkey', '列族:列名'
- 統計表行數:
count '表名'
- 根據Rowkey進行統計
- 指定具體的rowkey:
- 全表掃描:
- 表中新增資料資訊:
put '表名', 'rowkey', '列族:列名', '值'
- HBase只有覆蓋沒有修改
- 覆蓋時對應表名、rowkey、列族、列名欄位,輸入新的值資訊
- 清空表:
truncate '表名'
- 刪除表:
- 指定表不可用:
disable '表名'
- 刪除:
drop '表名'
- 指定表不可用:
(3) 退出終端
exit
或者quit
4. HBase讀寫資料
(1) HBase讀資料流程
-
概述:
- 客戶端Client訪問ZooKeeper,返回-ROOT-表後設資料位置,根據後設資料位置去查詢對應的RegionServer,同時根據-ROOT-查詢到.META表,再根據.META表的後設資料查詢到Region,返回Region的業務後設資料給客戶端。
-
具體流程:
- 客戶端Client從Region中的Store中讀取資料,若在寫資料快取memstore(存放使用者最近寫入的資料)中讀到對應資料,則直接返回資料資訊到客戶端,若memstore中不存在對應資料,則去讀資料快取blockcache中查詢,若blockcache中仍未找到,則去對應的HFile查詢資料資訊並存入blockcache,進而通過blockcache返回資料資訊到客戶端。HBase讀寫分離
(2) HBase寫資料流程
- 客戶端Client傳送寫資料請求,通過ZooKeeper獲取到表的後設資料資訊,客戶端通過RPC通訊查詢到對應的RegionServer,進而找到Region,同時在HLog中記錄寫操作,通過HLog把資料資訊寫入到memstore(16KB),memstore存滿後溢寫到storeFile中,最後HDFS客戶端統一儲存到HFile。
5. HBase API操作
(1) 準備工作
- 新建Maven工程,
pom.xml
中新增依賴:-
<dependencies> <dependency> <groupId>org.apache.hbase</groupId> <artifactId>hbase-server</artifactId> <version>1.3.0</version> </dependency> <dependency> <groupId>org.apache.hbase</groupId> <artifactId>hbase-client</artifactId> <version>1.3.0</version> </dependency> </dependencies> 複製程式碼
-
- 從HBase下的
conf/
目錄中匯出core-site.xml
,hbase-site.xml
,hdfs-site.xml
,匯入Maven工程的resources
目錄下。- 注意:不進行該操作會導致與HBase連線失敗
(2) 具體操作
-
package ybcarry.hbase; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.*; import org.apache.hadoop.hbase.client.*; import org.apache.hadoop.hbase.util.Bytes; import java.io.IOException; import java.util.ArrayList; import java.util.List; /** * @ClassName: HbaseTest * @Description * @Author: YBCarry * @Date2019-03-30 21:10 * @Version: V1.0 **/ public class HbaseTest { public static Configuration conf ; //配置資訊 static { conf = HBaseConfiguration.create() ; } /**1. 判斷HBase中表是否存在*/ public static boolean isExist(String tableNane) throws IOException { //舊版本操作表 //HBaseAdmin admin = new HBaseAdmin(conf); //載入配置 Connection connection = ConnectionFactory.createConnection(conf) ; //管理器 HBaseAdmin admin = (HBaseAdmin)connection.getAdmin() ; return admin.tableExists(TableName.valueOf(tableNane)) ; } /**2. 在HBase中建立表*/ public static void createTable(String tableName, String... columnFamilly) throws IOException { //載入配置 Connection connection = ConnectionFactory.createConnection(conf) ; //a. 如果對錶的操作需要使用管理器 HBaseAdmin admin = (HBaseAdmin)connection.getAdmin() ; //b. 建立描述器 HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(tableName)) ; //c. 指定多個列族 for (String cf : columnFamilly) { htd.addFamily(new HColumnDescriptor(cf)) ; } //d. 建立表 admin.createTable(htd) ; System.out.println("createTable----successful") ; } /**3. 向表中新增資料*/ public static void addData(String tableName, String rowkey, String cf, String column, String value) throws IOException { //載入配置 Connection connection = ConnectionFactory.createConnection(conf) ; //a. 指定表 Table table = connection.getTable(TableName.valueOf(tableName)) ; //b. 新增資料 put方式 Put put = new Put(Bytes.toBytes(rowkey)) ; //c. 指定新增的列族 列 值 put.addColumn(Bytes.toBytes(cf), Bytes.toBytes(column), Bytes.toBytes(value)) ; //d. 寫入表中 table.put(put) ; System.out.println("addData----successful") ; } /**4. 刪除一個rowkey*/ public static void deleteRow(String tableName, String rowkey) throws IOException { //載入配置 Connection connection = ConnectionFactory.createConnection(conf) ; //a. 指定表 Table table = connection.getTable(TableName.valueOf(tableName)) ; //b. 刪除rowkey delete方式 Delete delete = new Delete(Bytes.toBytes(rowkey)) ; //d. 執行操作 table.delete(delete) ; System.out.println("deleteRow----successful") ; } /**5. 刪除多個rowkey*/ public static void deleteRows(String tableName, String... rowkey) throws IOException { //載入配置 Connection connection = ConnectionFactory.createConnection(conf) ; //a. 指定表 Table table = connection.getTable(TableName.valueOf(tableName)) ; //b. 封裝delete操作 List<Delete> ds = new ArrayList<Delete>() ; //c. 遍歷rowkey for (String rk : rowkey) { Delete deletes = new Delete(Bytes.toBytes(rk)) ; ds.add(deletes) ; } //d. 執行操作 table.delete(ds) ; System.out.println("deleteRows----successful") ; } /**6. 全表掃描*/ public static void scanAll(String tableName) throws IOException { //載入配置 Connection connection = ConnectionFactory.createConnection(conf) ; //a. 指定表 Table table = connection.getTable(TableName.valueOf(tableName)) ; //b. 掃描操作 Scan scan = new Scan() ; //c. 獲取返回值 ResultScanner rs = table.getScanner(scan) ; //d. 列印掃描資訊 for (Result r : rs) { //單元格 Cell[] cells = r.rawCells() ; for (Cell cs : cells) { System.out.println("RowKey:" + Bytes.toString(CellUtil.cloneRow(cs))) ; System.out.println("ColumnFamilly:" + Bytes.toString(CellUtil.cloneFamily(cs))) ; System.out.println("Column:" + Bytes.toString((CellUtil.cloneQualifier(cs)))) ; System.out.println("Value:" + Bytes.toString((CellUtil.cloneValue(cs)))) ; } } //成功標誌 System.out.println("scanAll----successful") ; } /**7. 刪除表*/ public static void deleteTable(String tableName) throws IOException { //載入配置 Connection connection = ConnectionFactory.createConnection(conf) ; //a. 如果對錶的操作需要使用管理器 HBaseAdmin admin = (HBaseAdmin)connection.getAdmin() ; //b. 棄用表 admin.disableTable(tableName) ; //c. 刪除表 admin.deleteTable(TableName.valueOf(tableName)) ; //成功標誌 System.out.println("deleteTable----successful") ; } /**主函式*/ public static void main(String[] args) throws IOException { /**1. 判斷HBase中表是否存在*/ // System.out.println(isExist("user")) ; /**2. 在HBase中建立表*/ // createTable("create1", "info1", "info2", "info3") ; /**3. 向表中新增資料:列族 列 值*/ // addData("create1", "xiaoming", "info1", "age", "18") ; // addData("create1", "xiaoming", "info1", "sex", "man") ; // addData("create1", "xiaoming", "info2", "professional", "student") ; // addData("create1", "xiaohong", "info2", "professional", "teacher") ; /**4. 刪除一個rowkey*/ // deleteRow("create", "xiaoming") ; /**5. 刪除多個rowkey*/ // deleteRows("create", "xiaoming", "xiaohong") ; /**6. 全表掃描*/ // scanAll("create1") ; /**7. 刪除表*/ deleteTable("create2") ; } } 複製程式碼