谈谈HTable的实现

本文通过一个简单的示例介绍了HTable在HBase中的实现机制,包括HTable的初始化过程、如何与Zookeeper交互获取RegionServer信息,以及HTable进行数据读取的具体流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

HTable作为HBase的CRUD的客户端底层是怎么实现的,虽然HBase-The-Definitive-Guide 这本书的作者推荐在生产环境使用HTablePool
但了解HTable还是很有必要的

下面以一个简单的例子来说明
 

protected static String TEST_TABLE_NAME = "testtable";
 protected static String ROW1_STR = "row1";
 protected static String COLFAM1_STR = "colfam1";
 protected static String QUAL1_STR = "qual1";
 private final static byte[] ROW1 = Bytes.toBytes(ROW1_STR);
 private final static byte[] COLFAM1 = Bytes.toBytes(COLFAM1_STR);
 private final static byte[] QUAL1 = Bytes.toBytes(QUAL1_STR);

 @Test
 public void testHTable() throws IOException {

     Configuration conf = HBaseConfiguration.create();
     HTable table = new HTable(conf, TEST_TABLE_NAME);

     Get get = new Get(ROW1);
     Result result = table.get(get);
     byte[] val = result.getValue(COLFAM1, QUAL1);
     assertThat(Bytes.toString(val), is("val1"));
 }


代码非常简单,就是初始化HTable和调用HTable实例的get获取ROW1的值

在介绍下面的内容之前先简单的说下HBase server
HBase server 基本上由zookeeper和HRegion server组成
前者主要是用于监控和管理HRegion server,后者才是提供数据服务的
HRegion server又分为master+server,master用于维护meta信息,
master和server的确定使用了leader follow方式,任何HRegion server都有可能成为Master

HTable模型

  • HTable: 客户端API
  • HConnection: HTable对zookeeper的网络连接
  • ServerCallable:抽象一次和Region Server的交互,因此它需要有HConnection和HRegionLocation,同时需要有一个访问Region Server的接口
  • HRegionInterface  HRegionLocation: Region Server的地址
  • HRegionInfo: Region Server的信息 
  • HRegionInterface:访问Region Server的接口的动态代理
  • WritableRpcEngine$Invoker:动态代理的相关handle
  • HBaseClient:Region Server的客户端
  • 其他的就不解释了

HTable runtime

1)HTable的初始化step1     

  • 初始化对zookeeper的连接
  • 会调用zookeeper的api,启动两个线程,一个是sendthread,一个是eventhtread,
  • sendthread专门维护对zookeeper的连接,并且会监听zookeeper 的事件,比如节点变化的通知,一旦接到通知会将通知转发给eventhtread
  • eventhtread处理zookeeper的变化
2)HTable的初始化step2
  • 从zookeeper获取到root HRegionLocation[region=-ROOT-,,0.70236052, hostname=localhost, port=33032] 并cache
  • 从root HRegion中获取到meta  HRegionLocation[region=.META.,,1.1028785192, hostname=localhost, port=33032] 并cache
  • 从meta HRegion 取更多hregion信息缓存到本地(见HConnectionManager$HConnectionImplementation.prefetchRegionCache)
  •  从meta HRegion中获取表所在的HRegionLocation[region=testtable,,1332256150817.5c8417fb964377174f649af04a70ad5e., hostname=localhost, port=33032]并cache

3) HTable.get到底干了什么


  • 从cache中获取表对应的HRegionLocation
  • 从cache中获取HRegionLocation对应的Region server【一个实现了HRegionInterface的动态代理,使用了WritableRpcEngine$Invoker作为InvocationHandler】
  • 调用动态代理的get,解下来就会调用WritableRpcEngine$Invoker的invoke
  • 调用HBaseClient.call
4)仔细看看HBaseClient.call

    • 初始化一个Call实例(封装了请求和响应)
    • 连接到Region server(见HBaseClient.getConnection)得到HBaseClient.Connection实例,此时会启动一个读线程(每个region一个),专门读取服务端的响应,也会将请求写入读线程的队列中
    • 发请求,见【HBaseClient.Connection.sendParam(call)】,如果是多个请求线程,由于此时共用一个连接,还存在同步问题,且网络写也是阻塞的,写完了还得等通知
    • 读线程会不断的读取响应,读取一个相应响应就将请求队列中对应的请求删除,并通知主线程即客户端线程,如果读线程空闲超时会自动回收
    • 客户端线程和读线程采用传统的wait + notify 通信,这也意味着客户端线程会阻塞

小结

  • 从HTable 的实现中看到了所谓的传说中的RPC到底是咋回事
    • 一个服务接口
    • 实现了服务接口的动态代理
    • 动态代理对应的invoke handle
    • 当然还有底层网络客户端
  • 另外也看到的HTable的io模型
    • 多个客户线程同步+阻塞写,并将写注册到读线程的队列中
    • 单线程绑定单连接(基本上是每个region对应一个),读取响应,删除队列中的请求标示,并通知客户线程
    • 并没有使用NIO 
    • 和传统的连接池以及时髦的使用select的事件驱动比起来以及是一个比较怪异的实现



在 Apache Hadoop HBase 中,`HTable` 是用来与 HBase 表进行交互的重要工具。使用 `HTable` 通常涉及以下几个步骤: 1. **初始化连接**: 首先,你需要创建一个 `HBaseConfiguration` 对象,并设置所需的连接参数(如地址、认证信息等)。然后通过 `Connection` 类获取到 `ConnectionImplementation`,例如: ```java HBaseConfiguration conf = ...; Connection conn = ConnectionFactory.createConnection(conf); ``` 2. **创建表对象**: 使用提供的 `Connection` 创建 `HTable` 对象,传递表名: ```java TableName tableName = TableName.valueOf("your_table_name"); HTable table = new HTable(conn, tableName); ``` 3. **执行读写操作**: - **读取数据**:使用 `get()` 或 `Scanner` 来查询行或范围的数据。 - **写入数据**:使用 `put()` 方法插入或更新行,或者批量写入 `Batch`。 - **删除数据**:用 `delete()` 删除指定的行。 4. **处理异常**: HBase 操作可能会抛出 `IOException`,所以在关键代码块周围添加适当的错误处理。 5. **关闭资源**: 在完成所有操作后,记得关闭 `HTable` 和 `Connection`: ```java table.close(); conn.close(); ``` 6. **使用示例**(简化版): ```java try { HTable table = new HTable(conf, "test"); Put put = new Put(Bytes.toBytes("row1")); put.add(Bytes.toBytes("columnfam"), Bytes.toBytes("qualifier"), Bytes.toBytes("value")); table.put(put); Get get = new Get(Bytes.toBytes("row1")); Result result = table.get(get); // Process the result... } catch (IOException e) { e.printStackTrace(); } finally { if (table != null) { table.close(); } } ``` 注意:以上示例使用的是旧版本的 API,新版本(如 HBase 2.x)可能有所不同。建议查阅最新的官方文档以了解最新API。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值