1. 客户端访问源码示例
Configuration conf = HBaseConfiguration.create(); // hbase-site.xml,
core-site.xml, hdfs-site.xml
Try (Connection conn = ConnectionFactory.createConnection(conf)) { //
维持一个到Active Master和所有到RS的TCP连接,缓存Meta信息
try (Table table = conn.getTable(tableName)) { //
所有table共享conn配置、线程池、Meta缓存资源。ver 1.x非线程安全。
for (byte[] rowkey: new byte[][] { ROW_KEY0, ROW_KEY1 }) {
Put put = new Put(rowkey).addColumn(FAMILY, QUALIFIER, VALUE);
table.put(put);
}
Scan scan = new Scan().withStartRow(ROW_KEY1).setLimit(1);
try (ResultScanner scanner = table.getScanner(scan)) {
List\<Cell\> cells = new ArrayList\<\>();
for (Result result : scanner) {
cells.addAll(result.listCells());
}
println(cells.size()); // 1
Cell firstCell = cells.get(0);
println(CellUtil.cloneRow(firstCell)); // ROW_KEY1
println(CellUtil.cloneFamily(firstCell)); // FAMILY
}
}
}
2. 客户端定位Region
调用HBase API时,客户端先去MetaCache中找到业务rowkey所在的Region:
- 1)Region信息为空,说明MetaCache中没有这个rowkey的缓存。则客户端直接到hbase:meta表中Reversed Scan即可。
首次查找时,需要先读取ZooKeeper的/hbase/meta-region-server这个Znode,以便确定hbase:meta表所在的RegionServer。
在hbase:meta表中找到业务rowkey所在的Region之后,将(regionStartRow, region)这样的二元组信息存放在一个MetaCache中,这种情况一般发生在HBase客户端到服务端连接第一次建立后的少数几个请求内,不会对HBase服务端造成压力。
- 2)Region信息不为空,但是调用RPC请求对应RegionServer后发现Region并不在这个RegionServer上。
说明MetaCache信息过期,同样直接Reversed Scan hbase:meta表,找到正确的Region并缓存。
通常在某些Region在两个RegionServer之间移动后会发生这种情况。 事实上,无论是RegionServer宕机,还是由于Balance导致Region移动,发生的几率很小。而且,只会对Region移动后的极少数请求产生影响,这些请求只需要通过HBase客户端自动重试locate meta即可成功。
- 3)Region信息不为空,且调用RPC请求到对应RegionServer后,发现是正确的RegionServer。
3. 客户端Scanner
3.1. Scanner扫描流程
3.1.1. Scanner工作流程
3.1.2. 从HFile检索KeyValue
3.2. Scanner读取Result流程
3.2.1. 执行流程
scanner执行流程:
- 1. 用户每次执行scanner.next(),都会尝试去名为cache的队列中拿result,即步骤4。
- 2. 如果cache队列为空,则发起一次RPC,向服务端请求当前scanner的后续result数据,即步骤1。
- 3. 客户端收到result列表(步骤2)后,通过scanResultCache把这些results内的多个cell进行重组,最终组成用户需要的result放入到Cache中(步骤3)。
- 4. 步骤1+步骤2+步骤3 统称为 loadCache操作。 步骤3对RPC response中的result进行重组的原因: RegionServer为了避免被当前RPC请求耗尽资源,实现了多个维度的资源限制(如timeout,单次RPC响应最大字节数等),一旦某个维度资源达到阈值,就马上把当前拿到的cell返回给客户端,这样客户端拿到的result可能就不是一行完整的数据,因此需要重组。
Scan的几个重要概念:
- 1. caching:每次loadCache操作最多放caching个result到cache队列,避免某一次scanner.next()耗时过长。
- 2. batch:用户拿到的result中最多含有一行数据中的batch个cell,如5个cell当batch为2时,用户会收到3个result,每个result中cell数依次为2,2,1个。
- 3. allowPartial:scanner执行流程跳过步骤3重组流程,直接把服务端收到的result返回给用户,用户允许result含不完整cell。
- 4. maxResultSize:loadCache时单次RPC操作最多拿到多少字节数的结果集。