クラスターでタスクを1回だけ実行するにはどうすればよいですか?


13

サーバーのクラスターで一度だけ実行したいタスクがある場合、定期的にこれを達成するための最良の方法は何ですか?この場合のクラスターの定義は、ロードバランサーの背後に分散セッションを持つ2つ以上の同一サーバーです。

使用例: X時間に1回のみ実行する必要がある実行コストの高いタスクがあります。このジョブは、たとえば多数のレコードを反復処理し、そのステータスを更新できます。

  • 最悪のシナリオは、ジョブを2回実行するとデータが無効になることです。
  • 最良のシナリオは、ジョブがすべてのサーバー上のリソースを利用することです。

要件の概要:

  1. ノードの1つがダウンしている場合でも、ジョブを実行する必要があります。
  2. ジョブは、スケジュールごとに1回のみ実行する必要があります。
  3. 複数のジョブが同時にまたは重複してスケジュールされている場合、実行中のジョブの数はサーバー間で均等に分散されます。
  4. マシンは同じコードベースを持ち、NTPを介して同期する必要があります。
  5. 環境変数によって、構成はノードごとに異なる場合があります。
  6. ジョブは時間どおりに、または割り当てられた時間の特定の間隔内で開始する必要があります。(たとえば5分と言います)

可能な解決策

  • 1つのノードをマスターノードとして設定します。上記1に違反するため、これは機能しません。
  • ロードバランサーのバランスを取り、ジョブを開始するよう要求します。残念ながら、これには、同時に複数のジョブを実行している場合、それらがすべて同じマシンで実行されるという副作用があります。

これは、Javaのサーブレットコンテナで実行する必要があります。しかし、それは私が探している仕事をコーディングしていません。

確かにこれは既知の最良の解決策を備えた解決された問題です。


関連する質問。 /programming/5949038/schedule-job-executes-twice-on-cluster

上記の5つの要件に従ってソリューションが不十分であるため、これは重複ではありません。最も投票されたソリューションは人種問題に苦しみ、2番目のソリューションは要件3に違反します

回答:


16

共有データベースはありますか?過去にデータベースをアービターとして使用してこれを実行しました。

基本的に、各「ジョブ」はデータベース内の行として表されます。データベースに行を追加することでジョブをスケジュールし、実行する時間を指定すると、各サーバーが実行します。

SELECT TOP 1 *
FROM jobs
WHERE state = 'NotRun'
ORDER BY run_time ASC

そうすれば、彼らはすべて、次に実行するようにスケジュールされているジョブを選択します。それらはすべてスリープ状態にあるため、ジョブが実際に実行されるはずのときに目覚めます。次に、彼らはすべてこれを行います:

UPDATE jobs
SET state = 'Running'
WHERE job_id = :id
  AND state = 'NotRun'

:id上記の手順で取得したジョブの識別子はどこにありますか。更新はアトミックであるため、サーバーの1つだけが実際に行を更新します。データベースの「行の更新数」ステータスコードを確認し、実際に行を更新したサーバーであるかどうか確認できます。これでジョブを実行できます。

「勝たなかった」場合、およびジョブを実行していない場合は、すぐに手順1に戻ります。「勝った」場合は、ジョブを別のスレッドで実行するようにスケジュールし、数秒待ってから手順1に戻ります。この方法では、今回ジョブを取得できなかったサーバーがジョブを取得する可能性が高くなります。すぐに実行するようにスケジュールされています。


1
ここで使用しているisloationレベルは何ですか?コミットまたはシリアル化を読み取​​りますか?
マーベリックリズ

2

いくつかのアプリサーバーには、「クラスター全体のシングルトンサービス」の機能があります。

たとえば、Weblogicには、Web管理コンソールを介して設定されるシングルトンサービス機能があります。

weblogic.cluster.singleton.SingletonServiceを実装するクラスを作成し、それを使用して管理コンソールでサービスを宣言する必要があります。クラスターは、クラスをインスタンス化し、サービスの開始時または停止時に通知します。SingletonServiceインターフェースには、activate()およびdeactivate()メソッドがあります。

WebLogicは、クラスタのノードの1つでサービスを最初に起動するときにactivate()を呼び出します。選択したノードがダウンすると、管理サーバーは別のサーバーでサービスを「移動」し、そこでactivate()を呼び出します。

http://docs.oracle.com/cd/E12839_01/apirefs.1111/e13952/taskhelp/clusters/ConfigureSingletonService.html

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.