GS2-Lock
GS2-Lock は、リソース単位で動作するミューテックスを提供し、複数のサーバープロセス・複数の処理系から同一リソースへ同時にアクセスすることを防ぐための分散排他制御サービスです。
ゲームの運営では「同じプレイヤーに対して同じ処理を二重に実行してしまう」「異なるバックエンドサーバーが同じデータを同時に書き換えてしまう」といった問題が容易に発生します。GS2-Lock を利用すると、これらの問題をマイクロサービスとして提供される共有ミューテックスによって防ぐことができます。
ミューテックスの基本
GS2-Lock のロックは「ネームスペース」「ユーザーID」「プロパティID」の組み合わせによって識別される「ミューテックス」というリソースに対して取得します。
プロパティID には、排他制御を行いたいリソースを一意に識別する任意の文字列を指定します。例えば「ガチャの抽選処理」「アイテムの所持数更新」「外部連携への通知送信」など、二重実行を避けたい処理ごとに異なるプロパティIDを割り当てる運用が考えられます。
graph TD Server1["バックエンドサーバーA"] -->|Lock| Mutex["GS2-Lock<br/>ミューテックス"] Server2["バックエンドサーバーB"] -->|Lock 待機| Mutex Mutex -->|取得成功| Server1 Server1 -->|Unlock| Mutex Mutex -->|取得成功| Server2
トランザクションID
ロックを取得する際にはトランザクションIDを指定します。同じトランザクションIDで同じミューテックスに対して再帰的にロックを取得した場合、参照カウントが加算されるリエントラントロックとして振る舞います。解放時には同数の Unlock を実行することでロックが完全に解放されます。
異なるトランザクションIDによる二重取得は競合となり、先に取得したセッションがロックを解放するまで待機状態となります。
TTL による自動解放
ロックには TTL (Time To Live) を設定でき、TTL を経過するとロックは自動的に解放されます。
これにより、ロックを取得した処理系が異常終了したり、ネットワーク障害でロック解放処理が呼び出されなかった場合でもデッドロックを防ぐことが可能です。TTL は処理の最大想定実行時間に応じて適切な値を設定してください。
マルチタイトル・複数バックエンド間での排他
GS2-Lock は GS2 のマイクロサービスとして提供されるため、マルチタイトル間や複数のバックエンドサーバー、複数のリージョン間で共通の排他制御を実現できます。
GS2-Script から呼び出すことで、サーバーサイドスクリプトの内部から他のスクリプト実行や外部処理との排他制御を行うことも可能です。
トランザクションアクション
GS2-Lock ではトランザクションアクションを提供していません。
マスターデータ管理
GS2-Lock ではマスターデータの登録はありません。ネームスペースを作成するだけで利用を開始できます。
実装例
GS2-Lock は管理API/サーバーサイドAPI中心のマイクロサービスです。ゲームエンジン用 SDK (Unity/Unreal Engine) には専用の Domain クラスが提供されていません。
主に GS2-Script 内のサーバーサイドロジックや、自社のバックエンドサーバーから利用することを想定しているため、ゲームクライアントから直接呼び出すのではなく、以下のいずれかの手段で操作することを推奨します。
- GS2-Script からの呼び出し (サーバーサイドスクリプト経由の排他制御)
- 各種言語向け一般SDK (C# / Go / Python / TypeScript / PHP / Java) によるバックエンドサーバーからの呼び出し
- マネジメントコンソール (動作確認・運用時)
- GS2 CLI
各種SDKの詳細は対応するリファレンスページを参照してください。
より実践的な情報
二重実行防止のパターン
オンラインゲームでは、ネットワークの不安定さからプレイヤーが同じリクエストを短時間に複数回送信することがあります。このようなリクエストをサーバー側で受け入れてしまうと、アイテムの二重付与などにつながります。
トランザクションIDをリクエストごとに発行し、GS2-Lock で短時間の TTL を持つロックを取得することで、同じトランザクションIDによる重複処理は参照カウントとして扱われ、異なるリクエストとして受け取った同種の処理は競合として弾くことができます。
バックエンド間の整合性確保
複数のバックエンドサーバーが共通のリソースに対して書き込みを行うシナリオでは、GS2-Lock でリソース単位のミューテックスを取得した上で読み取り・更新・書き込みを行う設計が有効です。プロパティIDにリソースの識別子を埋め込むことで、リソースごとの細粒度な排他制御を実現できます。