一、數據存儲和讀取
HBase的數據存放在HDFS文件系統上,並且按照列族和行鍵進行組織。一行數據包含多個列族,每個列族包含多個列(也就是HBase中的列簇)。
HBase的讀寫流程如下:
- 客戶端與HBase ZooKeeper進行連接,並獲取到表的位置信息。
- 客戶端向HRegionServer發送讀/寫請求,同時將請求中的行鍵轉換為HRegion的位置信息。
- HRegionServer在本地緩存中查找數據。
- 如果緩存中沒有數據,則根據HRegion的位置信息,向HDFS中的數據塊獲取數據。
- 如果客戶端發送的是寫請求,HRegionServer將數據保存到內存中,並異步地將數據刷寫到HDFS。
- 如果客戶端發送的是讀請求,HRegionServer將數據返回給客戶端。
上述流程中,客戶端與ZooKeeper的交互是通過ZooKeeper中相應節點的監聽事件驅動的。所有讀寫請求都先發送給HRegionServer,然後由HRegionServer根據請求的類型分發給對應的HRegion進行操作。
二、寫入數據
接下來將分別介紹寫入新數據和更新已有數據兩種情況下的HBase寫入流程。
寫入新數據
寫入新數據時,HBase的寫入流程如下:
- 客戶端構建Put對象,選擇列族和行鍵,添加包含具體列值的鍵值對。
- 客戶端與ZooKeeper交互,獲取表位置信息。
- 客戶端向HRegionServer發送寫請求,寫請求中包括表的位置信息、Put對象的數據和操作類型。
- HRegionServer接收到寫請求後,將數據保存到內存中。
- 隨着內存中的數據量逐漸積累,HRegionServer會將數據寫入HDFS中。
- 在HDFS中生成新的HFile文件。
- 當HFile文件大小達到合適的大小時,HRegionServer會將多個HFile文件進行合併,生成一個更大的HFile文件。
Put put = new Put(Bytes.toBytes("row1"));
put.addColumn(Bytes.toBytes("cf"), Bytes.toBytes("name"), Bytes.toBytes("Tom"));
Configuration config = HBaseConfiguration.create();
Connection connection = ConnectionFactory.createConnection(config);
Admin admin = connection.getAdmin();
TableName tableName = TableName.valueOf("testtable");
HTableDescriptor tableDescriptor = new HTableDescriptor(tableName);
HColumnDescriptor columnDescriptor = new HColumnDescriptor("cf");
tableDescriptor.addFamily(columnDescriptor);
admin.createTable(tableDescriptor);
Table table = connection.getTable(tableName);
table.put(put);
更新已有數據
更新已有數據時,HBase的寫入流程如下:
- 客戶端構建Put對象,並添加需要更新的具體列值。
- 客戶端與ZooKeeper交互,獲取表位置信息。
- 客戶端向HRegionServer發送寫請求,請求中包含數據、表的位置信息和操作類型。
- HRegionServer根據請求中的行鍵,找到要更新的數據。
- HRegionServer將新的數據更新到內存中。
- 隨着內存中的數據量逐漸積累,HRegionServer會將數據寫入到HDFS中。
- 在HDFS中生成新的HFile文件。
- 當HFile文件大小達到合適的大小時,HRegionServer會將多個HFile文件進行合併,生成一個更大的HFile文件。
put.addColumn(Bytes.toBytes("cf"), Bytes.toBytes("age"), Bytes.toBytes("30"));
三、讀取數據
接下來將分別介紹獲取指定行和範圍掃描兩種情況下的HBase讀取數據流程。
獲取指定行數據
獲取指定行的數據時,HBase的讀取流程如下:
- 客戶端構造Get對象,設置列族和行鍵。
- 客戶端與ZooKeeper交互,獲取表位置信息。
- 客戶端向HRegionServer發送讀請求,請求中包含數據、表的位置信息和操作類型。
- HRegionServer根據請求中的行鍵,找到要讀取的數據。
- HRegionServer從內存中或者HDFS中讀取數據,並返回給客戶端。
Get get = new Get(Bytes.toBytes("row1"));
get.addFamily(Bytes.toBytes("cf"));
範圍掃描數據
範圍掃描數據時,HBase的讀取流程如下:
- 客戶端構造Scan對象,並設置要掃描的列族和範圍。
- 客戶端與ZooKeeper交互,獲取表位置信息。
- 客戶端向對應的HRegionServer發送範圍掃描請求,請求中包含數據、表的位置信息和操作類型。
- HRegionServer查找內存中的塊或者HDFS中的塊,並返回數據給客戶端。
- 如果需要合併多個HFile文件,HRegionServer會先進行內部合併操作,並返回給客戶端。
Scan scan = new Scan();
scan.setStartRow(Bytes.toBytes("row1"));
scan.setStopRow(Bytes.toBytes("row5"));
scan.addFamily(Bytes.toBytes("cf"));
四、總結
HBase的讀寫流程比較複雜,但是仍然是一個高效的分佈式系統。對於數據量比較大的應用場景,使用HBase存儲和讀取數據是一個不錯的選擇。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/312912.html