Hbase基本结构 (五) HBase客户端访问过程

353 阅读4分钟

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时,用户会收到3result,每个result中cell数依次为2,2,1个。 
        - 3. allowPartial:scanner执行流程跳过步骤3重组流程,直接把服务端收到的result返回给用户,用户允许result含不完整cell。 
        - 4. maxResultSize:loadCache时单次RPC操作最多拿到多少字节数的结果集。

3.2.2. 示例1: scan.setCaching(2).setAllowPartialResults(true).setMaxResultSize(1MB)

3.2.3. 示例2: scan.setCaching(2).setMaxResultSize(1MB)

3.2.4. 示例3: scan.setBatch(2).setCaching(2).setMaxResultSize(1MB)