MemoryStore veri yapılarını tasarlarken en iyi uygulamalar

*Bu içerik, yapay zekâ (beta) kullanılarak çevrildi ve hatalar içerebilir. Sayfayı İngilizce görüntülemek için buraya tıkla.

Veri yapısı yazbağlı olarak, MemoryStoreService bir veri yapısındaki bellek ve öğe sayısı sınırlarını uygular.Tüm veri yapıları da küresel bir bölüm başına istek sınırıyla sınırlıdır.

Her Roblox deneyiminin Hafıza Deposu Gözlemlenebilirlik Panosu vardır, hafıza depolama kullanımını izlemek için kullanabileceğiniz bir dizi grafik içerir.

Sıralanmış haritalar ve sıralar

Sıralanmış haritalar ve sıraların her ikisi de maksimum sayıda öğe ve maksimum toplam hafıza sınırına sahiptir.Ayrıca, bu veri yapılarından birinin öğeleri daima tek bir bölümde bulunur.Bu veri yapılarından birine yapılan her istek aynı bölüme yapılan bir istektir.

Sıralanmış bir harita veya sıra, öğe veya hafıza sınırına ulaştığında, gereksiz öğeleri manuel olarak kaldırmak veya öğeler için bir son kullanma süresi politikası ekleyerek en iyi eylem seçeneğidir.Alternatif olarak, sadece bellek sınırı yavaşlatmaya neden oluyorsa, anahtarlarınızın ve değerlerinizin gereksiz bilgilerini çıkararak öğelerinizin boyutunu azaltmayı deneyebilirsiniz.

Tüm öğelerinize ihtiyacınız var veya istek trafiği nedeniyle sınırlama yaşıyorsanız, tek çözüm parçalanmadır.

Parçalanma

Parçalama, çeşitli veri yapıları arasında bir dizi ilişkili veri depolama sürecidir.Diğer bir deyişle, mevcut, yüksek kapasiteli bir veri yapısını alıp onu aynı set verileriyle birlikte daha küçük ve çok sayıda yerine koymak demektir.

Parçalanma için anahtar zorluk, verileri orijinal ile aynı işlevsellikte yaymak için çeşitli veri yapıları arasında bir yol bulmaktır.

Sıralanmış bir haritayı parçalama

Sıralanmış bir haritayı parçalamak için, verilerinizi karakter aralıklarıyla alfabetik alt bölümlere ayırmayı düşünün.Örneğin, sadece A-Z'den ilk harfli anahtarlara sahip olduğunuzu ve dört sıralı haritanın mevcut kullanım durumunuz ve gelecekteki büyüme için yeterli olduğuna inandığınızı varsayalım:

  • İlk harita A-G'yi, ikinci H-N'yi, üçüncü O-T'yi ve dördüncü U-Z'yi kapsayabilir.
  • Bir öğe eklemek veya geri almak için, öğenin başlangıç karakterine göre uygun haritayı kullanın.
Sıralanmış Bir Haritayı Parçalara Ayırma

-- Hafıza Dükkanı Hizmetini Başlatın
local MemoryStoreService = game:GetService("MemoryStoreService")
-- Sıralı Harita kümelerinizi oluşturun
local sm_AtoG = MemoryStoreService:GetSortedMap("AtoG")
local sm_HtoM = MemoryStoreService:GetSortedMap("HtoM")
local sm_NtoT = MemoryStoreService:GetSortedMap("NtoT")
local sm_UtoZ = MemoryStoreService:GetSortedMap("UtoZ")
-- Eşya Anahtarı'ndan doğru kovuyu almak için yardımcı işlev
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
-- Oyuncu isimlerini varsayılan değeri 0 ile başlatın
for _, player in game:GetService("Players"):GetPlayers() do
local bucket = getSortedMapBucket(player)
bucket:SetAsync(player, 0, 600)
end
-- Bir oyuncunun değerini al
local player = "myPlayer"
local bucket = getSortedMapBucket(player)
local playerScore = bucket:GetAsync(player)
print(playerScore)

Bir sırayı parçalama

Sırayı parçalamak, sıralanmış bir haritayı parçalamaktan daha karmaşıktır.Talep trafiğini çoklu sıraya yaymak istemenize rağmen, ekler, okumalar ve kaldırmalar sadece sıra önünde veya arkasında gerçekleşir.

Bir çözüm, dönen bir sıra kullanmak, yani birden fazla sıra oluşturmak ve bir öğeyi eklediğinizde veya okuduğunuzda aralarında dönmek demektir:

  1. Birkaç sıra oluşturun ve bir dizeye ekleyin.

  2. İki yerel işaret oluşturun. Birisi okumak ve öğeleri kaldırmak istediğiniz sırayı temsil eder. Diğeri, öğeleri eklemek istediğiniz sırayı temsil eder:

    • Okuma işlemleri için, her sızdan ihtiyacınız olan öğe sayısını ve okuma işaretini nereye taşımanız gerektiğini hesaplayın.
    • Operasyonları kaldırmak için, okumadan her sıraya ID'leri geçirin.
    • Ekleme işlemleri için, ekleyici işaretçiye ekleyin ve işaretçiyi artırın.
Sırayı parçalama

-- Hafıza Dükkanı Hizmetini Başlatın
local MemoryStoreService = game:GetService("MemoryStoreService")
-- Sıralarınızı oluşturun
local q1 = MemoryStoreService:GetQueue("q1")
local q2 = MemoryStoreService:GetQueue("q2")
local q3 = MemoryStoreService:GetQueue("q3")
local q4 = MemoryStoreService:GetQueue("q4")
-- Sıraları Bir Dizeye Yerleştir
local queueArr = { q1, q2, q3, q4 }
-- Okuma indekslerini temsil eden iki işaret oluştur ve sıraya ekleyin
local readIndex = 1
local addIndex = 1
-- Endeksleri uygun şekilde güncelleyen yerel bir işlev oluştur
local function rotateIndex(index, n)
return (index + n - 1) % 4 + 1
end
-- Sıradan n öğe okuyan yerel bir işlev oluştur
local function readFromQueue(count, allOrNothing, waitTimeout)
local endIndex = count % 4
local countPerQueue = count // 4
local items = {}
local ids = {}
-- her sıraya dönüş döngüsü
for i = 1, 4, 1 do
-- bu sıra ek bir öğe okuyup okumayacağını belirleyin
local diff = i - readIndex
if diff < 0 then
diff += 4
end
local queue = queueArr[i]
-- her sıradan öğeleri oku
-- fazladan okuma kriterlerine uyarsa +1 öğe çıkar
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
-- Sırada n öğeyi kaldıran yerel bir işlev oluştur
local function removeFromQueue(ids)
for i = 1, 4, 1 do
local queue = queueArr[readIndex]
queue:RemoveAsync(ids[i])
end
end
-- Sıraya bir öğe ekleyen yerel bir işlev oluştur
local function addToQueue(itemKey, expiration, priority)
local queue = queueArr[readIndex]
queue:AddAsync(itemKey, expiration, priority)
addIndex = rotateIndex(addIndex, 1)
end
-- Biraz kod yazın!
for _, player in game:GetService("Players"):GetPlayers() do
addToQueue(player, 600, 0)
end
local players, ids = readFromQueue(20, true, -1)
removeFromQueue(ids)

Hash haritaları

Hash haritalarının bireysel hafıza veya öğe sayısı sınırları yoktur ve otomatik olarak parçalanır, ancak kötü bir şekilde kullandığınızda yavaşlatma ile karşılaşabilirsiniz.

Örneğin, bir oyun veri tabanının bir hash haritası ile bir deneyim düşünün, metadata adlı tek bir anahtarın değeri olarak depolanmış.Bu meta veri, yer ID'si, oyuncu sayısı ve daha fazlası gibi bilgiler içeren bir iç içe geçmiş nesneyi içeriyorsa, meta verinin her seferinde çağrılması ve tüm nesneyi alması gereken tek seçeneğiniz var. GetAsync("metadata")Bu durumda, tüm istekler tek bir anahtara ve dolayısıyla tek bir bölüme gider.

Tüm metadatları tek bir, iç içe geçmiş nesne olarak depolamak yerine, daha iyi yaklaşım, her alanın kendi anahtarı olarak depolanmasıdır, böylece hash haritası otomatik parçalama avantajından yararlanabilir.Metadat ve hash haritasının geri kalanı arasında ayrılması gerekiyorsa, bir isim ön eklemek (örneğinmetadata_user_count yerine sadece user_count ).