mcpField
R
roblox-datastores

roblox-datastores

github.com/nonloopedデータ・データベース25327 回インストール1 週間前に更新
リポジトリ

roblox-datastores について

roblox-datastores は、Roblox の体験でデータを永続化する開発者向けのスキルです。Roblox DataStore API を使ったストア選択、安全な書き込み、復旧、運用上の制限を扱います。

主な機能

  1. 01DataStore の種類の選択
  2. 02安全な UpdateAsync 書き込みパターン
  3. 03プレイヤープロフィールの保存フロー
  4. 04バージョン履歴と復旧
  5. 05キャッシュ、クォータ、監視

活用シーン

  1. 01プレイヤープロフィール用ストアの選択
  2. 02リーダーボードのクエリ作成
  3. 03書き込みエラー後のデータ復旧

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/nonlooped/roblox-suite --skill roblox-datastores

インストール後、Claude Code で/roblox-datastoresを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
best-practices-and-gotchas.md
core-operations-and-patterns.md
limits-quotas-throttling-error-codes.md
types-of-datastores.md
versioning-metadata-recovery.md
scripts/
BudgetMonitor.lua
SafeDataStore.lua
tests/
SafeDataStore.spec.lua

詳細

roblox-datastores

データの永続化はサーバー側で行います。同時書き込みには、純粋な UpdateAsync 変換関数を使用してください。書き込みエラーが発生した場合は、再試行や補償処理を行う前にバックエンドの状態を照合してください。

公式ソース:

一時的なキュー、ロビー、キャッシュには、MemoryStoreService を使用してください。ストアを選ぶ際は、types-of-datastores.md をお読みください。

相互参照:

  • 書き込み前のサーバー権威による検証については、roblox-networking/SKILL.md を参照してください。
  • サービス取得のパターン、pcall の徹底、Luau のシリアル化ルールについては、roblox-core/SKILL.md を参照してください。
  • 購入が永続データに影響する場合(読み込み時に所有権を再検証する場合)については、roblox-gamepasses/SKILL.md を参照してください。
  • ハブ全体と Engine API のリンクについては、roblox/SKILL.md を参照してください。

ストアを選ぶ

  1. データは一時的/短命、高頻度で更新される、またはサーバーが稼働している間だけ必要ですか(キュー、ロビー、レートカウンター、短期キャッシュなど)?
    → MemoryStoreService(キュー、ソート済みマップなど)を使用してください。DataStore は過剰なうえ、より高コストで低速です。リファレンスと公式比較を参照してください。

  2. リーダーボードやランキングのために、数値の並べ替えクエリが必要ですか?
    → OrderedDataStore(GetOrderedDataStore 経由)を使用してください。値は整数でなければなりません。バージョン管理/メタデータには対応していません。GetSortedAsync と DataStorePages による特殊な反復処理を使用します。制限は異なります(リファレンス/制限を参照してください)。

  3. 復旧/監査用のバージョン管理、ユーザー定義メタデータ、キーの一覧表示、またはより豊富な DataStore API(ListKeysAsync、ListVersionsAsync、GetVersionAsync、GetVersionAtTimeAsync)が必要ですか? → DataStoreOptions を指定して GetDataStore で作成する完全な DataStore を使用してください(これにより最新の DataStore クラスが返されます)。本格的なプレイヤーデータには、こちらを推奨します。

  4. 上記の要件がない、シンプルなキーと値による永続ストレージですか?
    → DataStoreService:GetDataStore()(標準の DataStore を返します)または DataStoreService:GetGlobalDataStore()(レガシーなグローバルストア。スコープは "u")を使用してください。新規開発では、名前を指定した GetDataStore ストアを推奨します。

スコープとプレフィックス(最新の推奨事項): 新規開発では、レガシーなスコープよりも、キーのプレフィックス(例:"profiles/User_1234")と ListKeysAsync によるフィルタリングを推奨します。スコープはキーに自動的に先頭追加されます。スコープをまたいで一覧表示するには、DataStoreOptions.AllScopes=true と空のスコープ文字列を使用してください(リファレンスを参照)。

Studio アクセス: Studio からバックエンド API にアクセスする必要がある場合は、専用のテストエクスペリエンスを使用してください。Studio のセッションで本番データの読み取りや書き込みを有効にしないでください。

推奨される安全なワークフロー

プレイヤーデータプロファイルのパターン(最も一般的)

完全な例とバリエーション(セッションロックやプロファイルのパターンを含む)については、references/best-practices-and-gotchas.md を参照してください。

高レベルのサーバーフロー(ServerScriptService のスクリプトから require される ModuleScript 内):

  1. PlayerAdded 時:

    • pcall + GetAsync で読み込みます(以前のサーバーの問題が発生した可能性がある場合は、重要な最新データを読み取るために UseCache=false を検討してください)。
    • デフォルト値とマージします。
    • サーバー側のテーブルまたはプロファイルオブジェクトに保存します(例:playerData[player.UserId] = data)。
    • ゲームパスの特典(収益化スキルを相互参照)やその他の状態を適用します。
    • 必要に応じて、初期 UI 同期のために Remote をクライアントに発火します(クライアントのデータは決して信頼しないでください)。
  2. プレイ中:

    • メモリ内のプロファイルを変更します。
    • 適切な transform を使って UpdateAsync または SetAsync で定期的に自動保存します(30~60 秒ごと)。
    • 重要なイベント(購入、レベルアップ、トレード)時には、安全のため UpdateAsync で直ちに保存します。
  3. PlayerRemoving / BindToClose / キャラクター死亡時:

    • pcall を使って最終保存を行います。
    • メモリ内のデータをクリーンアップします。
    • BindToClose では、最終保存を完了するために最大約 30 秒待機します(Roblox から猶予時間に上限が設けられています)。
  4. 書き込み中にエラーが発生した場合:

    • 検証パターンを使用します。書き込みに失敗したら、再試行/返金/ロールバックを決定する前に、UseCache=false を指定した GetAsync を直ちに実行して、実際のバックエンド状態を確認します。

複数のサーバーから同時に変更される可能性のある値には、純粋な(yield しない)transform 関数を使った UpdateAsync を使用してください。最後に書き込んだ側から見て、読み取りと書き込みがアトミックに行われます。

シリアライズのルール(重要): nil、ブール値、数値(inf/-inf/nan を除く)、文字列(有効な UTF-8)、buffer、およびこれらの型のみを含むテーブルに限ります。関数、保存するテーブル上のメタテーブル、循環参照は使用できません。開発中に問題が疑われるデータに対して HttpService:JSONEncode を使用すると、実際に保存されるデータを確認できます。references/core-operations... を参照してください。

OrderedDataStore を使ったリーダーボード

関連する値の変更時または保存時にデータを登録します(SetAsync または Increment を使用します)。
GetSortedAsync(ascending, pageSize, min?, max?) → DataStorePages でクエリします。GetCurrentPage() + AdvanceToNextPageAsync() を使ってページを反復処理します。
一括読み取りでは、BatchGetAsync(keys) を使って複数の順序付きエントリーを 1 回のリクエストで取得できます。各キーは 1 つの OrderedRead としてカウントされます(クォータについては error-codes-and-limits を参照してください。存在しないキーは省略されます)。 数値のみ使用できます。キーは文字列です。ページ反復処理には独自の制限があり、バージョン管理には対応していません。

ScrollingFrame に表示するか、必要に応じて UI に表示します。クエリを繰り返さずにグローバルにすばやくアクセスしたい場合は、上位 N 件を標準の DataStore にキャッシュします。

ページ反復処理の完全な例と制限の違いについては、references を参照してください。

バージョン管理と復旧

標準の DataStore(Ordered ではないもの)で Set/Update/Increment を行うたびに、時間単位でバージョン管理されるバックアップが作成されます。UTC の各時間内にキーへ最初に書き込むと新しいバージョンスナップショットが作成され、同じ時間内に後続の書き込みを行うと、その時間のバージョンが上書きされます。バージョン管理されたバックアップは、置き換えられてから約 30 日後に期限切れとなります。現在のバージョンに期限はありません。

  • ListVersionsAsync(key, sort, minDate?, maxDate?, pageSize?)
  • GetVersionAsync(key, version)
  • RemoveVersionAsync は 非推奨 です。現在のクリーンアップ API として紹介しないでください。復旧のためにバージョンを保持し、確認には ListVersionsAsync、GetVersionAsync、または GetVersionAtTimeAsync を使用してください。
  • GetVersionAtTimeAsync(key, timestampMillis):過去の特定時点で有効だったバージョンを検索します。
  • 元に戻すには、目的のバージョンを読み取り、その値とメタデータを SetAsync で書き戻します(これにより新しい現在のバージョンが作成されます)。

また、リスクのある公開を行う前には、日次 Snapshot Data Stores Open Cloud API を使用してください。

Creator Hub の Data Stores Manager では、キーの参照、メタデータ/バージョン履歴の表示、バージョンの比較、および適切な権限での復元ができます。

「インシデント発生時点に戻す」パターンを含む完全なコードサンプルについては、references/versioning-metadata-recovery.md を参照してください。

キャッシュの制御

デフォルトでは、GetAsync の結果はローカルに 4 秒間キャッシュされます。この期間内の後続の Get はキャッシュを返し、制限にはカウントされません。書き込みを行うと、キャッシュは即座に更新されます。

書き込み後の確認(特にエラー発生後)や、ほかのサーバーの影響で古いデータになっている疑いがある場合:

local opts = Instance.new("DataStoreGetOptions")
opts.UseCache = false
local value, info = store:GetAsync(key, opts)

これは常にバックエンドにアクセスし、クォータにカウントされます。必要な場合に限り、適切に使用してください。

references/versioning-metadata-recovery.md(一覧表示、キャッシュ、シリアル化)と references/best-practices-and-gotchas.md を参照してください。

制限、クォータ、スロットリング、予算

エクスペリエンスレベルの制限(エクスペリエンス全体の同時ユーザー数に応じて増加)と、サーバーごとの制限(DataStoreService:SetRateLimitForRequestType で設定可能)があります。エクスペリエンスレベルのプールは、ゲームサーバーと Open Cloud v2 の Data Store トラフィックで共有されます。外部からの一括処理によってライブプレイヤーがスロットリングされることも、その逆もあります。

UpdateAsync は読み取り予算と書き込み予算の両方にカウントされます。

大規模な処理の前には DataStoreService:GetRequestBudgetForRequestType(Enum.DataStoreRequestType.XXX) を使用して確認し、必要に応じてループ内で待機してください。

キューがあります(サイズ 30)。キューがいっぱいになると、スロットリングエラー(301~306 の範囲、または新しい *Throttled エラー)が発生します。

すべてのエラーコード(101 KeyNameEmpty から、すべての *ExperienceThrottled および *GameServerThrottled の各種エラーまで)の完全な一覧、エクスペリエンスレベルの計算式(基本値 300 + 同時ユーザー数 × N)、サーバー側のエラーについては、references/limits-quotas-throttling-error-codes.md を参照してください。

可観測性ダッシュボード(Creator Hub → Monitoring → Data Stores)には、API/ステータス別のリアルタイムリクエスト数、クォータ使用率、ストレージ容量と上限が表示されます。

Data Stores Manager には、合計サイズとストレージ上限(500 MB + 1 MB × lifetime users。最新バージョンの圧縮後のサイズで計測)、Data Store ごとのキー数などが表示されます。書き込み前に値を事前圧縮しないでください。

移行スクリプトや負荷の高いサーバーの制限を引き上げるには、サーバーの初期化時に SetRateLimitForRequestType を(種類ごとに 1 回)早めに呼び出してください。基本値 +(プレイヤーごとの値 × プレイヤー数)となります。種類ごとの制約については、ドキュメントを参照してください。

結果が不確定な書き込みへの対処

データストアへの呼び出しはすべて pcall の内側で実行する必要があります。

失敗した場合:

  • 具体的なエラーコード/メッセージを記録します。
  • 読み取りは、上限付きの指数バックオフとジッターを使って再試行します。
  • 呼び出した書き込みがエラーを返した場合は、拒否されたのではなく不明として扱います。UseCache = false を指定した新しい GetAsync で状態を確認します。
  • 書き込みの操作全体が冪等であると呼び出し元が証明した場合に限り、書き込みを再実行します。IncrementAsync は決して自動的に再実行しないでください。
  • 購入/復旧コードが曖昧な状態を失敗と誤認しないよう、committed、rejected、unknown のいずれかを明示的に返します。

Set/Update/Increment が失敗しても、変更が「発生しなかった」と決めつけてはいけません。UpdateAsync の変換関数は複数回実行されることがあり、yield したり、外部に副作用を発生させたりしてはいけません。

RemoveAsync は「tombstone」を作成し(Get は nil を返します)、明示的に削除されない限り、以前のバージョンは 30 日間クエリ可能です。

管理と監視
  • Data Stores Manager(Creator Hub)を使用して、データの確認、プレフィックスによるキー検索、バージョンの比較/復元、削除のスケジュール設定(クールダウンあり)を行います。Manager のRevertボタンでは、個々のキーを以前のバージョンに戻せます。Restoreボタンは、削除対象としてマークされたデータストアに使用するもので、キーの値を戻すものではありません。クールダウン中に削除されたキーを復元するには、Engine API の UpdateAsync または Open Cloud の UpdateDataStoreEntry を呼び出す必要があります。
  • トレンドの把握とクォータ予測には、可観測性ダッシュボードを使用します。
  • 一括削除/移行には、Open Cloud Data Stores APIs または公式の Batch Processor CLI/ツールを使用します。
  • ストレージ上限への接近/超過に関する通知を設定します。
  • 使用状況を定期的に確認します。

references/versioning-metadata-recovery.md(一覧表示/キャッシュについて)と、Manager および可観測性の各ページ(best-practices-and-gotchas.md からリンクされています)を参照してください。

チェックリスト

重要な書き込みを行う前に:

  • pcall で囲み、コミット済み/拒否/不明の各状態を明示的に処理している
  • 競合が発生しうる場合は、純粋な変換関数を使って UpdateAsync を使用している
  • 適切な場合、RTBF/GDPR の追跡用に userIds 配列を指定している
  • フル DataStore を使用する場合、変更がなくても、すべての書き込みでメタデータを指定している
  • 値がシリアライズ可能である(開発中に JSONEncode でテストする)
  • キー名のプレフィックスに一貫性があり、簡単に一覧表示できる

プレイヤーの参加/ロード時:

  • 適切に、新規ロードまたはキャッシュを考慮したロードを行っている
  • デフォルト値を安全にマージしている
  • PlayerAdded で所有権を再確認し(ゲームパスなど)、未所有の一度限りの消費型付与を再適用している
  • クライアントには機密情報を含まない派生状態のみを同期している

リスクの高いデータロジックの変更を公開する前に:

  • 利用可能であれば、Open Cloud を使って毎日スナップショットを取得する
  • コピーしたエクスペリエンスで十分にテストする

継続的に:

  • ダッシュボードとマネージャーを監視する
  • テストデータや一時データを削除する
  • サーバーの終了後に保持する必要のないデータには MemoryStores を使用する
  • データストアの数を減らし、まとまりのある大きなオブジェクトとキーのプレフィックスを優先する

よくある間違い

  • クライアント/LocalScript から呼び出す(即時エラーとセキュリティ上の脆弱性につながります)。
  • 関数、メタテーブル、またはシリアライズできないデータを保存する。
  • 競合する値に SetAsync を使う(競合状態により、更新の消失や重複が発生します)。
  • スロットリングエラーを無視して大量にリクエストする(リクエストの破棄やプレイヤーの不満につながります)。
  • ライブのプレイスで Studio の API アクセスをハードコードする。
  • キー/プレフィックスで整理せず、数百もの小さなデータストアを作成する。
  • 書き込み後の検証に、キャッシュされた Get の結果を使う。
  • OrderedDataStore にはバージョン管理がなく、整数のみを扱うことを忘れる。
  • RemoveAsync がすでに呼び出されている場合(nil と tombstone)を処理しない。
  • 監視せずにストレージクォータを超過する(予想外のコストや書き込み失敗につながります)。

Scripts フォルダーの使用方法

scripts/ ディレクトリには、成熟度ラベル付きのサンプルが含まれています:

  • SafeDataStore.lua:自動読み取り再試行、明示的な書き込み状態、オプトインの冪等な再実行、キャッシュを使わない照合を備えたレビュー済みサンプルです。
  • BudgetMonitor.lua:予算を検査する実験的なサンプルです。

専用のテストエクスペリエンスでこれらを適用して検証してください。このディレクトリは、バージョン管理された本番用ライブラリではありません。

実際の進め方

  1. 実装する機能に該当する references/ ファイルを読み、正確な仕様を確認します。
  2. ここおよび references に記載されたパターンとコードサンプルを使って実装します。
  3. 負荷をかけて予算の動作をテストします(複数のテストサーバーを使用するか、レート制限設定機能でシミュレーションします)。
  4. 可観測性とアラートを早い段階で追加します。
  5. Manager/Dashboard でストレージの増加をプロファイリングします。

永続化システムを信頼する前に、このガイダンスと静的解析、重点的なテスト、Studio での統合、可観測性、および最新の公式情報を組み合わせてください。

特定のメソッドの正式なクラス/プロパティリファレンスについては、必ず https://create.roblox.com/docs/reference/engine を参照し、DataStoreService、GlobalDataStore などを検索してください。

リファレンス一覧

コメント