web-dev-qa-db-ja.com

終了日がなく動的に変化する定期的なタスクを処理するための最も簡単で柔軟なスケーリング方法は何ですか?

問題:
私はLaravel 6.2でサービスを書いています。このサービスは、指定された時間に分単位でプッシュ通知をさまざまなユーザーに送信します。ユーザーは、月、週に何回を選択するか、または日付とその時刻に通知を受け取りたいと思っています。最初は、曜日(0〜6)とUTCタイムスタンプ(16:00:00)を保存し、Artisanコマンドを毎分実行して、その分のスケジュールを確認してください。

私が知る限り、私が取ることができる2つの主要なルートがありました:

  • 計算:各リマインダーが発生する頻度間隔と日付/時刻を保存します。
    • Pro:データベースを軽量に保ちます。
    • Con:毎分重い計算であり、データベースが大きくなると問題になる可能性があります。
  • 長期保存:頻度間隔をキャプチャし、これが発生するのに必要な実際の日付/時刻を保存します。
    • Pro:計算量を増やします。
    • Con:データベーステーブルにすばやく入力し、最終的にクエリを本当に遅くします。

アイデアと探査:

  1. Laravelタスク- https://laravel.com/docs/6.x/scheduling
    • Con:Kernel.phpファイルで各スケジュールを宣言せずに、スケジュールを十分に動的にすることができるかどうかわかりません。
  2. RRuleパッケージ- https://github.com/rlanvin/php-rrulehttps://github.com/simshaun/recurrhttps:/ /packagist.org/packages/jpmurray/laravel-rrule
    • RRuleをDBに保存してから、それらのタスクを動的にスケジュールします。
    • Con:これが効率的かベストプラクティスかはわかりません。
  3. 定期的なタスクの動的頻度をDBに保存してから、Laravelタスクスケジューリングの多くを動的にスケジュールする方法を考え出し、サーバーが再起動してこれらのタスクを動的cronとして再ロードする場合タスク。
    • Con:これが可能かどうかわからない。
  4. Laravelスヌーズパッケージ- https://github.com/thomasjohnkane/snooze
    • Con:将来のスケジューリングは1回だけ行われるようです。最初の実行時に別の呼び出しをチェーンしたくありません。それは矛盾しているようです。
1
SaundersB

ステップ1:ユーザーの操作

ユーザーがスケジュールを保存するときに、 CRONタブ形式 で保存してみてください。 「0 0 1 * *」のようなもの。

このストリングをエンコード/デコードしてタイムスタンプを提供できる多くのPHPライブラリが見つかります。これは、最も柔軟なスケジュール方法です。将来的には、いくつかの利用可能なライブラリの場合、このスケジュールをライブラリが期待する形式に変換するのは簡単です。

そのスケジュールをデータベーステーブルに保存します-notification_schedulesと言うと、ユーザーの操作は完了です。このステップでは計算はありません。

ステップ2:現在の時刻に一致するスケジュールを計算するためのスクリプト

次に、notification_schedulesからすべてのレコードをスキャンし、その時点で通知を送信するのに適したレコードを見つけるスクリプトを毎分実行します。レコードが適格である場合は、別のテーブルにレコードを作成します-notification_deliveryなど。 rabbitmqのようなメッセージングアーキテクチャがある場合は、メッセージを作成することをお勧めします。

ステップ3:配信パイプラインを生成するスクリプト

notification_deliveryを読み取って通知を送信する2つ目のスクリプトを追加します。通知が送信されたら、フラグを付けてレコードを更新するか、レコードを削除します。このnotification_deliveryには、配達予定の場合にのみアクティブレコードがあります。

ここでは、作業を3つの非同期部分に分割しています。柔軟で疎結合にします。

2