ホームページ >データベース >Redis >Redis 分散ロックに基づいてタスク スケジューリングを実装する方法

Redis 分散ロックに基づいてタスク スケジューリングを実装する方法

WBOY
WBOY転載
2023-05-28 13:37:30681ブラウズ

分散大規模データ収集のプロセスでは、情報ソースの管理が特に重要です。同じタスクを同時に 1 つのコレクタのみで処理できるようにするには、タスクのスケジューリングの一意性を確保する必要があります。通常、分散データ収集を実行する場合は、収集タスクを分散し、タスクの一意性を確保することが主な役割であるスケジューリング モジュールが存在します。

分散型であるため、複数のサーバー (複数のマシン) が関与し、各サーバーは複数のコレクター (複数のプロセス) に関与し、各コレクターには複数のスレッドが関与する可能性があります。したがって、タスク内のロック メカニズムはスケジューリングモジュールは特に重要です。アプリケーションの実装アーキテクチャに応じて、ロック実装メソッドは通常、次のタイプに分類できます。

  • ハンドラーが単一プロセスおよびマルチスレッドの場合、Python では、スレッド モジュールの Lock オブジェクトを使用して、共有変数への同期アクセスを制限し、スレッド セーフを実現できます。

  • 単一マシンと複数のプロセスの場合、Python ではマルチプロセッシングの Lock オブジェクトを使用して処理できます。

  • マルチマシンおよびマルチプロセス展開の場合、分散同期ロックを実装するには、サードパーティのコンポーネント (ストレージ ロック オブジェクト) に依存する必要があります。

スケジューリング モジュールはマルチマシン、マルチプロセス、マルチスレッドの処理メカニズムであるため、3 番目の方法と一致します。

#分散ロックの実装方法

現在主流の分散ロックの実装方法は次のとおりです。

  • Based on mysql などのデータベース

  • #redis などのキャッシュに基づく
  • #zookeeper に基づく
それぞれの実装方法にはそれぞれメリットがあり、総合的に検討した結果、Redis が最適です。主な理由は、

  • redis はメモリをベースに動作するため、データベースよりもアクセス速度が速く、同時実行性が高くてもロック後のパフォーマンスがそれほど低下しないためです

  • redis はキー値の生存時間 (TTL) を設定できます

  • redis は使いやすく、全体的な実装オーバーヘッドが低くなります

ただし、redis を使用して実装された分散ロックは、次の条件も満たす必要があります。

  1. 1 つのスレッドのみが占有できる他のスレッドはロックが解放されるまで待機する必要があります

  2. ロック操作はアトミック性を満たす必要があります

  3. デッドロックは発生しません。ロックを取得したときなど スレッドがロックを解放する前に突然異常終了し、他のスレッドがロックの解放をループで待機することになる

  4. ロックは同じスレッドによって設定する必要があります

データの一貫性を確保するために、redis を使用して分散同期ロックを実装します。これは次の特性を満たす必要があります。


  • 相互排他性を満たし、同時にロックを取得できるのは 1 つのスレッドのみです。

  • Redis の ttl を使用してデッドロックが発生しないようにします。が発生しますが、ロックの有効期限による問題も発生します。複数のスレッドが同時にロックを占有するという問題があるため、

  • 使用を避けるために、ロックの有効期限を合理的に設定する必要があります。ロックが誤って削除されないようにするためのロックの一意性


実際の操作プロセスでは、スケジューリング モジュールを分離しました。 Java クライアント Jredis (JRedis は、Redis 分散ハッシュ キー/値データベースに接続するために使用されるハイエンドの高性能 Java クライアントです。Spring Boot を使用して同期および非同期を実装する独立したサービス) に基づいて、コレクション システム全体から収集します。これにより、他のコレクターが HTTP 経由で処理される収集タスクをリクエストできるようになります。処理プロセスは大まかに次のとおりです:

  • コレクターは、HTTP 経由でタスク リクエストをディスパッチング センターに送信します。 ;

  • ディスパッチング センターはロックが存在するかどうかを判断し、存在する場合は空のセットが直接返されます。;

  • ロックが存在する場合は、空のセットが直接返されます。存在しない場合、リクエストはロックされ、ソース ルールに従って対応する収集タスクが取得されます。

  • 取得したタスクを返します (保留中のタスクがない場合は空を返します)

スケジューリング モジュールのコード実装は、大まかに次のとおりです:

public static List fetchTask(String lockKeyValue、RedisHashUtils redisHashUtils、HttpServletRequest request、

HashServiceInterface hif、ZSetServiceInterface zScoreSet、String dicName) {

List();

try {

String dicNameLock = "Dispatcher_Task_Lock";// タスク スケジュール ロック;


if (! redisHashUtils.keyIsExit(dicNameLock, lockKeyValue)) {// ロックが存在するかどうかを確認します

//ロックを追加します (タスクの一意性識別子をレコードに書き込みます);

redisHashUtils.addOneData(dicNameLock, lockKeyValue) ,

DateUtil.getYMDHMS());

// タスクロジックの処理

.......

「」」」」」」の '''''''''' アウト アウト アウト アウト アウト アウト アウト アウト スルー ‐‐‐‐‐‐‐‐hsdi.remove(redisHashUtils, dicNameLock, lockKeyValue);

申し訳ありませんが、書き換える必要がある元の単語が入力されていないため、書き換えは実行できません。 {

//ロックはすでに存在します

System.out.println("タスクの処理中、一時的に空のコレクションを返します....");

申し訳ありませんが、書き換える必要がある元の単語が指定されていないため、書き換えることはできません

} catch (

例外 e) {e.printStackTrace();

}

return result;

}

実際の操作中, ロックを追加するときは、ロックに 有効期限

を追加する必要があります。そうしないと、不明な例外が発生した場合にロックが解放されず、コレクタが収集タスクを取得できなくなる可能性があります。

以上がRedis 分散ロックに基づいてタスク スケジューリングを実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。