yukim.github.io

詳解repair (1)

May 28, 2013 - cassandra

@oranieさんがrepairのポイントについてまとめてくださってたので、便乗して、repairのちょっと踏み込んだ解説をしてみます。ようやく公開。

長くなったので何回かに分けてアップしていきます。 また、記事中のCassandaはバージョンv1.2.xを想定しています。

repairコマンドの実行

repair はレプリカ間の差異を文字通り修復するために実行します。実行コマンド nodetool repair にはいくつかオプションがあります。nodetool を何も指定しないで実行すると(実装の都合上非常に見にくい)ヘルプが表示されます。その中からrepairコマンドに関係のあるオプションを抜き出したのが以下です。

$ nodetool
usage: java org.apache.cassandra.tools.NodeCmd --host <arg> <command>

 ...

 -et,--end-token <arg>       token at which repair range ends

 ...

 -pr,--partitioner-range     only repair the first range returned by the
                             partitioner for the node
 ...
 -snapshot,--with-snapshot   repair one node at a time using snapshots
 -st,--start-token <arg>     token at which repair range starts

 ...

Available commands
  ...
  repair [keyspace] [cfnames] - Repair one or more column families (use -pr to repair only the first range returned by the partitioner)
  ...

分かりにくいので、整理すると以下のようになります。 ([]はオプションです。[]内の|はその前後どちらかを指定します。)

$ nodetool repair [[keyspace] [cf...]] [-snapshot] [-pr|-st <start token> -et <end token>]

[keyspace] [cf...] の部分はrepairを行うキースペースやカラムファミリを指定します。何も指定しない場合はすべてのキースペース内のカラムファミリを、キースペースを指定した場合はそのキースペース内のカラムファミリを順次repairしていきます。

-snapshot を指定すると、repairの実行前にまずSSTableのスナップショットを作成するようレプリカに指示します。そして、通常はすべてのレプリカに対して同時にハッシュツリーの計算を指示しますが、このオプションを付けると1つのレプリカ毎にハッシュツリーの計算を指示していきます。ハッシュツリーは取得したスナップショットに対して計算されます。つまり、比較的重いハッシュツリーの計算を1ノードごと行うことで、クラスタ全体のパフォーマンスに与える影響を最小限にできます。ただし、その分完了まで時間がかかります(そのためのスナップショットですね)。

-pr は、oranieさんの記事にある通りです。レプリカを含まない、ノードが持つトークン範囲のみrepairします。

-st, -et は最近追加されたオプションで、任意のトークン範囲をrepairできます。v1.1.11とv1.2.3から使えます。-st に範囲の開始トークン、-et に範囲の終端トークンを渡します。指定する範囲は、そのノードが持つトークン範囲内に入っていなければなりません。あるノードが持つトークン範囲を一気に行うのではなく、複数回に分けて行うことが可能になります。

repairの全体像

では、repairを実行した際に何が起こっているのでしょうか。repairの主な処理はAntiEntropyServiceで行われています。

repair コマンドを受け取ったノード(コーディネータ)は、repairを行うキースペースとトークン範囲ごとにrepairセッション(RepairSession)を作成します(コーディネータが持つトークン範囲もしくは-st-etで指定したトークン範囲)。そして、repairセッションはrepairするカラムファミリごとにrepairジョブ(RepairJob)を順次起動します。 後述するMerkleツリーの構築が比較的重い処理のため、repairジョブは順次起動されるようになっています。 repairジョブ は主に以下の2つの処理から成り立っています。

  1. Merkleハッシュツリーの取得・検証
  2. ハッシュ値が違う部分のデータの送受信

Merkleハッシュツリーの取得・検証

‘repair’ジョブは、まずコーディネータ自身とそのレプリカにrepairする範囲のMerkleハッシュツリー(MerkleTree)を要求します。Cassandraは葉の部分に細分化されたトークン範囲を持つハッシュツリーを構築します。要求を受け取ったノードは範囲内のRowのハッシュ値からツリーを構築し、コーディネータに返します(Validator)。すべてのハッシュツリーを受け取ったらそれらを総当たりで比較し(Differencer)、差異があるトークン範囲を特定します。A、B、Cの3つのノードをrepairしている場合、AとB、AとC、BとCの組み合わせで比較します。

ハッシュ値が違う部分のデータの送受信

比較した結果、差異があったトークン範囲のデータのみを送受信します(StreamRepairTask)。ハッシュツリーの葉の部分にあたるトークン範囲を最小単位として差分比較するため、データ送受信もその単位で行われます。

次回はMerkleハッシュツリーについて詳しく見ていきます。