roblox-data について
Roblox のデータ永続化、一時的なサーバー間共有状態、クォータを考慮した連携を扱うスキルです。DataStoreService、MemoryStoreService、MessagingService の選択と、並行性、キャッシュ、クォータ、リトライを解説します。
主な機能
- 01永続データのスキーマと移行
- 02データストアと順序付きデータストアの選択
- 03MemoryStore のキュー、マップ、ソート済みマップ
- 04サーバー間メッセージによる連携
- 05並行性、キャッシュ、クォータ、リトライ
活用シーン
- 01プレイヤーデータ保存と移行の設計
- 02マッチメイキングキューや一時共有状態の構築
- 03サーバー間の通知と状態更新の連携
- 04スロットリングや書き込み競合の調査
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ flatbedj/ roblox-skills --skill roblox-dataインストール後、Claude Code で/roblox-dataを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/cross-server-messaging.mddata-store-best-practices.mddata-stores-guides.mddata-stores-vs-memory-stores-comparison.mdmemory-store-best-practices-limits-and-observability.mdmemory-stores-guides.mdversioning-listing-caching-limits-and-observability.md詳細
roblox-data
使用する場面
タスクの主な内容が、Roblox のデータ永続化、サーバー間で共有する状態、またはクォータを考慮した調整に関する場合は、このスキルを使用します。
- プレイヤーの永続的なセーブデータ、グローバルな設定のようなレコード、その他の
DataStoreServiceの使用方法を設計する場合。 - 標準データストアと順序付きデータストアのどちらを使うか選択する場合。
- セーブデータのペイロード、スキーマのバージョン、マイグレーション、メタデータを構成する場合。
SetAsync()、UpdateAsync()、IncrementAsync()、バージョン API のどれを使うか判断する場合。MemoryStoreServiceを使った一時的なサーバー間システムを設計する場合。- メモリストアのキュー、ソートマップ、ハッシュマップのどれを使うか選択する場合。
MessagingServiceを使って複数のサーバーを調整する場合。- スロットリング、リクエスト予算、再試行、バックオフ、競合、可観測性に対処する場合。
- 古い読み取り、キャッシュの動作、冪等性、複数サーバーでの整合性について検討する場合。
タスクの主な内容が次の項目に関する場合は、このスキルを使用しないでください。
- リモートイベントのセキュリティ、クライアントからサーバーへの検証、または一般的なゲームプレイのネットワーク処理。
- OAuth フロー、API キーの設定、または一般的な Open Cloud 認証。
- データサービス以外のエンジン API の幅広い検索。
判断基準
- 数値、文字列、ブール値、テーブル、またはバッファーとして表現できる、セッションをまたいで永続化するデータには標準データストアを使用します。
- 保存する値が数値で、主な要件が永続的なランキングまたはソートされたデータの取得である場合に限り、順序付きデータストアを使用します。
- 関連するフィールドを複数の永続キーに分散させるのではなく、関連オブジェクトごとに 1 つの永続キーに保存する方法を優先します。
- 複数のサーバーが同じキーに書き込む可能性がある場合、または新しい値が現在の値に依存する場合は、
UpdateAsync()を優先します。 - 頻繁に使われる一時的なデータや、調整を目的とする期限切れ可能なデータには、メモリストアを使用します。
- キーによる検索や、多数のキーへのファンアウトには、メモリストアのハッシュマップを使用します。
- 順序が重要な場合や、ソートキーによる範囲読み取りが必要な場合は、メモリストアのソートマップを使用します。
- 順序付きの作業処理、マッチメイキングのキュー、または取得して削除するワークフローには、メモリストアのキューを使用します。
MessagingServiceは、有効期間の短いブロードキャスト信号、ファンアウト通知、または起動の調整に使用し、永続的な信頼できる唯一の情報源としては使用しないでください。- タスクの主な内容がリモート、クライアントへのレプリケーション、または信頼境界に関する場合は、
roblox-networkingに引き継ぎます。 - タスクの主な内容が一般的な実行時の構成やスクリプトの配置に関する場合は、
roblox-coreに引き継ぎます。 - タスクの主な内容がメンバーの検索、シグネチャ、またはクラスの特定に関する場合は、
roblox-apiに引き継ぎます。 - リクエストに対象外の内容が含まれる場合は、データサービスに関する部分のみを回答し、それ以外は除外します。
手順
- サービスを選ぶ前に、状態を分類します。
- セッションをまたいで永続する状態。
- 一時的だが、サーバー間で共有する状態。
- ブロードキャストのみの調整。
- 数値ランキングと、任意の構造化データのどちらか。
- 適合する範囲で、最も用途を絞ったプリミティブを選びます。
- 永続オブジェクトには、標準データストア。
- 永続的な数値ランキングには、順序付きデータストア。
- キーで管理する一時的な状態には、ハッシュマップ。
- 順序付きの一時的な状態には、ソート済みマップ。
- 取得して処理するワークアイテムには、キュー。
- 他の状態から再生成できる通知には、メッセージング。
- 永続保存では、安定したスキーマを定義します。
- 可能であれば、キーごとに自己完結したオブジェクトを1つ保持します。
- 値の中にスキーマバージョンのフィールドを含めます。
- 移行処理は、読み込み時、または読み込み後の初回書き込み時に行います。
- キー、スコープ、ストア名は短く、予測しやすいものにします。
- 同時実行を考慮して書き込みを設計します。
- 競合するキーには、
UpdateAsync()を優先します。 - コールバックは決定的で、yield しないようにします。
- 無効な更新を中止するには、
nilを返します。 - クリアする意図がない場合は、既存のメタデータとユーザー ID を保持します。
- 競合するキーには、
- キャッシュの動作を踏まえて読み込みを設計します。
GetAsync()は短時間、ローカルにキャッシュされるものとして扱います。- 鮮度が追加の予算消費に見合う場合に限り、キャッシュを使用しない読み込みを行います。
- 設計で古いデータを考慮していない限り、別のサーバーから書き込んだ直後に読み込むことは避けます。
- クォータを設計の一部として扱います。
- バースト的な永続書き込みの前に、リクエスト予算を確認します。
- 原子性と予算の使用効率が向上する場合は、関連する永続データを1つのオブジェクトにまとめます。
- メモリストアの TTL は、ユースケースで許容される範囲でできるだけ短くします。
- 処理後は、キューおよびソート済みマップのアイテムを速やかに削除します。
- リトライと障害に備えて設計します。
- ネットワーク呼び出しを
pcall()でラップします。 - 一時的な障害には、指数バックオフで再試行します。
- 多数のサーバーが同時に再試行する可能性がある場合は、ジッターを加えるか、再試行を分散させます。
- 可能な限り、再試行可能な操作を冪等にします。
- ネットワーク呼び出しを
- 可観測性を活用して改善につなげます。
- データストアのリクエスト数、スロットリング、クォータ使用量を監視します。
- メモリストアのメモリ使用量、リクエストユニット使用量、スロットリング状態を監視します。
- ダッシュボードを使って、ボトルネックがグローバルクォータ、キーごとの競合、ホットパーティションのどれにあるかを確認します。
- メッセージングはストレージではなく、調整レイヤーとして使います。
- コンパクトなイベントを発行します。
- 必要に応じて、データストアまたはメモリストアにある信頼できる状態を再読み込みするか、更新します。
- メッセージは遅延または重複する可能性があるものとして扱い、安全なハンドラーを実装します。
- ガイダンスの範囲を守ります。
- 永続化、一時的な共有状態、クォータ、同時実行に焦点を当てます。
- リモートセキュリティ、ゲームプレイネットワーキング、認証フローの話題に逸れないようにします。
リファレンスの使用
- 標準データストアと順序付きデータストアの違い、基本的な CRUD パターン、メタデータ、シリアル化、保存データの形状の決定については、
references/data-stores-guides.mdを開きます。 - 永続スキーマの構成、キーの整理、ストレージの衛生管理、クリーンアップ戦略については、
references/data-store-best-practices.mdを開きます。 - バージョン履歴、プレフィックスによる一覧表示、キャッシュの動作、制限、リクエスト予算、スロットリング、ダッシュボードについては、
references/versioning-listing-caching-limits-and-observability.mdを開きます。 - キュー、ソート済みマップ、ハッシュマップの選択、およびそれぞれの基本的な API パターンについては、
references/memory-stores-guides.mdを開きます。 - TTL 戦略、シャーディング、パーティションへの負荷、リクエストユニットの予算管理、競合への対処、ダッシュボードについては、
references/memory-store-best-practices-limits-and-observability.mdを開きます。 - トピックの設計、パブリッシュ・サブスクライブのフロー、永続状態または一時状態とメッセージングを組み合わせる調整パターンについては、
references/cross-server-messaging.mdを開きます。 - どのサービスクラスがデータを管理するかを最初に判断する場合は、
references/data-stores-vs-memory-stores-comparison.mdを開きます。
チェックリスト
- 状態が永続的、一時的なサーバー間共有、ブロードキャストのみのいずれかに分類されています。
- 選択したサービスが、耐久性と順序の要件に合っています。
- 永続キーでは、明示的なバージョンフィールドを持つ安定したスキーマが使用されています。
- 競合の可能性がある永続書き込みには、
UpdateAsync()が使用されています。 - 順序付きデータストアは、数値ランキングデータにのみ使用されています。
- キャッシュの動作と古いデータを読み取るリスクが考慮されています。
- リクエスト予算、クォータ、スロットリングの動作が設計に含まれています。
- メモリストアの TTL は意図的に短く設定され、クリーンアップの経路が明確になっています。
- 処理後にキュー項目が削除され、古くなったソート済みマップやハッシュマップの項目が整理されています。
- メッセージングは調整に使用され、信頼できる唯一のデータソースとしては使用されていません。
- リトライロジックでは、タイトなループではなく、
pcall()とバックオフが使用されています。 - リモートセキュリティ、OAuth、一般的な API 検索に関する内容は含まれていません。
よくある間違い
- 複数のサーバーから同時に書き込まれる高頻度アクセスキーに
SetAsync()を使用する。 - 十分な理由なく、1 つの永続的なプレイヤープロフィールを、互いに関連のない多数のキーに分割する。
- 構造化されたデータやメタデータの多いレコードに、順序付きデータストアを使用する。
GetAsync()が数秒間、キャッシュされた値を返す場合があることを忘れる。- メモリストアを永続ストレージとして扱う。
- ランダムなキーによるアクセスやスキャンにハッシュマップを使うほうが適しているのに、キューを使用する。
- すべてのハッシュマップのトラフィックを単一の高頻度アクセスキーに集中させ、パーティションのスロットリングを引き起こす。
- 一時的なメモリストア項目に長い TTL を設定し、古いデータでクォータを使い切る。
- 復元可能な状態の唯一の情報源として
MessagingServiceを使用する。 - スロットリングや競合が発生した際にすぐにリトライし、協調的なリトライ集中を引き起こす。
例
適切なサービスを選ぶ
- プレイヤープロフィールの保存:プレイヤーごとに 1 つのオブジェクトをキーとする標準データストア。
- 全期間のコインランキング:プレイヤー識別子をキー、数値を値とする順序付きデータストア。
- マッチメイキングプール:メモリストアのキュー。
- ランキング機能を備えたサーバー間オークションボード:メモリストアのソート済みマップ。
- サーバー ID をキーとする一時的な共有ルームの登録簿:メモリストアのハッシュマップ。
- サーバー間でキャッシュ更新ワークフローを実行する:メッセージを送信し、データストアまたはメモリストアから再読み込みする。
競合する永続保存には UpdateAsync() を使用する
local DataStoreService = game:GetService("DataStoreService")
local profileStore = DataStoreService:GetDataStore("PlayerProfiles")
local function saveCoins(userId, delta)
return profileStore:UpdateAsync(("player/%d"):format(userId), function(current, keyInfo)
current = current or {schemaVersion = 1, coins = 0}
current.coins += delta
return current, keyInfo:GetUserIds(), keyInfo:GetMetadata()
end)
end
状態の保持ではなく、ワーカーの起動にメッセージングを使用する
-- Publish: "queue has work"
-- Receiver: read the queue or map, then process authoritative state there.
コメント
Markdown 対応