HBase 詳解


1.HBase 架構


============================================

2. HBase Shell 操作

2.1. 基本操作

  • 進入HBase客戶端命令行:bin/hbase shell
  • 查看幫助命令:help
  • 查看當前數據庫中有哪些表:list

2.2. 表的操作

// 2.2.1. 創建表
create 'student','info'(列族)

// 2.2.2. 插入數據到表
put 'student','1001','info:sex','male'
put 'student','1001','info:age','18'
put 'student','1002','info:name','Janna'
put 'student','1002','info:sex','female'
put 'student','1002','info:age','20'

// 2.2.3. 掃描查看表數據
scan 'student'
scan 'student',{STARTROW => '1001', STOPROW => '1004'}
scan 'student',{STARTROW => '1001'}

// 2.2.4. 查看表結構
describe 'student'

// 2.2.5. 更新指定字段的數據
put 'student','1001','info:name','zhangsan'
put 'student','1001','info:age','22'

// 2.2.6. 查看“指定行”或“指定列族:列”的數據
get 'student','1001'
get 'student','1001','info:name'

// 2.2.7. 統計表數據行數
count 'student'

// 2.2.8. 刪除數據:
// 刪除某rowkey的全部數據
deleteall 'student','1001'
// 刪除某rowkey的某一列數據
delete 'student','1002','info:sex'

// 2.2.9. 清空表數據
// 清空表的操作順序為先disable, 然后再 truncate
truncate 'student'

// 2.2.10. 刪除表
// 先讓該表為 disable 狀態
disable 'student'
// 然后才能 drop 這個表
drop 'student'

// 2.2.11 變更表信息
// 將info列族中的數據存放3個版本
alter 'student',{NAME=>'info',VERSIONS=>3}
get 'student','1001',{COLUMN=>'info:name',VERSIONS=>3}

3. HBase 數據結構

3.1 RowKey

  • RowKey 可以是任意字符串(最大長度是64KB,實際應用中長度一般為10-100bytes),在HBASE內部,RowKey 保存為字節數組。存儲時,數據按照 RowKey 的字典序排序存儲。設計 RowKey 時,要充分考慮排序存儲這個特性,將經常一起讀取的行存儲在一起。(位置相關性)
  • RowKey 是用來檢索記錄的主鍵。訪問HBase table中的行,有三種方式:
    • 通過單個 RowKey 訪問;
    • 通過 RowKey 的 range(正則)
    • 全表掃描

3.2 Column Family

  • 列族:HBASE 表中的每個列,都歸屬於某個列族。列族是表的 schema 的一部分(而列不是)。必須在使用表之前定義。列名都以列族作為前綴。例如:courses:history, courses:math 都屬於 courses 這個列族。

3.3 Cell

  • 由(rowkey, column Family:column, version)唯一確定的單元。cell 中的數據是沒有類型的,全部是字節碼形式存儲。

3.4 TimeStamp

  • 版本通過時間戳來索引;

3.5 命名空間

  • Table: 表,所有的表都是命名空間的成員,即表必屬於某個命名空間,如果沒有指定,則在 default 默認的命名空間中;
  • RegionServer group:一個命名空間包含了默認的 RegionServer Group;
  • Permission: 權限。命名空間能夠讓我們來定義訪問控制列表ACL(Access Control List);
  • Quota:限額,可以強制一個命名空間可包含的 region 數量;
  • 常用命令:
    • 查看命名空間:list_namespace;
    • 創建命名空間:create_namespace 'bigdata';
    • 在指定命名空間下,創建表:create 'bigdata:student','info';
    • 刪除命名空間:drop_namespace 'bigdata';

4. HBase 原理

4.1 讀流程


=========================

4.2 寫流程

  • Client 向 HregionServer 發送寫請求;
  • HregionServer 將數據寫到 HLog(write ahead log)。為了數據的持久化和恢復;
  • HregionServer 將數據寫到內存(MemStore);
  • 反饋 Client 寫成功;


=========================

4.3 數據flush過程

  • 當 MemStore 數據達到閾值(默認是 128M,老版本是 64M),將數據刷到磁盤,將內存中的數據刪除,同時刪除HLog中的歷史數據;
  • 將數據存儲到HDFS中;
  • 在HLog中做標記點;

4.4 數據合並過程

  • 當數據塊達到4塊,Hmaster 觸發合並操作, Region 將數據塊加載到本地,進行合並;
  • 當合並的數據超過 256M, 進行拆分,將拆分后的 Region 分配給不同的 HregionServer 管理;
  • 當 HregionServer 宕機后,將 HregionServer 上的 hlog拆分,然后分配給不同的 HregionServer 加載,修改 META;
  • 注意:HLog 會同步到 HDFS;

5. HBase API 操作

5.1 環境准備

// pom.xml
  <dependencies>
      <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>RELEASE</version>
      </dependency>
      <dependency>
          <groupId>org.apache.hbase</groupId>
          <artifactId>hbase-server</artifactId>
          <version>1.3.4</version>
      </dependency>
      <dependency>
          <groupId>org.apache.hbase</groupId>
          <artifactId>hbase-client</artifactId>
          <version>1.3.4</version>
      </dependency>
  <dependencies>

5.2 程序編寫

public class TestHbase {
	
	private static Admin admin = null;
	private static Connection connection = null;
	private static Configuration configuration = null;
	static {
		// HBase 配置文件
		configuration = HBaseConfiguration.create();
		// zookeeper 配置
		configuration.set("hbase.zookeeper.quorum", "Zookeeper地址");
		configuration.set("hbase.zookeeper.property.clientPort", "2181");
		
		// 獲取連接對象
		try {
			connection = ConnectionFactory.createConnection(configuration);
			admin = connection.getAdmin();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	private void close(Connection conn, Admin admin) {
		if (conn != null) {
			try {
				conn.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		if (admin != null) {
			try {
				admin.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	// 判斷表是否存在
	@Test
	public void tableExist() throws IOException {
		
		// 執行操作
		Boolean student = admin.tableExists(TableName.valueOf("student"));
		System.out.println("表Staff是否存在:"+student);
		
		Boolean staff = admin.tableExists(TableName.valueOf("staff"));
		System.out.println("表Staff是否存在:"+staff);
		this.close(connection, admin);
		
	}
	
	// 創建表
	@Test
	public void createTable() throws IOException {
		// 創建表描述器
		HTableDescriptor hTableDescriptor = new HTableDescriptor(TableName.valueOf("country"));
		
		// 創建列描述器
		HColumnDescriptor hColumnDescriptor = new HColumnDescriptor("name");
		// 添加列族
		hTableDescriptor.addFamily(hColumnDescriptor);
		
		// 創建表操作
		admin.createTable(hTableDescriptor);
		
		System.out.println("表已經創建成功!");
		this.close(connection, admin);
	}
	
	// 刪除表
	@Test
	public void deleteTable() throws IOException {
		
		// 使表不可用
		admin.disableTable(TableName.valueOf("country"));
		
		// 刪除表
		admin.deleteTable(TableName.valueOf("country"));
		
		System.out.println("表已經刪除成功!");
		this.close(connection, admin);
	}
	
	
	// 操作表中數據: 
	// 增/改數據
	@Test
	public void putData() throws IOException {
		// 獲取table對象
		Table table = connection.getTable(TableName.valueOf("student"));
		
		// 創建put對象
		Put put = new Put(Bytes.toBytes("1010"));
		// 添加數據
		put.addColumn(Bytes.toBytes("info"), Bytes.toBytes("name"), Bytes.toBytes("貂蟬"));
		
		// 執行添加操作
		table.put(put);
		
		System.out.println("數據添加成功!");
		this.close(connection, admin);
	}
	
	// 刪除數據
	@Test
	public void deleteData() throws IOException {
		// 獲取table對象
		Table table = connection.getTable(TableName.valueOf("student"));
		
		// 創建delete對象
		Delete delete = new Delete(Bytes.toBytes("1010"));
		// 第一種方式:不建議使用,只是刪除最新版本
//		delete.addColumn(Bytes.toBytes("info"), Bytes.toBytes("name"));
		// 第二種方式:刪除所有版本
		delete.addColumns(Bytes.toBytes("info"), Bytes.toBytes("name"));
		
		// 刪除數據
		table.delete(delete);
		
		System.out.println("數據刪除成功!");
		table.close();
		this.close(connection, admin);
	}
	
	// 查詢數據
	// 全表掃描
	@Test
	public void scanTable() throws IOException {
		Table table = connection.getTable(TableName.valueOf("student"));
		// 構建掃描器
		Scan scan = new Scan();
		
		ResultScanner results = table.getScanner(scan);
		for(Result result : results) {
			Cell[] cells = result.rawCells();
			for (Cell cell : cells) {
				System.out.println("RK:" + Bytes.toString(CellUtil.cloneRow(cell)) +
								   ",CF:" + Bytes.toString(CellUtil.cloneFamily(cell)) + 
								   ",CN:" + Bytes.toString(CellUtil.cloneQualifier(cell)) + 
								   ",VALUE:" + Bytes.toString(CellUtil.cloneValue(cell)));
			}
		}
		
		table.close();
		this.close(connection, admin);
	}

  // 獲取指定列族:列的數據
	@Test
	public void scanColumnFamily() throws IOException {
		Table table = connection.getTable(TableName.valueOf("student"));
		// 創建get對象
		Get get = new Get(Bytes.toBytes("1001"));
		
		Result result = table.get(get);
		Cell[] cells = result.rawCells();
		for (Cell cell : cells) {
			System.out.println("RK:" + Bytes.toString(CellUtil.cloneRow(cell)) +
							   ",CF:" + Bytes.toString(CellUtil.cloneFamily(cell)) + 
							   ",CN:" + Bytes.toString(CellUtil.cloneQualifier(cell)) + 
							   ",VALUE:" + Bytes.toString(CellUtil.cloneValue(cell)));
		}
	}
}

**參考資料:** - [ubuntu 16.04 開放指定端口](https://blog.csdn.net/fancancan/article/details/81286689) - [HBase 單機啟動問題](https://blog.csdn.net/Sunday2017/article/details/80569947) - [hadoop +zookeeper + hbase 單節點安裝](https://www.cnblogs.com/chaoren399/p/5018550.html) - [Windows 環境下,出現“UnknownHostException”](https://blog.csdn.net/weixin_40861707/article/details/79979491)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM