0

大量のデータを 10 ノードの Cassandra リングにロードしようとしています。

挿入を行うスクリプトは、おそらくネットワーク I/O でブロックされ、1 秒あたり最大 4000 回の挿入を取得します。これらのうち 8 つを 1 台のマシンで起動すると、スループットはほぼ直線的に増加します。(個々のスループットはわずかに低下しますが、追加のプロセスによって十分に補われます。)

これはうまく機能しますが、まだ十分なスループットが得られないため、さらに 3 つの VM で同じセットアップを開始しました。(したがって、8 プロセス * 4 VM) 最初の追加の VM の後、さらに VM が追加されるにつれて頻度と重大度が増加すると、次のことが発生します。

  • クライアントはタイムアウト エラーを受信し始めます。書き込みを再試行できますが、バッチで行うため、進行状況はほぼ完全に排除されます。
  • リングが不安定になり、ノードは自分自身を「ダウン」とラベル付けし始めます。さらに、ノードが異なれば、誰がダウンしているかについての考えも異なる傾向があります。スクリプトが中止されると、リングは回復しません。(個々のノードを再起動するだけではこれを修正できませんでした。リング全体を再起動する必要がありました。)

「ダウン」はさまざまです。私の最後の実行で:

  • 4 つのノードが完全に停止しました。(Cassandra はまったく実行されていませんでした。) ログを確認したところ、なぜ停止したかについては何も記録されていないようでした。
  • 5 日目、カサンドラは走っていました。nodetool statusそのノードでハングします。2 つのスレッドが何らかの無限ループに入っているように見えます。(彼らは 100% の CPU をしっかりと使用しています。)java.lang.OutOfMemoryError: Java heap spaceログに があります。

コードは基本的に次のとおりです。

def prepped_batch_insert(session, items, insert_query, silent=False):

    # A mapping of number of inserts -> a prepared query for that number of
    # inserts.
    prepped_statements = {}

    def get_prepped_statement(inserts):
        if inserts in prepped:
            # We already created a prepared query for this many inserts, use
            # it:
            return prepped_statements[inserts]
        else:
            # We haven't yet created a prepared query for this many inserts, so
            # do so now:
            query = ['BEGIN UNLOGGED BATCH']
            for idx in xrange(inserts):
                query.append(insert_query.query)
            query.append('APPLY BATCH;')
            query = '\n'.join(query)
            ps = session.prepare(query)
            prepped_statements[inserts] = ps
            return ps

    def do_prepped_batch_insert(batch)
        ps = get_prepped_statement(len(batch))

        # Generate the list of params to the prepared query:
        params = []
        for idx, item in enumerate(batch):
            for k in insert_query.keyorder:
                params.append(item[k])
        # Do it.
        session.execute(ps, params)

    return inserter.insert_and_time(
        items,  # data generator
        do_prepped_batch_insert,  # The above function
        _WHAT_APPEARS_TO_BE_THE_OPTIMAL_CASSANDRA_BATCH_SIZE,  # = 200
        silent=silent,
    )

この関数はサイズ 200 のバッチにinsert_and_time分割itemsし、上記の関数を呼び出して、キット全体と kaboodle の時間を計測します。(このコードはリングにとって有害で​​す。)

さらに読み込みを試みたのは、1 秒あたり 20,000 回の挿入は遅かったため (その速度で挿入したいデータを挿入するには時間がかかるとのことでした…)、Cassandra は大容量に対応できるとのことでした。

私の質問:

  1. 私がしていることに異常はありますか?何か間違っていますか?
  2. リングを DDoS 攻撃しているだけですか?
  3. 何が問題なのかをデバッグするにはどうすればよいですか?
  4. 誤ったクライアント、私見は、サーバーを強制終了することはできません。(そして、上記はひどく間違っているわけではありません。)これを防ぐためにできることはありますか?

¹クライアントは、ファイル記述子もゆっくりとリークしているようです。これは関係ないと思います。(クラスターと接続の両方で呼び出し.shutdownています。) ドライバーのソースを見ると、例外によってリークが発生する経路がたくさんあるようです。

4

2 に答える 2