web-dev-qa-db-ja.com

既存のキースペースでcqlshを使用して新しいテーブルを作成:列ファミリーIDの不一致

ヒューストン、問題があります。

既存のCassandra(v2.1.3)キースペースでcqlshを使用して新しいテーブルを作成しようとすると、結果は次のようになります。

ServerError: 
<ErrorMessage code=0000 [Server error] message="Java.lang.RuntimeException:
Java.util.concurrent.ExecutionException: 
    Java.lang.RuntimeException:      
        org.Apache.cassandra.exceptions.ConfigurationException: Column family ID mismatch (found e8c03790-c952-11e4-a753-5981ea73cd7c; expected e8b14370-c952-11e4-a844-8f10bfb9c386)">

最初の作成試行の後、もう一度試行すると、次の結果になります。

AlreadyExists:テーブル 'ks.metrics'はすでに存在します

ただし、キースペースの既存のテーブルのリストを取得するdesc tables;は新しいテーブルを報告しません。

この問題は Cassandra-8387 に関連しているようですが、テーブルを作成しようとしているクライアントは1つだけです:cqlsh

起動時にキースペースとテーブルを作成するSparkジョブがたくさんあり、これを並行して実行する可能性があります。これにより、キースペースが破損しますか?

新しいキースペースを作成し、それにテーブルを追加すると、期待どおりに機能します。

何か案は?

[〜#〜]更新[〜#〜]

回避策が見つかりました:キースペースで修復を実行すると、テーブルが表示されます(desc tables)も機能します。

22
maasg

短い回答:競合状態があります 、これは1.1で解決されたと考えています.8.。


長い答え:

クラスターの1つで常にそのエラーが発生します。ハードドライブが非常に遅いテストマシンを使用していて、2つの別々のコンピューターに4つのノードがある場合、1つまたは2つのテーブルを作成するだけでエラーが発生します。

以下に、Cassandra 3.7インストールからのスタックトレースのコピーがあります。バージョンは2.1.3でしたが、コードのこの部分が大幅に変更されたことに驚かれることでしょう。

ご覧のとおり、例外はvalidateCompatibility()関数で発生します。これには、メタデータの新旧バージョンが次のものと等しい必要があります。

  • ksName(キースペース名)
  • cfName(列ファミリー名)
  • cfId(columnfamily UUID)
  • フラグ(isSuper、isCounter、isDense、isCompound)
  • コンパレーター(キーソーティングコンパレーター)

これらの値のいずれかが古いメタデータと新しいメタデータの間で一致しない場合、プロセスは例外を発生させます。この場合、cfIdの値は異なります。

スタックを上に行くと、すぐにapply()を呼び出すvalidateCompatibility()があります。

次に、updateTable()があります。同様に、それはapply()をほぼ即座に呼び出します。まず、getCFMetaData()を呼び出して、新しいデータと比較される現在の列ファミリーデータ(「古い」)を取得します。

次に、updateKeyspace()が表示されます。この関数は、何が変更されたかを知るためにdiffを計算します。次に、それを各タイプのデータに保存します。テーブルはタイプの後に2番目です...

その前に、キースペースレベルで何が変更されたかを計算するmergeSchema()があります。次に、削除されたキースペースを削除し、更新されたキースペース(および新しいキースペース)の新しいキースペースを生成します。最後に、それらはそれぞれのupdateKeyspace()を呼び出す新しいキースペースをループします。

次のスタックには、興味深い関数mergeSchemaAndAnnounceVersion()があります。これは、キースペースがメモリとディスクで更新されるとバージョンを更新します。スキーマのバージョンには、互換性のないcfIDが含まれているため、例外が生成されます。 Announceの部分は、このノードが特定のスキーマの新しいバージョンを認識しているという事実について、他のノードにゴシップメッセージを送信することです。

次に、MigrationTaskという名前のものが表示されます。これは、Cassandraノード間で変更を移行するために使用されるメッセージです。メッセージペイロードは、ミューテーションのコレクションです(mergeSchema()関数によって処理されます)。

スタックの残りの部分は、メッセージの処理に使用されるさまざまなタイプの関数であるrun()関数を示しています。

私の場合、問題は少し遅れて解決され、すべてが順調です。スキーマが最終的に同期するために私は何の関係もありません。予想通り。ただし、一度にすべてのテーブルを作成することはできません。したがって、これを見て私の見解は、移行メッセージが期待された順序で到着しないということです。イベントを再送信することによって処理され、混合を生成するタイムアウトが必要です。

それで、最初にメッセージを送信するコードを見てみましょう。MigrationManagerにそのコードがあります。ここにMIGRATION_DELAY_IN_MSパラメータは古い問題とリンクしています スキーマプッシュ/プルレース 。これは競合状態を回避するためのものでした。さて...あなたは行き​​ます。そのため、競合状態が発生する可能性があることを認識し、それを回避するために、少し遅延を追加しました。この修正の一部には、バージョンチェックが含まれています。バージョンが既に同じである場合は、更新を完全に避けます(つまり、そのゴシップを無視します)。

if (Schema.instance.getVersion().equals(currentVersion))
{
    logger.debug("not submitting migration task for {} because our versions match", endpoint);
    return;
}

私たちが話している遅延は1分です:

public static final int MIGRATION_DELAY_IN_MS = 60000;

1分で十分だと思うかもしれませんが、どういうわけか私はいつもエラーが発生します。

実際のところ、彼らのコードは、私のように大きな遅延を含め、複数の変更が次々に発生することを想定していません。したがって、1つのテーブルを作成してから他のことを行う場合は、問題ありません。一方、これらの遅いマシンで20個のテーブルを連続して作成したい場合、以前のスキーマ変更からのゴシップメッセージが遅れて到着します(つまり、新しいCREATE TABLEコマンドがそのノードに到着した後)。そのときにエラーが発生します。 。最悪の部分は、それが誤ったエラーであることです(つまり、それはゴシップが後であったことを示しており、私のスキーマが無効で、ゴシップメッセージのスキーマが古いことではありません)。

org.Apache.cassandra.exceptions.ConfigurationException: Column family ID mismatch (found 122a2d20-9e13-11e6-b830-55bace508971; expected 1213bef0-9e
    at org.Apache.cassandra.config.CFMetaData.validateCompatibility(CFMetaData.Java:790) ~[Apache-cassandra-3.9.jar:3.9]
    at org.Apache.cassandra.config.CFMetaData.apply(CFMetaData.Java:750) ~[Apache-cassandra-3.9.jar:3.9]
    at org.Apache.cassandra.config.Schema.updateTable(Schema.Java:661) ~[Apache-cassandra-3.9.jar:3.9]
    at org.Apache.cassandra.schema.SchemaKeyspace.updateKeyspace(SchemaKeyspace.Java:1350) ~[Apache-cassandra-3.9.jar:3.9]
    at org.Apache.cassandra.schema.SchemaKeyspace.mergeSchema(SchemaKeyspace.Java:1306) ~[Apache-cassandra-3.9.jar:3.9]
    at org.Apache.cassandra.schema.SchemaKeyspace.mergeSchemaAndAnnounceVersion(SchemaKeyspace.Java:1256) ~[Apache-cassandra-3.9.jar:3.9]
    at org.Apache.cassandra.service.MigrationTask$1.response(MigrationTask.Java:92) ~[Apache-cassandra-3.9.jar:3.9]
    at org.Apache.cassandra.net.ResponseVerbHandler.doVerb(ResponseVerbHandler.Java:53) [Apache-cassandra-3.9.jar:3.9]
    at org.Apache.cassandra.net.MessageDeliveryTask.run(MessageDeliveryTask.Java:64) [Apache-cassandra-3.9.jar:3.9]
    at Java.util.concurrent.Executors$RunnableAdapter.call(Executors.Java:511) [na:1.8.0_111]
    at Java.util.concurrent.FutureTask.run(FutureTask.Java:266) [na:1.8.0_111]
    at Java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.Java:1142) [na:1.8.0_111]
    at Java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.Java:617) [na:1.8.0_111]
    at Java.lang.Thread.run(Thread.Java:745) [na:1.8.0_111]
8
Alexis Wilke

誤って同じテーブル名を持つ2つの異なるテーブルスキーマがありました。そのため、この問題が発生しました(私はexpress-cassandraを使用していました)

0
Bamieh