メモリストアデータ構造を設計するベストプラクティス

*このコンテンツは、ベータ版のAI(人工知能)を使用して翻訳されており、エラーが含まれている可能性があります。このページを英語で表示するには、 こちら をクリックしてください。

データ構造の入力に応じて、MemoryStoreService はメモリとデータ構造のアイテムの数に制限を設定します。すべてのデータ構造は、グローバルな per- partition リクエスト制限によって制限されます。

各 Roblox エクスペリエンスには、メモリストア監視ダッシュボード が含まれており、メモリストア使用をモニタリングするためのチャートのセットが含まれています。

マップとキューをソート

ソートされたマップとキューは、それぞれ最大アイテム数と最大メモリの上限があります。さらに、これらのデータ構造の 1 つのアイテムは常に単一のパーティションにあります。これらのデータ構造の 1 つのリクエストは、常に同じパーティションにリクエストされます。

ソートされたマップまたはキューがアイテムまたはメモリの上限に到達すると、最善のコースアクションは、必要ないアイテムを手動または有効期限のポリシーを追加して、削除することです。また、メモリの上限がスロートしている場合は、キーと値から不要な情報を削除することもできます。

アイテムをすべて必要にするか、リクエスト処理量によりスロットが減少する場合、唯一の解決策はシャードです。

シャーディング

分割は、複数のデータ構造間で関連するデータをセットして保存するプロセスです。つまり、既存のハイスループットデータ構造を取り、複数の小さいデータ構造を交換して、元のデータセットと同じセットを含むようにします。

シャードするキーチャレンジは、オリジナルと同じ機能を維持する方法でデータを複数のデータ構造に拡散することです。

ソートされたマップをシャードする

ソートされたマップをかけるには、データをキャラクター範囲でアルファベット順に分割することを考慮してください。たとえば、A-Z の最初の文字を持つキーがある場合、または 4つのソートされたマップがあると思われる場合、現在の使用ケースと将来の成長には、4つのソートされたマップが十分であることを示すために、次のように仮定してください:

  • 最初のマップは A-G、第2の H-N、第3の O-T、そして第4の U-Z を覆うことができます。
  • アイテムを挿入または取り出すには、アイテムの開始キャラクターに基づく適切なマップを使用します。
ソートされたマップをシャードする

-- メモリーストアサービスを初期化する
local MemoryStoreService = game:GetService("MemoryStoreService")
-- ソートされたマップバケツを作成
local sm_AtoG = MemoryStoreService:GetSortedMap("AtoG")
local sm_HtoM = MemoryStoreService:GetSortedMap("HtoM")
local sm_NtoT = MemoryStoreService:GetSortedMap("NtoT")
local sm_UtoZ = MemoryStoreService:GetSortedMap("UtoZ")
-- アイテムキーから正しいバケツを取り戻すヘルパー機能
local function getSortedMapBucket(itemKey)
if (itemKey >= "a" and itemKey < "h") then
return sm_AtoG
elseif (itemKey < "n") then
return sm_HtoM
elseif (itemKey < "u") then
return sm_NtoT
else
return sm_UtoZ
end
end
-- プレイヤー名をデフォルトの 0 で初期化します
for _, player in game:GetService("Players"):GetPlayers() do
local bucket = getSortedMapBucket(player)
bucket:SetAsync(player, 0, 600)
end
-- プレイヤーの値を取り戻す
local player = "myPlayer"
local bucket = getSortedMapBucket(player)
local playerScore = bucket:GetAsync(player)
print(playerScore)

キューを分割する

キューを分割するのは、ソートされたマップを分割するのと比べてトリックです。ただし、リクエストの通信量を複数のキューに分散するために、追加、読み取り、削除は、キューの前または後にのみ発生します。

1つのソリューションは、回転キューを使用することで、アイテムを追加または読み込むときに、複数のキューを作成し、回転することです:

  1. 複数のキューを作成し、アレイに追加します。

  2. ローカルポインターを 2つ作成します。1つは、読み込みたいアイテムを表示し、他の 1つは、追加したいアイテムを表示します。

    • 読み取りオペレーションの場合、各キューから必要なアイテムの数と、読み取りポインターを移動する場所を計算します。
    • オペレーションを削除する場合、ID を読み取りの各キューに渡します。
    • 追加オペレーションの場合、追加ポインターでキューに追加し、ポインターをインクリメントします。
キューを分割する

-- メモリーストアサービスを初期化する
local MemoryStoreService = game:GetService("MemoryStoreService")
-- キューを作成
local q1 = MemoryStoreService:GetQueue("q1")
local q2 = MemoryStoreService:GetQueue("q2")
local q3 = MemoryStoreService:GetQueue("q3")
local q4 = MemoryStoreService:GetQueue("q4")
-- 配列にキューを入れる
local queueArr = { q1, q2, q3, q4 }
-- インデックスを表す 2つのポインタを作成し、キューを追加する
local readIndex = 1
local addIndex = 1
-- インデックスを適切に更新するローカル関数を作成します
local function rotateIndex(index, n)
return (index + n - 1) % 4 + 1
end
-- クエー列から n 個のアイテムを読み込むローカル関数を作成します
local function readFromQueue(count, allOrNothing, waitTimeout)
local endIndex = count % 4
local countPerQueue = count // 4
local items = {}
local ids = {}
-- 各キューをループする
for i = 1, 4, 1 do
-- このキューが追加のアイテムを読み取るかどうかを決定します
local diff = i - readIndex
if diff < 0 then
diff += 4
end
local queue = queueArr[i]
-- 各キューからアイテムを読み取る
-- 追加の読み取り条件に一致する場合 +1 アイテム
if diff < endIndex then
items[i], ids[i] = queue:ReadAsync(countPerQueue + 1, allOrNothing,waitTimeout)
else
items[i], ids[i] = queue:ReadAsync(countPerQueue, allOrNothing,waitTimeout)
end
end
readIndex = rotateIndex(readIndex, count)
return items, ids
end
-- クエールから n 個のアイテムを削除するローカル関数を作成します
local function removeFromQueue(ids)
for i = 1, 4, 1 do
local queue = queueArr[readIndex]
queue:RemoveAsync(ids[i])
end
end
-- アイテムをキューに追加するローカル関数を作成します
local function addToQueue(itemKey, expiration, priority)
local queue = queueArr[readIndex]
queue:AddAsync(itemKey, expiration, priority)
addIndex = rotateIndex(addIndex, 1)
end
-- コードを書いて!
for _, player in game:GetService("Players"):GetPlayers() do
addToQueue(player, 600, 0)
end
local players, ids = readFromQueue(20, true, -1)
removeFromQueue(ids)

ハッシュマップ

ハッシュマップには個々のメモリまたはアイテムのカウント限度がありませんので、正しく使用すると自動的にシャードされますが、不正に使用すると、制限を超えてしまう可能性があります。

たとえば、ゲームデータのハッシュマップを持つエクスペリエンス、存在する値の単一のキー名が metadata で表示されている場合を考えてください。このメタデータには、場所 ID、プレイヤー数などの情報が含まれており、メタデータが必要になるたびに、<

メタデータを単一の、ネストされたオブジェクトとして保存する代わりに、より良いアプローチは、各フィールドをそれぞれのキーとして保存することです。これにより、ハッシュマップの自動シャードに利益を得ることができます。メタデータとレストの間のセパレーションが必要な場合は、名