MemoryStoreService 是一個高吞吐量和低延遲數據服務,可從活動會作業中的所有服務器快速存取內存數據。 記憶體儲存 適合快速變更且不需要持久的頻繁和短暫數據,因為它們的存取速度更快,且到達最長壽命時會消失。對於需要在會話之間持續的資料,請使用 資料儲存。
數據結構
而不是直接存取原始資料,記憶體儲存有三種原始資料結構在服務器間共享快速處理:排序地圖、隊列和哈希地圖。每個數據結構都適合某些使用案例:
- 技能基礎匹配 - 將用戶信息,例如技能等級,保存在服務器間的共用 隊列 中,並使用大廳服務器定期運行匹配。
- 跨服務器交易和拍賣 - 啟用用戶可以在實時變更價格的物品進行投標的通用交易,並使用排序的鑰匙值對組合的地圖進行拍賣。
- 全球排行榜 - 在排序地圖內的共用排行榜中儲存和更新用戶排名。
- 共享庫存 - 將庫存項目和統計資料儲存在共用的 哈希地圖 中,用戶可以並行使用庫存項目。
- 對永久數據進行緩存 - 將永久數據同步到資料儲存庫中的記憶儲存庫進行緩存 哈希地圖 ,以便提高體驗的履約。
一般來說,如果您需要根據特定鍵存取資料,請使用哈希地圖。如果需要將這些數據訂購,請使用排序的地圖。如果您需要按特定順序處理數據,請使用隊列。
限制和配額
為了維持可擴展性和系統性履約,記憶儲存有記憶大小、API 請求和資料結構尺寸的數據使用額度。
記憶體儲存有基於過期時間的驅逐政策,也稱為生存時間(TTL)。項目在過期後被驅逐,記憶配額將被釋放以用於新入口。當您達到記憶限制時,所有後續的寫入請求都會失敗,直到項目過期或您手動刪除它們。
記憶體大小限制
記憶配額限制體驗可以使用的記憶總量。它不是固定值。相反,它會隨著時間變化,取決於體驗中的使用者數量,以下列方式計算: 64KB + 1KB * [使用者數量] 。額度適用於體驗等級,而不是服務器等級。
當使用者加入體驗時,額外的記憶容量即時可用。當使用者離開體驗時,額度不會立即減少。在額度重新評估為更低值之前,有一個追溯期為八天。
體驗使用記憶體大小上限後,任何增加記憶體大小的 API 請求都會失敗。要求減少或不更改記憶體大小仍然成功。
使用 可觀察 面板,您可以使用 記憶使用 圖表在實時查看體驗的記憶大小配額。
API 請求限制
對於 API 請求限制,有一個 請求單位 額度適用於所有 MemoryStoreService。配額是 1000 + 100 * [並行使用者數量] 每分鐘的請求單位。
大多數 API 呼叫只消耗一個請求單位,但有一些例外:
MemoryStoreSortedMap:GetRangeAsync()
根據返回的項目數量消耗單位。例如,如果此方法返回 10 個項目,則呼叫計為 10 個請求單位。如果返回空回應,則計為一個請求單位。
根據返回的項目數量消耗單位,與 MemoryStoreSortedMap:GetRangeAsync() 一樣,但在閱讀時每兩秒消耗額外的單位。使用 waitTimeout 參數指定最大閱讀時間。
MemoryStoreHashMap:UpdateAsync()
最少消耗兩個單位。
MemoryStoreHashMap:ListItemsAsync()
使用 [掃描的分區數量] + [已返回的項目] 單位。
要求限額也會應用於體驗層而不是伺服器等級。這樣可以為服務器之間分配請求,只要總體請求率不超過額度就行。如果您超過配額,當服務限制您的請求時,您將收到錯誤回應。
當可用的 可觀察性 功能時,您可以在實時查看體驗的請求單位額度。
數據結構尺寸限制
對於單一排序的地圖或隊列,以下尺寸和項目數限制適用:
- 最大項目數量:1,000,000
- 最大總尺寸(包括排序地圖的鑰匙):100 MB
每個分區限制
請參閱每個分區限制。
最佳實踐
為了保持記憶使用模式最佳化且避免達到 限制 ,請遵循以下最佳做法:
移除處理過的項目。: 使用 MemoryStoreQueue:RemoveAsync() 方法清理隊列中的閱讀項目和使用 MemoryStoreSortedMap:RemoveAsync() 方法清理排序的地圖可以釋放記憶並保持數據結構更新。
將過期時間設為在添加資料時可能的最小時間框架。: 雖然預設有效期時間為 MemoryStoreQueue:AddAsync() 和 MemoryStoreSortedMap:SetAsync() 的兩者都是 45 天,但設置最短可能時間可自動清理舊數據,以防止它們填滿您的記憶使用額度。
- 不要儲存大量資料以長期過期,因為它可能會超過您的記憶限額,導致可能導致整個體驗中斷的問題。
- 始終明確刪除不需要的項目或設置短期項目過期。
- 一般來說,您應該使用明確的刪除來釋放記憶和項目過期作為安全機制,防止未使用的項目長時間佔用記憶。
只在記憶中保留必要的值。
例如,對於拍賣屋體驗,您只需要維持最高標價。您可以在一個鑰匙上使用 MemoryStoreSortedMap:UpdateAsync() 來保留最高標價,而不是保留您數據結構中的所有標價。
使用 指數退避 來幫助保持在 API 請求限制之下。
例如,如果您收到 DataUpdateConflict,您可能會在兩秒後重試,然後四、八、等等。而不是一直向 MemoryStoreService 發送請求,以獲得正確的回應。
使用 碎片化 將巨型數據結構分解為多個較小的結構。
往往更容易在較小的結構中管理數據,而不是將所有數據存儲在一個大型結構中。這種方法也可以幫助避免使用和速率限制。例如,如果你有一個排序的地圖使用前缀來區分其鑰匙,考慮將每個前缀分開到自己的排序地圖。對於特別受歡迎的體驗,你甚至可以根據使用者ID的最後數字將使用者分開到多個地圖。
壓縮存儲值。
例如,考慮使用 LZW 算法來減少儲存的值大小。
可觀察性
觀察性面板提供監控和解決您記憶存儲使用的見解和分析。在您的記憶使用和 API 請求的不同方面上實時更新圖表,您可以跟蹤您體驗的記憶使用模式、查看目前分配的額度、監視 API 狀態並識別性能優化的潛在問題。
下表列出並說明所有監測儀面板上可用的 API 回應狀態代碼的 狀態請求數量 和 API x 狀態請求 圖表。要了解有關如何解決這些錯誤的更多信息,請參閱排除故障。對於錯誤相關的特定配額或限制,請參閱 限制和配額。
狀態碼 | 說明 |
---|---|
成功 | 成功。 |
數據結構記憶超出限制 | 超出數據結構等級記憶體限制(100MB)。 |
資料更新衝突 | 由於並行更新造成衝突。 |
存取遭拒 | 未獲得存取經驗數據的權限。此請求不會消耗請求單位或使用額度。 |
內部錯誤 | 內部錯誤。 |
無效請求 | 請求沒有所需資訊或具有不正確的資訊。 |
數據結構項目超出限制 | 超出數據結構等級項目數限制(1M)。 |
找不到物品 | 在 或 中找不到項目。每 2 秒進行投票,直到找到隊列中的項目為止,返回此狀態代碼。 |
數據結構請求超出限制 | 超出數據結構等級請求單限(每分鐘 100,000 請求單位)。 |
分割請求超出限制 | 超出分割請求單位限制。 |
總請求超出限制 | 超出宇宙級請求單位限制。 |
總記憶超出限制 | 超出宇宙級記憶容量。 |
項目價值尺寸過大 | 價值大小超出限制(32KB)。 |
下表列出從客戶端的狀態代碼,目前在可觀察性面板上無法使用。
狀態碼 | 說明 |
---|---|
內部錯誤 | 內部錯誤。 |
未發布的地點 | 您必須發布此位置才能使用 MemoryStoreService。 |
無效客戶端存取 | MemoryStoreService必須從伺服器呼叫。 |
無效的過期時間 | 「過期」欄位的時間必須介於 0 和 3,888,000 之間。 |
無效請求 | 無法將值轉換為 json。 |
無效請求 | 無法將 sortKey 轉換為有效的數字或字串。 |
轉換呼叫失敗 | 無法呼叫變換回呼函數。 |
請求限制 | 最近的記憶儲存請求超過了一個或多個限制。 |
更新衝突 | 超出最大重試次數。 |
排除問題
下表列出並說明每個回應狀態代碼的建議解決方案:
錯誤 | 故障排除選項 |
---|---|
數據結構請求超出限制/分區請求超出限制 |
|
總請求超出限制 | |
數據結構項目超出限制 |
|
數據結構記憶超出限制 | |
總記憶超出限制 | |
資料更新衝突 |
調查以確認你是否有效地呼叫 MemoryStoreService 以避免衝突。理想情況下,你不應該過度傳送請求。: 一次使用 方法為隊列和 方法為排序的地圖刪除項目。 |
內部錯誤 |
|
無效請求 |
|
項目價值尺寸過大 |
|
在工作室測試和調試
在 MemoryStoreService 中的數據被隔離在 Studio 和生產之間,因此在 Studio 中變更數據不會影響生產行為。這意味著來自 Studio 的 API 呼叫無法存取生產資料,因此您可以安全地在生產前測試記憶存儲和新功能。
工作室測試具有與生產相同的 限制和配額。對於基於使用者數量計算的額度,結果額度可能很小,因為你是唯一的使用者進行 Studio 測試。當從工作室測試時,您也可能會注意到稍微高於使用在生產中的延遲和錯誤率,是因為進行驗證存取和權限的一些額外檢查。
要了解如何在實時體驗或在工作室測試時偵錯記憶儲存的方法,請使用 開發者控制台。