-3

チケット システム (PHP/Laravel+Mongo) を使用しており、アクションを適用する必要があるかどうかを確認する必要があります。たとえば、チケットで 12 時間アクティビティがない場合、ステータスを変更し、メール通知を送信します。

foreach ループでデータベースから約 20,000 行を処理し、それぞれに対して定期的に何らかの作業を行う方法について、あなたの経験を共有していただけますか?

今のところ、データベースからすべての行を取得して foreach を実行するだけですが、パフォーマンスに問題があります。

問題#1。システム要件とサーバー制限 このようなタイプのシステムのパターンを探しています。各タスクは有限のマシンであり、私のスクリプトは変更とトグル状態を追跡するスーパーバイザーであるとイメージできます。問題は、20,000 個のアイテムで foreach を実行するときのメモリと CPU です。これは、1,000 個のアイテムごとにサーバーをスケールアップする間違った方法であり、大きくなります。

問題#2。パフォーマンス 各タスクの処理には時間がかかります (状態の確認、次の状態の選択、次の状態に関連するアクションの実行)。メール/SMS/通話の送信など、時間のかかるアクションにはキューを使用します。行数が少ない場合は正常に動作しますが、20K 行の場合、そのために約 10 分の遅延が発生しました。これは非常に重要です。

タスクの状態を同時に管理および切り替えるには、別のアプローチまたはツール (おそらく nodejs ノンブロッキング) を使用する必要があると考えました。

ありがとう

4

1 に答える 1

1

あなたの場合のベストプラクティスだと思うのは、1時間ごとまたは12時間ごとにcronを実行することです(正確にする必要があるかどうかに応じて、ほぼ1時間を目指します)。cron の目的は、過去 12 時間 (updated_at と datetime の間で日付が異なる) に変更されていないレコードをクエリし、結果を配列に取得することです。

この配列 (20k レコードのうち 10k レコードとしましょう) を使用して、単一のクエリでそれらすべてを別のステータスに更新します。その後、ユーザーの電子メールを見つけるために、この配列から user_ids を取得できます (または、ユーザーを内部結合して最初のクエリでユーザーの電子メールを取得し、二次クエリの必要性を回避できます)、キュー システムをセットアップします。このようにして、アプリケーションの残りの部分を危険にさらすことなく、バックグラウンドで動作し続け、電子メールで通知します。

https://laravel.com/docs/5.6/scheduling

https://laravel.com/docs/5.6/notifications

https://laravel.com/docs/5.6/queues

于 2018-05-07T11:24:57.250 に答える