ขึ้นอยู่กับประเภทของโครงสร้างข้อมูล MemoryStoreService จะบังคับใช้ ขีดจำกัด เกี่ยวกับหน่วยความจำและจำนวนรายการในโครงสร้างข้อมูล โครงสร้างข้อมูลทั้งหมดยังถูกจำกัดโดยขีดจำกัดคำขอทั่วไประดับพาร์ติชัน
แต่ละเกมใน Roblox จะมี แดชบอร์ดการสังเกตหน่วยความจำ ซึ่งรวมชุดกราฟที่คุณสามารถใช้เพื่อติดตามการใช้งาน Memory Store
แผนที่จัดเรียงและคิว
แผนที่จัดเรียงและคิวมีขีดจำกัดเกี่ยวกับจำนวนรายการสูงสุดและหน่วยความจำทั้งหมดที่สูงสุด นอกจากนี้ รายการในโครงสร้างข้อมูลเหล่านี้จะอยู่ในพาร์ติชันเดียวดังนั้นทุกคำขอไปยังโครงสร้างข้อมูลเหล่านี้จะเป็นคำขอไปยังพาร์ติชันเดียวกัน
เมื่อแผนที่จัดเรียงหรือคิวถึงขีดจำกัดของจำนวนรายการหรือหน่วยความจำ วิธีการที่ดีที่สุดคือการลบรายการที่ไม่จำเป็นออกด้วยตนเองหรือโดยการเพิ่มนโยบายการหมดอายุสำหรับรายการ หรือหากขีดจำกัดหน่วยความจำเป็นสาเหตุที่ทำให้เกิดการจำกัด คุณสามารถลองลดขนาดของรายการของคุณโดยการลบข้อมูลที่ไม่จำเป็นออกจากกุญแจและค่าของคุณ
หากคุณต้องการรายการทั้งหมดของคุณหรือต้องเผชิญกับการจำกัดเนื่องจากการไหลของคำขอ วิธีเดียวที่เป็นไปได้คือการแบ่งพาร์ติชัน
การแบ่งพาร์ติชัน
การแบ่งพาร์ติชันคือกระบวนการในการจัดเก็บชุดข้อมูลที่เกี่ยวข้องทั่วโครงสร้างข้อมูลหลายตัว กล่าวอีกนัยหนึ่งคือการนำโครงสร้างข้อมูลความถี่สูงที่มีอยู่มาแทนที่ด้วยโครงสร้างข้อมูลที่เล็กกว่าหลายตัวที่รวมกันมีชุดข้อมูลเดียวกันกับข้อมูลต้นฉบับ
ความท้าทายหลักในการแบ่งพาร์ติชันคือวิธีการกระจายข้อมูลทั่วโครงสร้างข้อมูลหลายตัวในลักษณะที่รักษาฟังก์ชันการทำงานเดียวกันกับข้อมูลดั้งเดิม
สำหรับแผนที่แฮช แม้ว่าโครงสร้างข้อมูลจะถูกแบ่งอยู่แล้ว แต่การแบ่งพาร์ติชันจะทำโดยการกระจายคำขอระหว่างกุญแจหลายตัว
การแบ่งพาร์ติชันแผนที่จัดเรียง
ในการแบ่งพาร์ติชันแผนที่จัดเรียง ให้พิจารณาการแยกข้อมูลของคุณออกเป็นส่วนย่อยตามตัวอักษรที่มีช่วงตัวอักษร สำหรับตัวอย่าง สมมติว่าคุณมีแต่กุญแจที่มีตัวอักษรแรกจาก A-Z และคุณเชื่อว่าแผนที่จัดเรียงสี่ตัวเพียงพอสำหรับการใช้งานที่ปัจจุบันและการเติบโตในอนาคต:
- แผนที่แรกสามารถครอบคลุม A-G, แผนที่ที่สอง H-N, แผนที่ที่สาม O-T, และแผนที่ที่สี่ U-Z
- ในการแทรกหรือดึงข้อมูลรายการ ให้ใช้แผนที่ที่เหมาะสมตามอักขระเริ่มต้นของรายการ
การแบ่งพาร์ติชันแผนที่จัดเรียง
-- เริ่มต้นบริการ MemoryStore
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)
การแบ่งพาร์ติชันคิว
การแบ่งพาร์ติชันคิวทำได้ยากกว่าการแบ่งพาร์ติชันแผนที่จัดเรียง แม้ว่าคุณจะต้องกระจายการไหลของคำขอไปยังคิวหลายตัว แต่การเพิ่ม ป้อนข้อมูล และลบจะเกิดขึ้นที่ด้านหน้า或หลังของคิวเท่านั้น
หนึ่งในวิธีแก้ไขคือการใช้คิวหมุนเวียน ซึ่งหมายถึงการสร้างคิวหลายตัวและหมุนระหว่างคิวเหล่านั้นเมื่อคุณเพิ่มหรือลูกค้าไอเท็ม:
สร้างคิวหลายตัวและเพิ่มพวกมันลงในอาร์เรย์
สร้างตัวชี้ท้องถิ่นสองตัว ตัวหนึ่งแทนคิวที่ต้องการอ่านและลบรายการออก อีกตัวหนึ่งแทนคิวที่ต้องการเพิ่มรายการเข้าไป:
- สำหรับการดำเนินการอ่านให้คำนวณจำนวนรายการที่คุณต้องการจากแต่ละคิวรวมถึงตำแหน่งที่จะย้ายตัวชี้การอ่านไป
- สำหรับการดำเนินการลบ ให้ส่ง ID จากการอ่านไปยังแต่ละคิว
- สำหรับการดำเนินการเพิ่ม ให้เพิ่มในคิวที่ตำแหน่งการเพิ่มและเพิ่มจำนวนตัวชี้
การแบ่งพาร์ติชันคิว
-- เริ่มต้นบริการ MemoryStore
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 }
-- สร้างตัวชี้ท้องถิ่นสองตัวแทนที่ดัชนีของคิวที่อ่านและเพิ่ม
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 หากข้อมูลเมตาดาต้าดังกล่าวมีวัตถุที่ซ้อนกันพร้อมข้อมูลเช่น รหัสสถานที่ จำนวนผู้เล่น และข้อมูลอื่นๆ ทุกครั้งที่ต้องการข้อมูลเมตาดาต้า คุณไม่มีทางเลือกอื่นนอกจากการเรียก GetAsync("metadata") และดึงวัตถุทั้งหมด ในกรณีนี้ คำขอทั้งหมดจะไปที่กุญแจเดียวและดังนั้นจึงเป็นพาร์ติชันเดียว
แทนที่จะเก็บข้อมูลเมตาดาต้าทั้งหมดเป็นวัตถุซ้อนกันเดียว วิธีที่ดีกว่าคือการเก็บแต่ละฟิลด์เป็นกุญแจของตัวเองเพื่อให้แผนที่แฮชสามารถใช้ประโยชน์จากการแบ่งพาร์ติชันอัตโนมัติ หากคุณต้องการการแยกระหว่างข้อมูลเมตาดาต้ากับแผนที่แฮชที่เหลือ ให้เพิ่มคำนำหน้าชื่อ (เช่น metadata_user_count แทนที่จะเป็นแค่ user_count)
นอกจากนี้ หากกุญแจเดียวหรือไม่กี่ตัวถูกเข้าถึงบ่อย ๆ จะเป็นเรื่องสำคัญในการแบ่งพาร์ติชันการเรียกสิ่งเหล่านี้ไปยังกุญแจจำนวนมาก ตัวอย่างเช่น หากเซิร์ฟเวอร์เกมทั้งหมดต้องดึงค่าจากกุญแจแผนที่แฮชเดียว คุณอาจประสบกับการจำกัดพาร์ติชัน เพื่อป้องกันสิ่งนี้คุณสามารถกระจายคำเรียกเหล่านั้นไปยังหลายกุญแจที่มีค่าตรงกันจนกว่าการจำกัดพาร์ติชันจะไม่เกิดขึ้นอีกต่อไป