HBase源码分析之HRegion上MemStore的flsuh流程(二)

        继上篇《HBase源码分析之HRegion上MemStore的flsuh流程(一)》之后,我们继续分析下HRegion上MemStore flush的核心方法internalFlushcache(),它的主要流程如图所示:


        其中,internalFlushcache()方法的代码如下:

/**
   * Flush the memstore. Flushing the memstore is a little tricky. We have a lot of updates in the
   * memstore, all of which have also been written to the wal. We need to write those updates in the
   * memstore out to disk, while being able to process reads/writes as much as possible during the
   * flush operation.
   * <p>This method may block for some time.  Every time you call it, we up the regions
   * sequence id even if we don't flush; i.e. the returned region id will be at least one larger
   * than the last edit applied to this region. The returned id does not refer to an actual edit.
   * The returned id can be used for say installing a bulk loaded file just ahead of the last hfile
   * that was the result of this flush, etc.
   * @return object describing the flush's state
   *
   * @throws IOException general io exceptions
   * @throws DroppedSnapshotException Thrown when replay of wal is required
   * because a Snapshot was not properly persisted.
   */
  protected FlushResult internalFlushcache(MonitoredTask status)
      throws IOException {
    return internalFlushcache(this.wal, -1, status);
  }

  /**
   * @param wal Null if we're NOT to go via wal.
   * @param myseqid The seqid to use if <code>wal</code> is null writing out flush file.
   * @return object describing the flush's state
   * @throws IOException
   * @see #internalFlushcache(MonitoredTask)
   */
  protected FlushResult internalFlushcache(
      final WAL wal, final long myseqid, MonitoredTask status) throws IOException {
    
	//  如果RegionServerServices类型的rsServices不为空,且为夭折的,直接抛出异常
	if (this.rsServices != null && this.rsServices.isAborted()) {
      // Don't flush when server aborting, it's unsafe
      throw new IOException("Aborting flush because server is aborted...");
    }
	
	// 获取开始时间
    final long startTime = EnvironmentEdgeManager.currentTime();
    // If nothing to flush, return, but we need to safely update the region sequence id
    // 如果没有可以刷新的缓存,直接返回,但是我们需要安全的更新Region的sequence id
    if (this.memstoreSize.get() <= 0) {
      // Take an update lock because am about to change the sequence id and we want the sequence id
      // to be at the border of the empty memstore.
      // 获取一个更新锁,因为我们即将要更新一个序列ID,并且我们想让这个序列ID成为一个空的memstore的边界
      MultiVersionConsistencyControl.WriteEntry w = null;
      
      // 获取更新锁的写锁
      this.updatesLock.writeLock().lock();
      try {
        if (this.memstoreSize.get() <= 0) {
          // Presume that if there are still no edits in the memstore, then there are no edits for
          // this region out in the WAL subsystem so no need to do any trickery clearing out
          // edits in the WAL system. Up the sequence number so the resulting flush id is for
          // sure just beyond the last appended region edit (useful as a marker when bulk loading,
          // etc.)
          // wal can be null replaying edits.
          // 假设如果有memstore仍然没有数据,
          if (wal != null) {
            w = mvcc.beginMemstoreInsert();
            long flushSeqId = getNextSequenceId(wal);
            FlushResult flushResult = new FlushResult(
                FlushResult.Result.CANNOT_FLUSH_MEMSTORE_EMPTY, flushSeqId, "Nothing to flush");
            w.setWriteNumber(flushSeqId);
            mvcc.waitForPreviousTransactionsComplete(w);
            w = null;
            return flushResult;
          } else {
            return new FlushResult(FlushResult.Result.CANNOT_FLUSH_MEMSTORE_EMPTY,
                "Nothing to flush");
          }
        }
      } finally {
        this.updatesLock.writeLock().unlock();
        if (w != null) {
          mvcc.advanceMemstore(w);
        }
      }
    }

    LOG.info("Started memstore flush for " + this +
      ", current region memstore size " +
      StringUtils.byteDesc(this.memstoreSize.get()) +
      ((wal != null)? "": "; wal is null, using passed sequenceid=" + myseqid));

    // Stop updates while we snapshot the memstore of all of these regions' stores. We only have
    // to do this for a moment.  It is quick. We also set the memstore size to zero here before we
    // allow updates again so its value will represent the size of the updates received
    // during flush
    // 当我们更新所有这些region存储的memstore的快照时,停止更新操作。
    // 我们这样做一瞬间,它是非常迅速的。
    
  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值