排序地圖資料結構的記憶儲存允許您將經常使用的記憶體資料以鍵值對的形式存儲,並可選擇一個排序鍵,根據排序鍵和鍵保持特定的順序。與佇列不同,進入地圖的鍵的順序並不決定處理的順序,因此排序地圖對於基於排序的資料組織非常有用,用於實施遊戲內實體的參與,例如排行榜和跨伺服器拍賣。
限制
除了資料結構大小限制之外,排序地圖的鍵大小限制為128個字元,值大小限制為32 KB,排序鍵大小限制為128個字元。
如果您需要存儲超過此限制的資料,您可以採用分片技術通過鍵前綴將它們拆分並分佈到多個資料結構中。對記憶儲存進行分片還可以幫助提高系統的可擴展性。
獲取排序地圖
要獲取排序地圖,請使用您希望為地圖定義的名稱調用MemoryStoreService:GetSortedMap()。該名稱在遊戲中是全局的,因此您可以在使用該名稱的任何腳本中訪問相同的排序地圖。
local MemoryStoreService = game:GetService("MemoryStoreService")
local sortedMap = MemoryStoreService:GetSortedMap("SortedMap1")獲取排序地圖後,請調用以下任何函數:
| 功能 | 動作 |
|---|---|
| MemoryStoreSortedMap:SetAsync() | 新增一個新鍵,或如果鍵已存在則覆蓋其值和/或排序鍵。 |
| MemoryStoreSortedMap:GetAsync() | 讀取特定的鍵。 |
| MemoryStoreSortedMap:GetRangeAsync() | 讀取所有現有鍵或它們的特定範圍。 |
| MemoryStoreSortedMap:UpdateAsync() | 更新鍵的值和/或排序鍵,從排序地圖中檢索後。 |
| MemoryStoreSortedMap:RemoveAsync() | 移除排序地圖中的一個鍵。 |
| MemoryStoreSortedMap:GetSizeAsync() | 獲取排序地圖中的項目數。 |
新增或覆蓋資料
要新增一個新鍵或覆蓋排序地圖中鍵的值或排序鍵,請使用鍵名稱、其值、一個過期時間(以秒為單位)和一個可選的排序鍵調用MemoryStoreSortedMap:SetAsync()。一旦鍵過期,記憶體會自動清理。最大過期時間為3,888,000秒(45天)。如果提供,排序鍵必須是一個有效的數字(整數或浮點數)或字符串。
在鍵的排序順序中,排序鍵優先於鍵。例如,當以升序排序時,數字排序鍵首先排序,然後是字符串排序鍵,最後是沒有排序鍵的項目。所有具有數字排序鍵的項目按排序鍵進行排序,如果兩個項目的排序鍵相等,則按鍵進行排序。類似地,所有具有字符串排序鍵的項目按排序鍵進行排序,如果兩個項目的排序鍵相等,則按鍵進行排序。所有沒有排序鍵的項目僅按鍵排序。
升序排序的一些資料示例 -
{key: "player1", value: someValue1, sortKey: -1}
{key: "player2", value: someValue2, sortKey: 0}
{key: "player4", value: someValue3, sortKey: 1}
{key: "player5", value: someValue4, sortKey: 1}
{key: "player3", value: someValue5, sortKey: 3.14}
{key: "player6", value: someValue6, sortKey: "someString"}
{key: "player0", value: someValue7}
{key: "player7", value: someValue8}注意player0在所有具有排序鍵的鍵之後進行排序。player6在所有具有數字排序鍵的鍵之後進行排序。player4和player5具有相同的排序鍵,因此按鍵以升序排序。
local MemoryStoreService = game:GetService("MemoryStoreService")
local sortedMap = MemoryStoreService:GetSortedMap("SortedMap1")
local setSuccess, _ = pcall(function()
return sortedMap:SetAsync("User_1234", 1000, 30, 3.14152)
end)
if setSuccess then
print("設置成功。")
end獲取資料
您可以獲取與特定鍵相關聯的資料值和排序鍵,或者獲取範圍內鍵的多個值和排序鍵。
獲取一個鍵的資料
要獲取與排序地圖中特定鍵相關聯的值和排序鍵,請使用鍵名稱調用MemoryStoreSortedMap:GetAsync()。
local MemoryStoreService = game:GetService("MemoryStoreService")
local sortedMap = MemoryStoreService:GetSortedMap("SortedMap1")
local setSuccess, _ = pcall(function()
return sortedMap:SetAsync("User_1234", 1000, 30, 3.14152)
end)
if setSuccess then
print("設置成功。")
end
local item
local getSuccess, getError = pcall(function()
item = sortedMap:GetAsync("User_1234")
end)
if getSuccess then
print(item)
else
warn(getError)
end獲取多個鍵的資料
要作為單個操作從排序地圖獲取多個鍵的資料,請調用MemoryStoreSortedMap:GetRangeAsync()。此函數默認情況下列出所有現有鍵,但您可以設置鍵範圍的上限和下限。例如,以下代碼示例從排序地圖的開頭檢索最多20個項目,鍵大於或等於10,排序鍵大於或等於100,並且鍵小於或等於50,排序鍵小於或等於500。
local MemoryStoreService = game:GetService("MemoryStoreService")
local sortedMap = MemoryStoreService:GetSortedMap("SortedMap1")
local lowerBound = {}
lowerBound["key"] = "10"
lowerBound["sortKey"] = 100
local upperBound = {}
upperBound["key"] = "50"
upperBound["sortKey"] = 500
-- 獲取最多20個項目,自排序地圖開始
local getSuccess, items = pcall(function()
return sortedMap:GetRangeAsync(
Enum.SortDirection.Ascending, 20, lowerBound, upperBound)
end)
if getSuccess then
for _, item in items do
print(item.key)
print(item.sortKey)
end
end更新資料
要從排序地圖中檢索鍵的值和排序鍵並更新它,請使用鍵名稱、一個用於更新該鍵的值和排序鍵的回調函數以及一個過期時間(以秒為單位)調用MemoryStoreSortedMap:UpdateAsync()。最大過期時間為3,888,000秒(45天)。
對於大多數遊戲,多個伺服器可以同時更新相同的鍵並更改值。由於UpdateAsync()在更新之前始終修改最新的值,因此您應該使用它來讀取最新值作為回調函數的輸入。
例如,以下代碼示例更新排行榜中玩家的分數。分數的計算方法為擊殺數/死亡數。UpdateAsync()確保即使多個遊戲伺服器同時更新相同項目,擊殺數和死亡數也會更新為最新值。玩家的擊殺數和死亡數是單調遞增的值,因此在會話中只能增加其值。
local MemoryStoreService = game:GetService("MemoryStoreService")
local sortedMap = MemoryStoreService:GetSortedMap("Leaderboard")
local function updateLeaderboard(itemKey, killsToAdd, deathsToAdd)
local success, newStats, newScore = pcall(function()
return sortedMap:UpdateAsync(itemKey, function(playerStats, playerScore)
playerStats = playerStats or { kills = 0, deaths = 0 }
playerStats.kills += killsToAdd
playerStats.deaths += deathsToAdd
if playerStats then
-- `playerScore` 是用於排序地圖中項目的排序鍵
playerScore = playerStats.kills / math.max(playerStats.deaths, 1)
return playerStats, playerScore
end
return nil
end, 30)
end)
if success then
print(newStats)
print(newScore)
end
endUpdateAsync()的延遲類似於GetAsync()和SetAsync(),除非發生爭用。
當發生爭用時,系統會自動重試操作,直到以下三種情況之一發生:操作成功,回調函數返回nil,或者達到最大重試次數。如果系統達到最大重試次數,則會返回衝突。
移除資料
您可以使用MemoryStoreSortedMap:RemoveAsync()來移除排序地圖中的一個鍵,也可以刪除記憶儲存排序地圖中的所有資料。
移除鍵
要從排序地圖中移除鍵,請使用鍵名稱調用MemoryStoreSortedMap:RemoveAsync()。
local MemoryStoreService = game:GetService("MemoryStoreService")
local sortedMap = MemoryStoreService:GetSortedMap("SortedMap1")
local setSuccess, _ = pcall(function()
return sortedMap:SetAsync("User_1234", 1000, 30, "someStringSortKey")
end)
if setSuccess then
print("設置成功。")
end
local removeSuccess, removeError = pcall(function()
sortedMap:RemoveAsync("User_1234")
end)
if not removeSuccess then
warn(removeError)
end刪除所有資料
要刪除排序地圖中的記憶體,請使用MemoryStoreSortedMap:GetRangeAsync()列出所有鍵,然後使用MemoryStoreSortedMap:RemoveAsync()將它們移除。
local MemoryStoreService = game:GetService("MemoryStoreService")
local sortedMap = MemoryStoreService:GetSortedMap("SortedMap1")
-- 初始下限為nil,從第一個項目開始清空
local exclusiveLowerBound = nil
while true do
-- 從當前下限開始獲取最多一百個項目
local getRangeSuccess, items = pcall(function()
return sortedMap:GetRangeAsync(Enum.SortDirection.Ascending, 100, exclusiveLowerBound)
end)
if getRangeSuccess then
local removeSuccess = true
local removeError = nil
for _, item in items do
removeSuccess, removeError = pcall(function()
sortedMap:RemoveAsync(item.key)
end)
end
-- 如果移除項目時出現錯誤,請嘗試使用相同的排他性下限重新執行
if not removeSuccess then
warn(removeError)
-- 如果範圍不足一百個項目,則達到地圖末尾
elseif #items < 100 then
break
else
-- 最後檢索到的鍵為下一次迭代的排他性下限
exclusiveLowerBound = {}
exclusiveLowerBound["key"] = items[#items].key
exclusiveLowerBound["sortKey"] = items[#items].sortKey
end
end
end獲取大小
要獲取排序地圖中的項目數,請調用 MemoryStoreSortedMap:GetSizeAsync()。
local MemoryStoreService = game:GetService("MemoryStoreService")
local sortedMap = MemoryStoreService:GetSortedMap("SortedMap1")
local setSuccess, _ = pcall(function()
return sortedMap:SetAsync("User_1234", 1000, 30, 3.14152)
end)
if setSuccess then
print("設置成功。")
end
local size
local success, sizError = pcall(function()
size = sortedMap:GetSizeAsync()
end)
if success then
print(size)
else
warn(sizeError)
end