トランザクションアクションの組み合わせ
1 つのトランザクションにどのアクションを一緒に指定してよいか。各サービスの API リファレンスにある組み合わせの表を読む前提となる説明
GS2 が提供するマイクロサービスには、概ねネームスペース設定に transactionSettingV2 というフィールドが存在します。
そのネームスペースが発行するトランザクションをどのように実行するかは、この設定で決まります。
TransactionSettingV2 は以下の構造を持ちます。
| 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 | |
|---|---|---|---|---|---|---|
| distributorNamespaceId | string | ✓ | “grn:gs2:{region}:{ownerId}:distributor:default” | ~ 1024文字 | トランザクションの実行に使用する GS2-Distributor ネームスペース | |
| enableParallelExecution | bool | ✓ | false | アクションを直列ではなく並列に実行するか |
設定する項目はこの 2 つだけです。どちらを選んでも、トランザクションの実行方法に関するそれ以外の項目は推奨構成に固定されているため、次の 3 点は常に成り立ちます。
この 3 点は、トランザクションを発行した API の事前スクリプトにも適用されます。 たとえば商品購入時のスクリプトを設定している場合、そのスクリプトが GS2 の API を呼び出して行ったデータの書き換えや、スクリプトが発行したトランザクションも、商品購入 API が成功したときにまとめて反映されます。
トランザクションの実行に使用する GS2-Distributor のネームスペースを設定します。
用途ごとにトランザクションの実行を分けたい場合を除き、プロジェクトに用意される default ネームスペースのままで問題ありません。
トランザクションに含まれるアクションを 1 件ずつ実行するか、まとめて同時に実行するかを設定します。 実質的に選択の余地があるのはこの項目だけです。
false)各アクションは、先に実行されたアクションの書き込みを踏まえて動作します。 アクションは検証・消費・入手の順に 1 件ずつ実行され、次のことができます。
%{Gs2Xxx:ActionName.path[0].field} を使って、先に実行された検証・消費アクションの結果を、後続の検証・消費・入手アクションの引数として渡す%{...} で参照元にできるのは検証アクションと消費アクションの結果だけで、入手アクションの結果は参照できません。
同名のアクションが複数あるときは、最初に実行されたものが優先されます。
解決できないプレースホルダは引数の値としてそのまま残るため、数値フィールドであれば検証に失敗することがあります。
代償は次のとおりです。
各フェーズの中での実行順は、アクション名、次に対象リソースの順で決まります。 リクエストに並べた順ではないため、並べ替えて実行順を指定することはできません。 なお、消費アクションは名前によらず必ず入手アクションより先に実行されます。
true)アクションは同一のデータスナップショットに対して並列に実行されます。 レスポンスタイムは最も遅いアクション 1 件分で済み、アクション数の上限もありません。
代償は次のとおりです。
database:transaction:same.resource(400)で失敗します%{...} は先行するフェーズ(検証 → 消費 → 入手の順)の結果だけを参照できます。同じフェーズ内のアクションへの参照は解決されずにそのまま残ります。また %{...} を含むフェーズは先行するフェーズの完了を待ってから実行されるため、その分だけレスポンスタイムが伸びます同一トランザクション内で同じデータを 2 つ以上のアクションが書き換えないことを保証できる場合にだけ有効にしてください。
この設定は、トランザクションを発行する時点の挙動を変えません。 同じリソースを対象にしたアクションが 1 件に畳み込まれること、黙って捨てられること、エラーで拒否されることは、直列実行でも並列実行でも同じように発行時に起こります。 変わるのは、アクションが実行に到達したあとの挙動だけです。 どのアクションを 1 つのトランザクションに一緒に指定してよいかは トランザクションアクションの組み合わせ を参照してください。
graph TD
Start["transactionSettingV2 を設定"] --> Q3{"同じデータを 2 つ以上の<br/>アクションが書き換えないと<br/>保証できるか"}
Q3 -- 保証できない --> Sequential["enableParallelExecution = false(既定)"]
Q3 -- 保証できる --> Q4{"先に実行されるアクションの結果を<br/>後続のアクションから参照しているか"}
Q4 -- 同じフェーズ内で参照している --> Sequential
Q4 -- 参照していない、または<br/>先行するフェーズだけを参照している --> Q1{"アクションが 21 件以上になる、または<br/>レスポンスタイムを切り詰めたいか"}
Q1 -- どちらでもない --> Sequential
Q1 -- どちらかに当てはまる --> Parallel["enableParallelExecution = true"]判断に迷う場合は既定の直列実行のままにしてください。 直列実行はトランザクションの組み方に対する制約が最も少なく、並列実行で失敗する組み合わせのほとんどが直列実行では成立します。
なお直列実行では 21 件以上のアクションを発行できないため、アクション数が上限を超えるうえに同じデータへの書き込みも避けられない場合は、トランザクションを分割してください。
TransactionSettingV2 が登場する前は、ネームスペース設定の transactionSetting でトランザクションの実行方法を指定していました。
transactionSetting は非推奨です。TransactionSettingV2 が存在しなかった頃に作成されたネームスペースのために残されており、TransactionSettingV2 が設定されていない間だけ適用されます。
新しく作成するネームスペースでは使用しないでください。
transactionSetting は、トランザクションの実行に関わる要素――自動実行(AutoRun)、アトミック実行(AtomicCommit)、GS2-Distributor を利用した非同期実行、スクリプト結果の一括適用、GS2-JobQueue による入手アクションの非同期化、直列実行――をそれぞれ個別の項目として公開しているため、推奨されない組み合わせも作れてしまいます。
その推奨構成を 1 つの設定としてまとめたものが TransactionSettingV2 です。
TransactionSettingV2 を設定すると、transactionSetting の各項目は次のように固定されます。
transactionSetting の項目 | TransactionSettingV2 での値 |
|---|---|
| enableAutoRun | true |
| enableAtomicCommit | true |
| enableSequentialExecution | enableParallelExecution の否定 |
| transactionUseDistributor | false |
| commitScriptResultInUseDistributor | false |
| acquireActionUseJobQueue | false |
そのため、TransactionSettingV2 を使うネームスペースでは次の 3 つを利用できません。
transactionSetting を使い続けるのは、これらの挙動にすでに依存しているネームスペースに限ってください。
なお、かつてこれらの設定で回避していた競合の多くは、直列実行によって解消します。
事前スクリプトの書き換えとトランザクションの競合は同じリクエスト内の更新が 1 つのコミットへ合流することで、消費アクションと入手アクションの競合や入手アクションどうしの競合は同じ行を複数のアクションから更新できることで、それぞれ回避する必要がなくなります。
1 つのトランザクションにどのアクションを一緒に指定してよいか。各サービスの API リファレンスにある組み合わせの表を読む前提となる説明