HBase源码系列(四)Put、Delete在服务端是如何处理的?

前面看过了客户端入口HTable中Put、Delete的操作,然后向服务端发送rpc请求,服务端就开始干活了。
还记得Put操作在服务端的入口吗?

Put

再看下服务端RSRpcServices的put入口:

public MultiResponse multi(final RpcController rpcc, final MultiRequest request) throws ServiceException {

    for (RegionAction regionAction : request.getRegionActionList()) {
            this.requestCount.add(regionAction.getActionCount());
       ...
       if (request.hasCondition()) {
       ...
       } else {
           // Mutate a list of rows atomically.
           ClientProtos.RegionLoadStats stats = mutateRows(region, regionAction.getActionList(),cellScanner);
           // add the stats to the request
           if (stats != null) {
               responseBuilder.addRegionActionResult(RegionActionResult.newBuilder()
                       .addResultOrException(ResultOrException.newBuilder().setLoadStats(stats)));
           }
           processed = Boolean.TRUE;
       }
    } 
    ...
}

构造RowMutations,带着看下RowMutations是怎么设计的:

public class RowMutations implements Row {
  private final List<Mutation> mutations = new ArrayList<Mutation>();
  private byte [] row;
}

public interface Row extends Comparable<Row> {
  /**
   * @return The row.
   */
  byte [] getRow();
}

继续,Put和Delete操作都会走这里!

RowMutations rm = null;
for (ClientProtos.Action action : actions) {
    if (action.hasGet()) {
        throw new DoNotRetryIOException("Atomic put and/or delete only, not a Get=" + action.getGet());
    }
    MutationType type = action.getMutation().getMutateType();
    if (rm == null) {
        rm = new RowMutations(action.getMutation().getRow().toByteArray());
    }
    // Put和Delete操作都会走这里
    switch (type) {
    case PUT:
        rm.add(ProtobufUtil.toPut(action.getMutation(), cellScanner));
        break;
    case DELETE:
        rm.add(ProtobufUtil.toDelete(action.getMutation(), cellScanner));
        break;
    default:
        throw new DoNotRetryIOException("Atomic put and/or delete only, not " + type.name());
    }
}
region.mutateRow(rm);

终于进入的重要的processRowsWithLocks()方法,先进行各种检查:

// 先检查每条数据是否在region的rowkey范围内
for (byte[] row : processor.getRowsToLock()) {
    checkRow(row, "processRowsWithLocks");
}

// 检查region的memstoreSize是否大于blockingMemStoreSize
checkResources();

如果MemStore的堆内存超过了阻塞队列的MemStore大小,则抛RegionTooBusyException异常:

if (this.memstoreSize.get() > this.blockingMemStoreSize) {
    blockedRequestsCount.increment();
    requestFlush();
    throw new RegionTooBusyException("Above memstore limit, " + "regionName=" + (this.getRegionInfo() == null ?
            "unknown" :
            this.getRegionInfo().getRegionNameAsString()) + ", server=" + (
            this.getRegionServerServices() == null ? "unknown" : this.getRegionServerServices().getServerName())
            + ", memstoreSize=" + memstoreSize.get() + ", blockingMemStoreSize=" + blockingMemStoreSize);
}
// Coprocessor
startRegionOperation();
// 实例化WAL日志
WALEdit walEdit = new WALEdit();
...

后面才是重头戏,列出重要步骤:
1、运行pre-process hook
2、获得行锁
3、给region加锁
4、processor扫描行,产生mutations和waledits
5、为这次添加进MemStore的数据添加一个批次号
6、调用preBatchMutate hook
7、Apply to memstore
8、Append no sync
9、Release region lock
10、Release row lock(s)
11、Sync edit log
12、call postBatchMutate hook
13、Roll mvcc forward
14、Run post-process hook

Delete

服务端入口

public MutateResponse mutate(final RpcController rpcc, final MutateRequest request) throws ServiceException {
case DELETE:
   Delete delete = ProtobufUtil.toDelete(mutation, cellScanner);
   quota.addMutation(delete);
   //
   if (request.hasCondition()) {
       Condition condition = request.getCondition();
       byte[] row = condition.getRow().toByteArray();
       byte[] family = condition.getFamily().toByteArray();
       byte[] qualifier = condition.getQualifier().toByteArray();
       CompareOp compareOp = CompareOp.valueOf(condition.getCompareType().name());
       ByteArrayComparable comparator = ProtobufUtil.toComparator(condition.getComparator());
       if (region.getCoprocessorHost() != null) {
           processed = region.getCoprocessorHost()
                   .preCheckAndDelete(row, family, qualifier, compareOp, comparator, delete);
       }
       if (processed == null) {
           boolean result = region
                   .checkAndMutate(row, family, qualifier, compareOp, comparator, delete, true);
           if (region.getCoprocessorHost() != null) {
               result = region.getCoprocessorHost()
                       .postCheckAndDelete(row, family, qualifier, compareOp, comparator, delete, result);
           }
           processed = result;
       }
   } else {
       // 调用HRegion的delete方法
       region.delete(delete);
       processed = Boolean.TRUE;
   }
   break;
}

HRegion的delete操作,比Put操作简化了很多:

public void delete(Delete delete) throws IOException {
    checkReadOnly();
    checkResources();
    startRegionOperation(Operation.DELETE);
    try {
        delete.getRow();
        // All edits for the given row (across all column families) must happen atomically.
        doBatchMutate(delete);
    } finally {
        closeRegionOperation(Operation.DELETE);
    }
}

服务端在put和delete的时候,RegionCoprocessorHost做了许多工作,后面在深挖以下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值