MemoryStore 데이터 구조 설계 시 모범 사례

*이 콘텐츠는 AI(베타)를 사용해 번역되었으며, 오류가 있을 수 있습니다. 이 페이지를 영어로 보려면 여기를 클릭하세요.

데이터 구조 입력따라 MemoryStoreService는 메모리 및 데이터 구조의 항목 수에 제한을 적용합니다. 모든 데이터 구조는 또한 전역 분할 요청 제한을 통해 제한됩니다.

각 Roblox 경험에는 Memory Store Observability Dashboard 가 있으며, 이는 메모리 스토어 사용을 모니터링하는 데 사용할 수 있는 차트 집합을 포함합니다.

정렬된 맵과 대기열

정렬된 맵과 대기열은 모두 최대 항목 수 및 최대 메모리 크기에 제한이 있습니다. 또한 이 데이터 구조의 항목 중 하나에 대한 모든 요청은 항상 단일 파티션에 있습니다. 이 데이터 구조의 모든 요청에 대한 요청은 항상 동일한 파티션에 대한 요청입니다.

정렬된 맵이나 큐가 아이템 또는 메모리 한도에 도달하면 가장 좋은 조치는 필요 없는 항목을 수동으로 제거하거나 만료 정책을 추가하여 항목의 크기를 줄이는 것입니다. 또는 메모리 한도가 전부 차거나 속도가 느리면 키 및 값에서 불필요한 정보를 제거하여 항목의 크기를 줄일

모든 항목이 필요하거나 요청 처리량 때문에 속도가 느리다면 유일한 해결책은 분할입니다.

분할

분할은 다중 데이터 구조 간의 관련 데이터 집합을 저장하는 프로세스입니다. 즉, 원래 데이터 집합과 동일한 하이 트래픽 데이터 구조를 사용하여 여러 개의 작은 데이터 집합을 생성하는 것을 의미합니다.

분할의 열쇠 도전은 원본과 동일한 기능을 유지하면서 데이터를 여러 데이터 구조로 확장하는 방법을 찾는 것입니다.

정렬된 맵 분할

정렬된 맵을 분할하려면 캐릭터 범위가 있는 알파벳 하위 섹션으로 데이터를 분할하십시오. 예를 들어, A-Z의 첫 글자가 있는 키만 있으면 현재 사용 사례와 미래의 성장을 위해 4개의 정렬된 맵이 충분합니다.

  • 첫 번째 맵은 A-G, 두 번째 H-N, 세 번째 O-T, 그리고 네 번째 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. 여러 개의 큐를 만들고 배열에 추가합니다.

  2. 두 개의 로컬 포인터를 생성합니다. 하나는 읽고 제거할 항목을 나타내고, 다른 하나는 항목을 추가할 큐를 나타냅니다.

    • 읽기 작업에 대해 각 큐에서 필요한 항목 수와 읽기 포인터를 이동할 위치를 계산합니다.
    • 제거 작업의 경우, 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 }
-- 읽기 인덱스를 나타내는 포인터 두 개를 생성하고 큐를 추가합니다.Create two pointers representing the indexes of the read and add queues
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)

해시 맵

해시 맵에는 개별 메모리 또는 항목 수 제한이 없으며 자동으로 분할되지만, 잘못 사용하면 속도가 느려지는 경우가 있습니다.

예를 들어, 게임 데이터의 해시 맵이 포함된 경험을 고려하십시오. 이 메타데이터에는 장소 ID, 플레이어 수 등의 정보가 포함되어 있습니다. 메타데이터가 필요할 때마다 메타데이터에 액세스할 수 없으며 모든 요청이 단일

단일 중첩된 개체로 모든 메타데이터를 저장하는 대신, 더 나은 접근 방식은 각 필드를 자체 키로 저장하여 해시 맵이 자동 분할의 이점을 활용할 수 있도록 합니다. 메타데이터와 해시 맵 나머지 사이에 구분이 필요한 경우 이름 접두사(