HBaseの行ロック原理と実装

  HBaseのような削除PUTなどの変異操作、など、行ロックを取得する必要があり、その後、行ロックを獲得して動作するが、HRegion.getRowLockInternal(バイト[]列、ブールwaitForLock)、したがって、最初の一般的なブラウジングすることにより行われます以下のように、この方法のプロセスについて。見ることができる、方法は、ラインロックと関連するコンテンツROWLOCK RowLockContext二つのクラスに関する。どちらも、HRegion内部クラスは、これら2つのクラスが実装されている方法では、以下の詳細を見ています。

保護ROWLOCK getRowLockInternal(バイト[]列、ブールwaitForLockは)のIOException {スロー
    HashedBytesのrowKey =新しいHashedBytes(行)。
    RowLockContext rowLockContext =新しいRowLockContext(のrowKey)。

    //ループ我々は(waitForLockない限り!)行ロックを獲得するまで
    (TRUE){ながら
      RowLockContext existingContext = lockedRows.putIfAbsent(のrowKey、rowLockContext)。
      もし(existingContext == NULL){ 
        //行がすでにいずれかのスレッドによってロックされていない、新しく作成されたコンテキストを使用します。
        ブレーク; 
      }そうであれば(existingContext.ownedByCurrentThread()){ 
        //行が既に現在のスレッドによってロックされ、既存のコンテキストを代わりに再利用。
        rowLockContext = existingContext。
        ブレーク; 
      }他{
        (!waitForLock){場合は
          NULLを返します。
        } 
        {しようと
          あきらめるか、それを待つ、行はすでにいくつかの他のスレッドによってロックされている// 
          {(!existingContext.latch.await(this.rowLockWaitDuration、TimeUnit.MILLISECONDS))場合
            のためにロックを待っている」(時限を新たにIOExceptionが投げ行: "+のrowKey)。
          } 
        }キャッチ(InterruptedExceptionあるIE){ 
          LOG.warn( "行のロックを待機中断スレッド:" +のrowKey)。
          InterruptedIOExceptionではIIE =新しいてInterruptedIOException(); 
          iie.initCause(IE); 
          IIEを投げます。
        } 
      } 
    }

    //このスレッドのための新しいロックを割り当てる
    )(戻りrowLockContext.newLock。
  }

  メインロジック放出方法であるROWLOCKファーストクラスを参照し、行がロックを解除するために使用されます。ブールパラメータのリリースがあると同時に、デフォルトでは、行ロックアウト解除されたか否かの代表falseです。

パブリック静的クラスROWLOCK { 
    最終RowLockContextコンテキストを@VisibleForTesting。
    プライベートブール値= falseをリリース。

    @VisibleForTesting ROWLOCK(RowLockContextコンテキスト){ 
      this.context =文脈。
    } 

    / ** 
     *指定されたロックを解除してください。現在のスレッドによって保持されない残りのロックがない場合
     *その行のロックを解除し、他のスレッドがロックを取得することを可能にします。
     * @throwsはIllegalArgumentExceptionスレッド所有しているロックとは別のスレッドによって呼び出された場合
     * / 
    公共ボイドリリース(){ 
      場合{(リリース!)
        context.releaseLock()を。
        =真の解放。
      } 
    } 
  }

  しかしROWLOCKで、かつZehui市でロックに関連する実際の情報を、表示されませんでした、慎重にコンテキストを持つメソッドを、リリース見て、心配しないで、RowLockContextタイプです。この方法はまた、コンテキストオブジェクトを渡すように構成されているが、それはRowLockContextに見て、新しいROWLOCKからRowLockContextに疑われました。

{クラスRowLockContext @VisibleForTesting 
    プライベートHashedBytes最終行; 
  //行とされたCountDownLatchをカウントすることで達成条件をロックします。HBaseのは、ロックを競争するためにどのくらいの状態最後に知っているので、カウントLOCKCOUNTを追加しないので、ここではその理由は、1に設定したCountDownLatchます
  LOCKCOUNTがゼロのときlatch.coutDownその後、//。それ以外の場合は、中getRowLockInternalを待っています。
最終LATCH =たCountDownLatch新しい新しいプライベートたCountDownLatch(1); 民間最終スレッドthread; プライベートLOCKCOUNTのINT = 0; RowLockContext(HashedBytes行){ this.row =行; this.threadにThread.currentThread =(); } ブールownedByCurrentThread(){ スレッド==にThread.currentThreadリターン(); } ROWLOCK newLock(){ LOCKCOUNT ++。 新しいROWLOCKを返す(この); } } 無効releaseLock(){ {場合(ownedByCurrentThread()!) 新しいIllegalArgumentExceptionをスローし( "スレッドによって保持されているロック:" +スレッド + "別のスレッドによって解放することができません:" +にThread.currentThread()); } lockCount--。 IF(LOCKCOUNT == 0){ //スレッドによってない残りのロック、アンロック、および他のスレッドがアクセスすることを可能に RowLockContext existingContext = lockedRows.remove(行)。 もし(existingContext =これは!){ 新しいのRuntimeException(投げる 「内部行ロック状態矛盾、起こるべきではありません、行:」+行)。 latch.countDown(); } } }

  行とされたCountDownLatchをカウントすることによって達成条件をロックします。HBaseの条件がロックを競争するためにどのくらいの最後に知っているので、カウントLOCKCOUNTを追加しないので、ここではその理由は、1に設定されたCountDownLatchます
LOCKCOUNTがゼロの場合は、その後、latch.coutDown。それ以外の場合は、中getRowLockInternalを待っています。
  HRegionもキーメンバ変数があります:現在の行を格納するために使用lockedrowsは、すべての情報行ロックを獲得した、のrowKeyにキー、値がRowLockContextです。
//含むそのロックのコンテキストにロックされた行からのマップ:
  // -その行で待機しているスレッドのたCountDownLatch 
  // -ロック(再入可能)を所有するスレッド
  // -によって保持された(リエントラント)ロックの参照カウントスレッド
  // -行自体
  プライベート最終のConcurrentHashMap <HashedBytes、RowLockContext> lockedRows = 
      新規のConcurrentHashMap <HashedBytes、RowLockContext>();
  まあ、関係する行ロックの内容は、我々は一般的な見解を持っているし、次にロジックでgetRowLockInternalから再び渡すようになりました。
  1. rowKey RowLockContextに従ってオブジェクトの構築
  2. 行までのループがロックを取得している間、またはタイムアウトを待ちます
    1. 最初の行ロック情報のrowKeyのlockedrows、putIfAbsentのConcurrentMapのここでの使用があるか否かを判定する
      1. ない場合は、この行は、lockedrows行ロック、ループのダイレクトアウトブレイクし、現在行ロックに情報を得るために、他のスレッドをロックすると思っていません。
      2. もしそうであれば、以下のように、ロックが占有されていることを行が、ロジックがあります
        1. 銀行がロック・スレッドは、それ自体でそれがある場合は、ループの外に、rowLockContextを上書きします保持しているかどうかを決定
        2. あなたが待っている場合、タイムアウト例外がスローされた場合は、待つlatch.await呼び出します。あなたが直接のリターンを待っていない場合は、パラメータwaitForLock、行ロックを待つ必要があるかどうか。
    2. あなたは蚊帳の外に飛び降りた場合、それは、買収が成功したことを意味newLockと返します。

   :上記のプロセスは、私たちはコードを見て、releaseRowLocks HRegionの方法によって達成され、行ロックを取得するために、リリース行ロックです

/ ** 
   *行ロックの与えられたリストがnullでない場合は、すべてのロックを解除します。
   * / 
  パブリック無効releaseRowLocks(一覧<ROWLOCK> rowLocks){ 
    (rowLocks = nullを!)場合は{ 
      (ROWLOCK ROWLOCK:rowLocks)について{ 
        rowLock.release(); 
      } 
      rowLocks.clear()。
    } 
  }

  可視呼が達成RowLock.release、この方法は、以下のように特定の論理であり、上記のコードを有します。

      でlockedrowsで削除された行ロック。

      次のようにリリースが、それがfalseの場合、コールcontext.releaseLockは、context.releaseLockロジックがあるかどうかfalseに決定されます

        最初のではなく、例外がスローされた場合、ロー・ロック・スレッドがその行ロックの保持者である解放するかどうかを決定します

        count--;

        次いでカウント== 0、及び直接latch.countDownを呼び出す場合、このメソッドは、行ロックを取得するために他のスレッドをトリガします。カウント== 0は、スレッドがロックを持っていることを意味すると転用する必要はありませんが、リリースされました

        リリースがtrueに設定されています。

注意

ここでgetRowLockInternalで、限りlockedRows.putIfAbsent(のrowKey、rowLockContext)が成功すると、他のスレッドはConcurrentMapが保証によって成功しません。

おすすめ

転載: www.cnblogs.com/Evil-Rebe/p/11323010.html