データをバージョン管理、リスト表示、およびキャッシュを使用して管理します。
バージョン管理
バージョン管理は、データを設定、更新、およびインクリメントするときに行われます。関数 SetAsync()、UpdateAsync()、および IncrementAsync() は、各UTCの時間に各キーへの最初の書き込みを使用して、データのバージョン付きバックアップを作成します。同じUTCの時間にキーへの連続した書き込みは、前のデータを永続的に上書きします。
バージョン付きバックアップは、新しい書き込みがそれを上書きしてから30日後に期限切れになります。最新のバージョンは決して期限切れになりません。
以下の関数がバージョン管理操作を実行します。
| 関数 | 説明 |
|---|---|
キーのすべてのバージョンをリスト表示し、すべてのバージョン番号を列挙するために使用できる DataStoreVersionPages インスタンスを返します。時間範囲を使用してバージョンをフィルタリングできます。 | |
キーのバージョン番号を使用して特定のバージョンを取得します。 | |
特定のキーのバージョンを削除します。 この関数は、前のバージョンを保持しながらトムストーンバージョンを作成します。たとえば、RemoveAsync("User_1234") を呼び出し、その後 GetAsync("User_1234") を呼び出そうとすると、nil が返されます。しかし、ListVersionsAsync() および GetVersionAsync() を使用してデータの古いバージョンを取得することはできます。 |
バージョン管理を使用してユーザーリクエストを処理できます。ユーザーが2020-10-09T01:42 に問題が発生したと報告した場合、次の例を使用してデータを以前のバージョンに戻すことができます:
local DataStoreService = game:GetService("DataStoreService")
local gameStore = DataStoreService:GetDataStore("PlayerGame")
local DATA_STORE_KEY = "User_1234"
local maxDate = DateTime.fromUniversalTime(2020, 10, 09, 01, 42)
-- 指定された時間に最も近いバージョンを取得
local listSuccess, pages = pcall(function()
return gameStore:ListVersionsAsync(DATA_STORE_KEY, Enum.SortDirection.Descending, nil, maxDate.UnixTimestampMillis)
end)
if listSuccess then
local items = pages:GetCurrentPage()
if #items > 0 then
-- 最も近いバージョンを読む
local closestEntry = items[1]
local success, value, info = pcall(function()
return gameStore:GetVersionAsync(DATA_STORE_KEY, closestEntry.Version)
end)
-- 最も近いバージョンで上書きして現在の値を復元
if success then
local setOptions = Instance.new("DataStoreSetOptions")
setOptions:SetMetadata(info:GetMetadata())
gameStore:SetAsync(DATA_STORE_KEY, value, nil, setOptions)
end
else
-- エントリが見つかりませんでした
end
end
スナップショット
スナップショットデータストアオープンクラウドAPIを使用すると、ゲーム内のすべてのデータストアのスナップショットを1日に1回取得できます。データストレージロジックを変更するゲームの更新を公開する前に、スナップショットを取得してください。スナップショットを取得すると、前のバージョンのゲームから最新のデータを保証できます。
たとえば、スナップショットを持たない場合、3:30 UTCにデータが破損する更新を公開すると、破損したデータが3:00-3:30 UTCの間に書き込まれたデータを上書きしてしまいます。しかし、3:29 UTCにスナップショットを取得すれば、破損したデータは3:29 UTC以前に書き込まれたデータを上書きせず、3:00-3:29 UTCの間に書き込まれたすべてのキーの最新データが保存されます。
リスト表示とプレフィックス
データストアは、プレフィックスによるリスト表示を許可します。たとえば、名前の最初の n 文字でリスト表示することができ、キーやプレフィックスが「dog」のデータストアに対して「d」、 「do」、または「dog」を使用します。
すべてのデータストアまたはキーをリスト表示する際にプレフィックスを指定し、そのプレフィックスに一致するオブジェクトのみを取得できます。ListDataStoresAsync() および ListKeysAsync() の両方の関数は、リストを列挙するために使用できる DataStoreListingPages オブジェクトを返します。
| 関数 | 説明 |
|---|---|
| ListDataStoresAsync() | すべてのデータストアをリスト表示します。 |
| ListKeysAsync() | データストア内のすべてのキーをリスト表示します。 |
スコープ
データストア内のキーをさらに整理するために、GetDataStore() の第2パラメータとして一意の文字列をスコープとして設定できます。デフォルトのスコープ(スコープが指定されていない場合)は global です。このスコープは、データストアに対して行うすべての操作のすべてのキーの先頭に自動的に追加されます。
| キー | スコープ |
|---|---|
| houses/User_1234 | houses |
| pets/User_1234 | pets |
| inventory/User_1234 | inventory |
データストア名、スコープ、およびキーの組み合わせは、キーを一意に識別します。この3つの値は、スコープを持つキーを識別するために必要です。たとえば、スコープが global の User_1234 というキーは次のように読み取れます:
local DataStoreService = game:GetService("DataStoreService")
local inventoryStore = DataStoreService:GetDataStore("PlayerInventory")
local success, currentGold = pcall(function()
return inventoryStore:GetAsync("User_1234")
end)
しかし、キー User_1234 にスコープ gold がある場合、次のようにのみ読み取りが可能です:
local DataStoreService = game:GetService("DataStoreService")
local inventoryStore = DataStoreService:GetDataStore("PlayerInventory", "gold")
local success, currentGold = pcall(function()
return inventoryStore:GetAsync("User_1234")
end)
AllScopes プロパティ
DataStoreOptions には、すべてのスコープからキーをリストとして返す AllScopes プロパティが含まれています。次に、リストアイテムの KeyName プロパティを使用して、データの読み取りを GetAsync() として、データの削除を RemoveAsync() で行うことができます。
AllScopes プロパティを使用する場合、GetDataStore() の第2パラメータは空の文字列 ("") でなければなりません。
local DataStoreService = game:GetService("DataStoreService")local options = Instance.new("DataStoreOptions")options.AllScopes = truelocal ds = DataStoreService:GetDataStore("DS1", "", options)
AllScopes プロパティを有効にしてデータストアに新しいキーを作成する場合、そのキーのためにスコープを scope/keyname 形式で必ず指定する必要があります。指定しない場合、API はエラーをスローします。たとえば、スコープが金色の gold/player_34545 は許可されますが、player_34545 はエラーを引き起こします。
| global/K1 | house/K1 |
| global/L2 | house/L2 |
| global/M3 | house/M3 |
キャッシュ
キャッシュを使用してデータストアからデータを一時的に保存し、パフォーマンスを向上させ、サーバーへのリクエスト数を減らします。たとえば、ゲームはデータのコピーをキャッシュして、データストアに別の呼び出しを行わずにそのデータにすばやくアクセスできます。
キャッシュは、次のようにデータストアキーに対する変更に適用されます:
- GetAsync() を使用してデータを読み取る。
- SetAsync() を使用してデータを作成する。
- UpdateAsync() を使用してデータを更新する。
- RemoveAsync() を使用してデータを削除する。
GetVersionAsync()、ListVersionsAsync()、ListKeysAsync()、および ListDataStoresAsync() はキャッシュを実装していませんので、常にサービスバックエンドから最新のデータを取得します。
デフォルトでは、エンジンは GetAsync() を使用して、バックエンドから取得した値をローカルキャッシュに4秒間保存します。またデフォルトでは、GetAsync() のキャッシュされたキーへのリクエストは、バックエンドに進むことなくキャッシュされた値を返します。キャッシュされた値を返す GetAsync() リクエストは、あなたのサーバーの制限 と スループットの制限 にはカウントされません。
バックエンドからキャッシュされていない値を取得するすべての GetAsync() 呼び出しは、キャッシュを即座に更新し、4秒のタイマーを再スタートします。
キャッシュの無効化
キャッシュを無効にして、最新の値をサーバーから取得するためにキャッシュの使用を選択解除するには、GetAsync() 呼び出しに DataStoreGetOptions パラメータを追加し、UseCache プロパティを false に設定してリクエストがキャッシュ内の任意のキーを無視するようにします。
キャッシュを無効にすることで、高頻度でキーに書き込んでいる複数のサーバーが最新の値を取得する必要がある場合に役立ちます。ただし、これによりデータストアの制限と割当をより消費する可能性があります。なぜなら、キャッシュをバイパスする GetAsync() リクエストは常にスループットとサーバーの制限にはカウントされるからです。
書き込み後の即時確認読み取りには、GetAsync() とともに DataStoreGetOptions.UseCache = false を使用します。デフォルトでは、GetAsync() はローカルの4秒キャッシュを使用するため、通常の確認読み取りでは古いデータが返されることがあります。
これは、UpdateAsync()、SetAsync()、IncrementAsync()、または RemoveAsync() 操作がエラーを返した後に特に重要です。この場合、コードはリトライするか、払い戻しするか、他の是正措置を取るべきかを判断する必要があります。
以下の例は、書き込みの結果を確認する際にキャッシュをバイパスする方法を示します:
local ok = pcall(function()
store:UpdateAsync(key, transform)
end)
if not ok then
local options = Instance.new("DataStoreGetOptions")
options.UseCache = false
local success, value = pcall(function()
return store:GetAsync(key, options)
end)
if success then
-- キャッシュされた状態ではなく、バックエンドの状態に基づいて決定する
end
end
シリアル化
DataStoreService はデータをJSON形式で保存します。スタジオでLuauデータを保存すると、RobloxはそのデータをJSONに変換するシリアル化というプロセスを使用します。次にRobloxは、そのデータをLuauに戻し、別のプロセスであるデシリアル化によって返します。
シリアル化とデシリアル化は次のLuauデータタイプをサポートしています:
- 数値
- 特別な数値 inf、-inf、および nan はJSON基準に準拠していないため、保存しないでください。Open Cloudでこれらの値を含むキーにはアクセスできません。
- テーブル
- テーブルは他のサポートされているデータタイプのみを含む必要があります
- 数値キーは、テーブルの長さが0である場合に文字列に変換されます
シリアル化がサポートされていないデータタイプを保存しようとすると、次のいずれかの結果になります:
- そのデータタイプの保存に失敗し、エラーメッセージが表示されます。
- nil としてそのデータタイプの保存に成功します。
データタイプが nil として保存される理由をデバッグするには、JSONEncode 関数を使用できます。この関数にLuauデータタイプを渡すと、データストアで保存されるときの形式で返され、返されるデータをプレビューおよび調査できます。