6

(状況を明確に説明しながら、この質問をできるだけ短くするように努めます。何か不足している場合はコメントしてください。)

状況

  • 同じデータセンターで 3 台のサーバーを含むクラスターを実行しています
  • 展開を容易にするために、各サーバーはまったく同じアプリケーション コードを実行します。

目的

  • 1 つのサーバーで毎分1 つのタスク (タスク Xと呼びます) を実行すること。

これらの条件下で

  • クラスターは引き続き分散され、高可用性を維持します
  • 各サーバーは同じアプリケーション コードを実行し続けます。つまり、「コード A をマスター サーバーにデプロイし、コード B をすべてのセカンダリ サーバーにデプロイする」というようなことはありません。

サーバーの種類を区別したくない理由は、高可用性 (いわゆるマスターがダウンしたときの問題を回避する)、冗長性 (負荷の分散) を維持し、さまざまなサーバーを展開する必要がある複雑な展開手順を作成することを避けるためです。さまざまな種類のサーバーへのアプリケーション。

なぜこれが難しいのですか?このタスクを 5 分ごとに実行するコードを追加すると、各サーバーが同じアプリケーション コードを実行するため、各サーバーがタスクを実行します。そのため、各ティック中にどのサーバーが同じように実行されるかを調整できる必要があります。

Apache Kafkaまたはなどの分散メッセージング メカニズムを使用できますRedis。そのようなメカニズムを使用してそのようなタスクを調整する場合、そのような「アルゴリズム」はどのように機能しますか?

この質問を他の人に投げかけたところ、彼の答えはタスク キューを使用することでした。ただし、これでは問題が解決しないようです。なぜなら、どのサーバーがタスクをタスク キューに追加するのかという疑問が残るからです。すべてのサーバーがタスクをキューに追加すると、エントリが重複します。さらに、キュー内の次のタスクを実行するのはどのサーバーでしょうか? これらはすべて、異なる種類のサーバーを区別せずに、クラスター内で調整して決定する必要があります。

4

2 に答える 2

3

分散ロックを探しているようです。Redis は でこれを見事に行いsetnxます。と組み合わせると、expireN 秒ごとに解放されるグローバル ロックを作成できます。

setnxキーがまだ存在しない場合にのみ、値を書き込み、true を返します。Redis 操作はアトミックであるためsetnx、キーの有効期限が切れた後に最初に呼び出したサーバーのみがタスクの実行を許可されます。

ルビーでの例を次に示します。

# Attempt to get the lock for 'Task X' by setting the current server's hostname
if redis.setnx("lock:task:x", `hostname`.chomp)
  # Got the lock, now I set it to expire after 5 minutes
  redis.expire("lock:task:x", 60 * 5)
  # This server has the go ahead to execute the task
  execute_task_x
else
  # Failed to get the lock. Another server is doing the work this time around
end

Redis Masterこれにより、を利用しない限り、まだ 1 つのサーバーを呼び出すことに依存していますredis-sentinel。自動フォールオーバーの設定方法については、redis-sentinel のドキュメントを参照してください。

于 2012-10-31T18:11:40.553 に答える
0

JGroupsを使用してこれを実現することもできます。サンプル実装はこちら

于 2014-10-16T16:43:53.837 に答える