大量のデータを 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 は大容量に対応できるとのことでした。
私の質問:
- 私がしていることに異常はありますか?何か間違っていますか?
- リングを DDoS 攻撃しているだけですか?
- 何が問題なのかをデバッグするにはどうすればよいですか?
- 誤ったクライアント、私見は、サーバーを強制終了することはできません。(そして、上記はひどく間違っているわけではありません。)これを防ぐためにできることはありますか?
¹クライアントは、ファイル記述子もゆっくりとリークしているようです。これは関係ないと思います。(クラスターと接続の両方で呼び出し.shutdown
ています。) ドライバーのソースを見ると、例外によってリークが発生する経路がたくさんあるようです。