데이터를 버전 관리, 목록화 및 캐싱을 통해 관리하세요.
버전 관리
버전 관리는 설정할, 업데이트할 및 증가시킬 때 발생합니다. 함수 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는 하루에 한 번 게임의 모든 데이터 저장소를 스냅샷으로 찍을 수 있게 해줍니다. 데이터 저장 논리를 변경하는 게임 업데이트를 배포하기 전에 반드시 스냅샷을 찍어 두세요. 스냅샷을 찍는 것은 이전 게임 버전의 최신 데이터를 확보할 수 있도록 보장합니다.
예를 들어, 스냅샷 없이 데이터 손상이 발생하는 업데이트를 UTC 3:30에 게시하면 손상된 데이터가 3:00-3:30 UTC 사이에 작성된 모든 데이터를 덮어씌웁니다. 그러나 3:29 UTC에 스냅샷을 찍으면 손상된 데이터가 3:29 UTC 이전에 작성된 모든 데이터를 덮어씌우지 않으며, 3:00-3:29 UTC 사이에 작성된 모든 키의 최신 데이터가 보존됩니다.
목록화 및 접두사
데이터 저장소는 접두사로 목록화할 수 있습니다. 예를 들어, 접두사가 "dog"인 모든 키 또는 데이터 저장소에 대해 이름의 첫 n 글자, 즉 "d", "do" 또는 "dog"로 목록화할 수 있습니다.
모든 데이터 저장소 또는 키를 목록화할 때 접두사를 지정할 수 있으며, 해당 접두사와 일치하는 객체만 반환받을 수 있습니다. ListDataStoresAsync() 및 ListKeysAsync() 함수 모두 사용하여 목록을 열거할 수 있는 DataStoreListingPages 객체를 반환합니다.
| 함수 | 설명 |
|---|---|
| ListDataStoresAsync() | 모든 데이터 저장소를 나열합니다. |
| ListKeysAsync() | 데이터 저장소의 모든 키를 나열합니다. |
범위
GetDataStore()의 두 번째 매개변수로 고유한 문자열을 범위로 설정하여 데이터 저장소의 키를 추가로 구성할 수 있습니다. 범위를 지정하지 않으면 기본 범위는 global입니다. 범위는 데이터 저장소에서 수행하는 모든 작업의 모든 키 앞에 자동으로 추가됩니다.
| 키 | 범위 |
|---|---|
| houses/User_1234 | houses |
| pets/User_1234 | pets |
| inventory/User_1234 | inventory |
데이터 저장소 이름, 범위 및 키의 조합은 키를 고유하게 식별합니다. 범위를 지정하여 키를 식별하기 위해서는 이 세 가지 값이 모두 필요합니다. 예를 들어, User_1234라는 global-스코프 키를 읽을 수 있습니다:
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()의 두 번째 매개변수는 빈 문자열("")이어야 합니다.
local DataStoreService = game:GetService("DataStoreService")local options = Instance.new("DataStoreOptions")options.AllScopes = truelocal ds = DataStoreService:GetDataStore("DS1", "", options)
AllScopes 속성을 활성화하고 데이터 저장소에 새 키를 생성하면 반드시 범위를 키 형식으로 지정해야 합니다: 범위/키 이름 형식으로. 그렇지 않으면 API는 오류를 발생시킵니다. 예를 들어, gold/player_34545는 범위를 gold로 설정하여 사용할 수 있지만, player_34545는 오류를 발생시킵니다.
| global/K1 | house/K1 |
| global/L2 | house/L2 |
| global/M3 | house/M3 |
캐싱
성능을 개선하고 서버에 대한 요청 수를 줄이기 위해 데이터 저장소의 데이터를 임시로 저장하는 데 캐싱을 사용하세요. 예를 들어, 게임은 데이터의 복사본을 캐시하여 데이터 저장소에 다른 호출을 할 필요 없이 빠르게 접근할 수 있습니다.
캐싱은 다음을 사용하여 데이터 저장소 키를 수정할 때 적용됩니다:
- GetAsync()를 사용하여 데이터 읽기.
- SetAsync()를 사용하여 데이터 생성.
- UpdateAsync()를 사용하여 데이터 업데이트.
- IncrementAsync()를 사용하여 데이터 증가.
- RemoveAsync()를 사용하여 데이터 제거.
GetVersionAsync(), ListVersionsAsync(), ListKeysAsync(), 및 ListDataStoresAsync()는 캐싱을 구현하지 않으며 항상 서비스 백엔드에서 최신 데이터를 가져옵니다.
기본적으로 엔진은 백엔드에서 검색한 값을 로컬 캐시에 네 초 동안 저장하기 위해 GetAsync()를 사용합니다. 기본적으로, GetAsync()에 대한 캐시된 키의 요청은 캐시된 값을 반환하며 백엔드로 계속 진행하지 않습니다. 캐시된 값을 반환하는 GetAsync() 요청은 귀하의 서버 한계와 처리량 한계에는 포함되지 않습니다.
백엔드에서 캐시되지 않은 값을 검색하는 모든 GetAsync() 호출은 즉시 캐시를 업데이트하고 4초 타이머를 재시작합니다.
캐싱 비활성화
캐싱을 비활성화하고 서버에서 최신 값을 검색하기 위해 캐시를 사용하지 않으려면 DataStoreGetOptions 매개변수를 GetAsync() 호출에 추가하고 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 데이터 유형을 이 함수에 전달하면, Roblox가 데이터 저장소에 저장했을 형식으로 반환받을 수 있으며, 이를 통해 반환된 데이터를 미리 보기하고 조사할 수 있습니다.