3

Python GAE SDK を使用しています。

の 6000 以上のインスタンスに対して実行する必要がある処理がありますMyKind。1 回のリクエストで処理するには遅すぎるため、タスク キューを使用しています。1 つのタスクで 1 つのエンティティのみを処理する場合、数秒しかかかりません。

ドキュメントによると、「バッチ」で追加できるタスクは 100 個までです。(それはどういう意味ですか? 1 つの要求で? 1 つのタスクで?)

そこで、「バッチ」が「リクエスト」を意味すると仮定して、データストア内のエンティティごとにタスクを作成する最善の方法を見つけようとしています。どう思いますか?

MyKindの順序が決して変わらないと仮定できれば簡単です。(処理によって実際にMyKindインスタンスが変更されることはありません。他のタイプの新しいインスタンスが作成されるだけです。) 100 未満の間隔で、開始する場所のオフセットをそれぞれに与えて、一連のタスクを作成できます。次に、各タスクは、実際の処理を行う個別のタスクを作成できます。

しかし、非常に多くのエンティティがあり、元の要求で必要なすべてのスケジューリング タスクを追加できない場合はどうなるでしょうか? これにより、再帰的な解決策が必要だと思います。各タスクは、与えられた範囲を調べます。範囲内に要素が 1 つしかない場合は、その要素に対して処理を行います。それ以外の場合は、範囲を後続のタスクにさらに分割します。

エンティティを識別するためにオフセットと制限を使用することを期待できない場合 (順序が一定であることが保証されていないため)、それらのキーを使用することはできますか? しかし、その後、何千ものキーを送信する可能性があり、扱いにくいようです.

ここで正しい道をたどっていますか、それとも検討すべき別の設計がありますか?

4

2 に答える 2

9

taskqueue.add(url='/worker', params={'cursor': cursor})タスクをエンキューしているようにコードを実行すると; 指定したパラメータを使用して帯域外で実行するようにリクエストをスケジュールします。1 回の操作で最大 100 個までスケジュールできるようです。

でも、あなたはしたくないと思います。タスク チェーンを使用すると、これがはるかに簡単になります。

ワーカー タスクは次のようになります。

  • クエリを実行して、処理するレコードを取得します。タスク パラメータでカーソルが指定されている場合は、それを使用します。クエリを 10 レコードに制限するか、30 秒で終了できると思われるものに制限します。

  • 10 件のレコードを処理する

  • クエリが 10 件のレコードを返した場合は、別のタスクをキューに入れ、クエリから更新されたカーソルを渡して、中断したところから再開できるようにします。

  • 取得したレコードが 10 件未満の場合は、完了です。万歳!メールか何かを発射して終了します。

このルートでは、最初のタスクを開始するだけでよく、残りは自分自身を追加します。

タスクが失敗した場合、App Engine は成功するまで再試行するため、1 つのタスクがタイムアウトしてチェーンが壊れる原因となるデータストアの問題について心配する必要はありません。

編集:

上記の手順は、エンティティが 1 回だけ処理されることを保証するものではありません。通常、タスクは 1 回だけ実行する必要がありますが、べき等性を考慮して設計することをお勧めします。それが大きな懸念事項である場合は、次の 1 つの方法で対処できます。

  • 処理する各エンティティにステータス フラグを付けるか、フラグを保持する補足エンティティを作成します。保留中、処理中、処理済みなどの状態が必要です。

  • 処理する新しいエンティティをフェッチするときは、トランザクションでロックし、処理フラグをインクリメントします。保留中のエンティティのみを実行します。処理が終了したら、フラグを再度インクリメントします。

開始する前にすべてのエンティティに処理フラグを追加する必要はありません。「保留中」の状態は、プロパティまたは対応するエンティティがまだ存在しないことを意味する場合があります。

于 2010-07-12T02:36:45.983 に答える
0

また、デザインによっては、処理が必要なすべてのレコードに番号を付けるという、私が行ったことを行うこともできます。私は約 3500 個のアイテムを処理していますが、それぞれの処理に 3 秒ほどかかります。オーバーラップやタイムアウトを回避し、将来の拡張を考慮して、最初のタスクはデータベースからその種類のすべての一意のアイテムのリストを取得します。次に、それを 500 個の各アイテム ID のリストに分割し、データベース内のすべての一意のアイテムを説明するまでループし、500 個の ID の各チャンクをハンドラー タスクの第 2 層にポストします。2 番目のハンドラー タスク (現在は 7 つまたは 8 つの異なるタスク) のそれぞれには、500 項目の一意のリストがあり、これらの各ハンドラー タスクは、一意の識別子ごとに 1 つずつ、500 のタスクを追加します。

データベース内の一意のアイテムの数に基づいてループとカウントによってすべて管理されるため、必要な数の一意のアイテムを追加でき、タスクの数は重複することなくそれらに対応するように拡張されます。私は日常的にゲームの価格を追跡するために使用しているため、すべて cron ジョブを使用して起動され、私の側で介入する必要はまったくありません。

于 2011-01-29T19:01:57.040 に答える