MemoryStoreService เป็นบริการข้อมูลที่มีความสามารถในการประมวลผลสูงและมีความหน่วงต่ำ ซึ่งให้การเก็บข้อมูลในหน่วยความจำที่รวดเร็วและสามารถเข้าถึงได้จากเซิร์ฟเวอร์ทั้งหมดในเซสชันที่ใช้งานอยู่ Memory Stores เหมาะสำหรับข้อมูลที่เปลี่ยนแปลงบ่อยและชั่วคราวซึ่งไม่จำเป็นต้องมีความทนทาน เนื่องจากเข้าถึงได้เร็วกว่าและจะหายไปเมื่อถึงอายุการใช้งานสูงสุด สำหรับข้อมูลที่ต้องการให้คงอยู่ระหว่างเซสชัน ให้ใช้ data stores.
โครงสร้างข้อมูล
แทนที่จะเข้าถึงข้อมูลดิบโดยตรง หน่วยความจำมีโครงสร้างข้อมูลพื้นฐานสามประเภทที่แชร์กันระหว่างเซิร์ฟเวอร์เพื่อการประมวลผลที่รวดเร็ว: sorted map, queue, และ hash map. โครงสร้างข้อมูลแต่ละประเภทเหมาะสำหรับกรณีการใช้งานที่เฉพาะเจาะจง:
- การจับคู่ตามทักษะ - บันทึกข้อมูลผู้ใช้ เช่น ระดับทักษะ ใน queue ที่แชร์กันระหว่างเซิร์ฟเวอร์ และใช้เซิร์ฟเวอร์ล็อบบี้เพื่อทำการจับคู่เป็นระยะๆ
- การซื้อขายและการประมูลข้ามเซิร์ฟเวอร์ - เปิดให้มีการซื้อขายทั่วไประหว่างเซิร์ฟเวอร์ที่แตกต่างกัน ซึ่งผู้ใช้สามารถเสนอราคาสำหรับรายการที่มีราคาเปลี่ยนแปลงแบบเรียลไทม์ โดยใช้ sorted map ของคู่คีย์-ค่า
- กระดานผู้นำระดับโลก - เก็บและอัปเดตอันดับผู้ใช้ในกระดานผู้นำที่แชร์กันภายใน sorted map
- สินค้าคงคลังที่แชร์กัน - บันทึกสินค้าคงคลังและสถิติใน hash map ที่แชร์กัน ซึ่งผู้ใช้สามารถใช้สินค้าคงคลังร่วมกันได้
- แคชสำหรับข้อมูลที่คงอยู่ - ซิงค์และคัดลอกข้อมูลที่คงอยู่ใน data store ไปยัง hash map ของหน่วยความจำที่สามารถทำหน้าที่เป็นแคชและปรับปรุงประสิทธิภาพของเกมของคุณ
โดยทั่วไป หากคุณต้องการเข้าถึงข้อมูลตามคีย์เฉพาะ ให้ใช้ hash map หากคุณต้องการให้ข้อมูลนั้นมีการจัดเรียง ให้ใช้ sorted map หากคุณต้องการประมวลผลข้อมูลของคุณในลำดับเฉพาะ ให้ใช้ queue
ข้อจำกัดและโควต้า
เพื่อรักษาความสามารถในการขยายตัวและประสิทธิภาพของระบบ หน่วยความจำมีโควต้าการใช้งานข้อมูลสำหรับขนาดหน่วยความจำ, การเรียก API, และขนาดของโครงสร้างข้อมูล
หน่วยความจำมีนโยบายการลบตามเวลาหมดอายุ ซึ่งเรียกอีกอย่างว่าเวลาในการมีชีวิต (TTL) รายการจะถูกลบออกหลังจากหมดอายุ และโควต้าหน่วยความจำจะถูกปล่อยให้ว่างสำหรับรายการใหม่ เมื่อคุณถึงขีดจำกัดหน่วยความจำ การเรียกเขียนทั้งหมดที่ตามมาจะล้มเหลวจนกว่ารายการจะหมดอายุหรือคุณลบออกด้วยตนเอง
โควต้าขนาดหน่วยความจำ
โควต้าหน่วยความจำจำกัดปริมาณหน่วยความจำทั้งหมดที่เกมสามารถใช้ได้ มันไม่ใช่ค่าคงที่ แต่จะเปลี่ยนแปลงไปตามจำนวนผู้ใช้ในเกมตามสูตร 64 KB + 1.2 KB * [จำนวนผู้ใช้] โควต้าจะใช้ในระดับเกมแทนที่จะเป็นระดับเซิร์ฟเวอร์
เมื่อผู้ใช้เข้าร่วมเกม โควต้าหน่วยความจำเพิ่มเติมจะพร้อมใช้งานทันที เมื่อผู้ใช้ออกจากเกม โควต้าจะไม่ลดลงทันที จะมีระยะเวลาการติดตามเป็นเวลาแปดวันก่อนที่โควต้าจะประเมินค่าใหม่เป็นค่าที่ต่ำกว่า
หลังจากเกมของคุณถึงโควต้าขนาดหน่วยความจำ การเรียก API ใดๆ ที่เพิ่มขนาดหน่วยความจำจะล้มเหลวเสมอ การเรียกที่ลดลงหรืไม่เปลี่ยนแปลงขนาดหน่วยความจำยังคงสำเร็จ
ด้วยแดชบอร์ด observability คุณสามารถดูโควต้าขนาดหน่วยความจำของเกมของคุณแบบเรียลไทม์โดยใช้แผนภูมิ การใช้งานหน่วยความจำ
ขีดจำกัดการเรียก API
โควต้า request unit จะใช้กับการเรียก API ของ MemoryStoreService ทุกครั้ง โควตานี้คือ 1000 + 120 * [จำนวนผู้ใช้ที่ใช้งานพร้อมกัน] หน่วยการเรียกต่อหนึ่งนาที
การเรียก API ส่วนใหญ่จะใช้เพียงหนึ่งหน่วยการเรียก โดยมีข้อยกเว้นบางประการ:
MemoryStoreSortedMap:GetRangeAsync()
ใช้หน่วยตามจำนวนรายการที่ส่งคืน ตัวอย่างเช่น หากวิธีนี้ส่งคืน 10 รายการ การเรียกจะนับเป็น 10 หน่วยการเรียก หากส่งคืนการตอบสนองว่าง จะนับเป็นหนึ่งหน่วยการเรียก
ใช้หน่วยตามจำนวนรายการที่ส่งคืน เช่นเดียวกับ MemoryStoreSortedMap:GetRangeAsync() แต่ใช้หน่วยเพิ่มเติมทุกสองวินาทีในขณะที่อ่าน กำหนดเวลาการอ่านสูงสุดด้วยพารามิเตอร์ waitTimeout
MemoryStoreHashMap:UpdateAsync()
ใช้หน่วยขั้นต่ำสองหน่วย
MemoryStoreHashMap:ListItemsAsync()
ใช้หน่วย [จำนวนพาร์ติชันที่สแกน] + [รายการที่ส่งคืน]
โควต้าการเรียกจะใช้ในระดับเกมแทนที่จะเป็นระดับเซิร์ฟเวอร์ ซึ่งให้ความยืดหยุ่นในการจัดสรรการเรียกระหว่างเซิร์ฟเวอร์ตราบใดที่อัตราการเรียกรวมไม่เกินโควต้า หากคุณเกินโควต้า คุณจะได้รับการตอบสนองข้อผิดพลาดเมื่อบริการจำกัดการเรียกของคุณ
ด้วยฟีเจอร์ observability ที่มีอยู่ คุณสามารถดูโควตาหน่วยการเรียกของเกมของคุณแบบเรียลไทม์
ขีดจำกัดขนาดโครงสร้างข้อมูล
สำหรับ sorted map หรือ queue เดียว ขีดจำกัดขนาดและจำนวนรายการต่อไปนี้จะใช้:
- จำนวนรายการสูงสุด: 1,000,000
- ขนาดรวมสูงสุด (รวมถึงคีย์สำหรับ sorted map): 100 MB
ขีดจำกัดต่อพาร์ติชัน
แนวทางปฏิบัติที่ดีที่สุด
เพื่อให้รูปแบบการใช้งานหน่วยความจำของคุณมีประสิทธิภาพและหลีกเลี่ยงการถึง ข้อจำกัด ให้ปฏิบัติตามแนวทางปฏิบัติที่ดีที่สุดเหล่านี้:
ลบรายการที่ประมวลผลแล้ว การทำความสะอาดรายการที่อ่านอย่างสม่ำเสมอโดยใช้วิธี MemoryStoreQueue:RemoveAsync() สำหรับ queue และ MemoryStoreSortedMap:RemoveAsync() สำหรับ sorted maps สามารถปล่อยหน่วยความจำและทำให้โครงสร้างข้อมูลทันสมัย
ตั้งเวลาในการหมดอายุให้สั้นที่สุดเท่าที่จะเป็นไปได้เมื่อเพิ่มข้อมูล แม้ว่าเวลาหมดอายุเริ่มต้นจะเป็น 45 วันสำหรับทั้ง MemoryStoreQueue:AddAsync() และ MemoryStoreSortedMap:SetAsync() การตั้งเวลาให้สั้นที่สุดสามารถทำความสะอาดข้อมูลเก่าโดยอัตโนมัติเพื่อป้องกันไม่ให้ข้อมูลเหล่านั้นเติมเต็มโควต้าการใช้งานหน่วยความจำของคุณ
- อย่าเก็บข้อมูลจำนวนมากที่มีเวลาหมดอายุยาว เพราะมีความเสี่ยงที่จะเกินโควต้าหน่วยความจำของคุณและอาจทำให้เกิดปัญหาที่อาจทำให้เกมของคุณเสียหาย
- ควรลบรายการที่ไม่จำเป็นออกอย่างชัดเจนหรือกำหนดเวลาหมดอายุให้สั้น
- โดยทั่วไป คุณควรใช้การลบอย่างชัดเจนเพื่อปล่อยหน่วยความจำและการหมดอายุของรายการเป็นกลไกความปลอดภัยเพื่อป้องกันไม่ให้รายการที่ไม่ได้ใช้งานใช้หน่วยความจำเป็นระยะเวลานาน
เก็บเฉพาะค่าที่จำเป็นในหน่วยความจำ
ตัวอย่างเช่น สำหรับเกมบ้านประมูล คุณเพียงแค่ต้องรักษาการเสนอราคาสูงสุด คุณสามารถใช้ MemoryStoreSortedMap:UpdateAsync() บนคีย์หนึ่งเพื่อรักษาการเสนอราคาสูงสุดแทนที่จะเก็บการเสนอราคาทั้งหมดในโครงสร้างข้อมูลของคุณ
ใช้ exponential backoff เพื่อช่วยให้คุณอยู่ต่ำกว่าโควต้าการเรียก API
ตัวอย่างเช่น หากคุณได้รับ DataUpdateConflict คุณอาจลองใหม่หลังจากสองวินาที จากนั้นสี่ แปด เป็นต้น แทนที่จะส่งคำขอไปยัง MemoryStoreService อย่างต่อเนื่องเพื่อให้ได้การตอบสนองที่ถูกต้อง
แบ่งโครงสร้างข้อมูลขนาดใหญ่เป็นโครงสร้างขนาดเล็กหลายๆ โครงสร้างโดยการ sharding
มักจะจัดการข้อมูลในโครงสร้างขนาดเล็กได้ง่ายกว่าการเก็บทุกอย่างในโครงสร้างข้อมูลขนาดใหญ่เพียงโครงสร้างเดียว วิธีนี้ยังช่วยหลีกเลี่ยงการใช้งานและขีดจำกัดอัตราได้อีกด้วย ตัวอย่างเช่น หากคุณมี sorted map ที่ใช้คีย์ที่มีพรีฟิก ให้พิจารณาแยกแต่ละพรีฟิกออกเป็น sorted map ของตนเอง สำหรับเกมที่มีความนิยมสูง คุณอาจแยกผู้ใช้เป็นหลายแผนที่ตามหลักฐานสุดท้ายของ ID ผู้ใช้ของพวกเขา
Shard คีย์ที่เข้าถึงบ่อยใน hash maps โดยมีสำเนาหลายๆ คีย์เพื่อกระจายโหลด
บีบอัดค่าที่เก็บ
ตัวอย่างเช่น พิจารณาใช้ LZW อัลกอริธึมเพื่อลดขนาดค่าที่เก็บ
ลงทะเบียนในบริการขยาย
คุณสามารถเพิ่มโควต้าการจัดเก็บและการเรียกของคุณโดยการเข้าร่วม Extended Services
การสังเกต
แดชบอร์ด Observability ให้ข้อมูลเชิงลึกและการวิเคราะห์สำหรับการติดตามและแก้ไขปัญหาการใช้งานหน่วยความจำของคุณ ด้วยแผนภูมิที่อัปเดตแบบเรียลไทม์ในด้านต่างๆ ของการใช้งานหน่วยความจำและการเรียก API คุณสามารถติดตามรูปแบบการใช้งานหน่วยความจำของเกมของคุณ ดูโควต้าที่จัดสรรในปัจจุบัน ติดตามสถานะ API และระบุปัญหาที่อาจเกิดขึ้นเพื่อเพิ่มประสิทธิภาพ
ตารางต่อไปนี้แสดงและอธิบายรหัสสถานะทั้งหมดของการตอบสนอง API ที่มีอยู่ในแผนภูมิ จำนวนคำขอโดยสถานะ และ คำขอตาม API x สถานะ ของแดชบอร์ดการสังเกต สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีการแก้ไขข้อผิดพลาดเหล่านี้ โปรดดูที่ การแก้ไขปัญหา สำหรับโควต้าหรือขีดจำกัดเฉพาะที่ข้อผิดพลาดเกี่ยวข้อง โปรดดูที่ ข้อจำกัดและโควต้า.
| รหัสสถานะ | คำอธิบาย |
|---|---|
| Success | สำเร็จ. |
| DataStructureMemoryOverLimit | เกินขีดจำกัดขนาดหน่วยความจำระดับโครงสร้างข้อมูล (100 MB). |
| DataUpdateConflict | เกิดความขัดแย้งเนื่องจากการอัปเดตพร้อมกัน. |
| AccessDenied | ไม่ได้รับอนุญาตให้เข้าถึงข้อมูลเกม คำขอนี้ไม่ใช้หน่วยการเรียกหรือโควต้า. |
| InternalError | ข้อผิดพลาดภายใน. |
| InvalidRequest | คำขอไม่มีข้อมูลที่จำเป็นหรือมีข้อมูลที่ไม่ถูกต้อง. |
| DataStructureItemsOverLimit | เกินขีดจำกัดจำนวนรายการระดับโครงสร้างข้อมูล (1M). |
| NoItemFound | ไม่พบรายการใน MemoryStoreQueue:ReadAsync() หรือ MemoryStoreSortedMap:UpdateAsync() ReadAsync() จะตรวจสอบทุก 2 วินาทีและส่งคืนรหัสสถานะนี้จนกว่าจะพบรายการในคิว. |
| DataStructureRequestsOverLimit | เกินขีดจำกัดหน่วยการเรียกระดับโครงสร้างข้อมูล (100,000 หน่วยการเรียกต่อหนึ่งนาที). |
| PartitionRequestsOverLimit | เกินขีดจำกัดหน่วยการเรียกพาร์ติชัน. |
| TotalRequestsOverLimit | เกินขีดจำกัดหน่วยการเรียกระดับจักรวาล. |
| TotalMemoryOverLimit | เกินโควต้าหน่วยความจำระดับจักรวาล. |
| ItemValueSizeTooLarge | ขนาดค่ามากเกินไป (32 KB). |
ตารางต่อไปนี้แสดงรหัสสถานะจากฝั่งลูกค้า ซึ่งขณะนี้ไม่สามารถใช้ได้ในแดชบอร์ดการสังเกต
| รหัสสถานะ | คำอธิบาย |
|---|---|
| InternalError | ข้อผิดพลาดภายใน. |
| UnpublishedPlace | คุณต้องเผยแพร่สถานที่นี้เพื่อใช้ MemoryStoreService. |
| InvalidClientAccess | MemoryStoreService ต้องถูกเรียกจากเซิร์ฟเวอร์. |
| InvalidExpirationTime | ฟิลด์ 'expiration' ต้องอยู่ระหว่าง 0 ถึง 3,888,000. |
| InvalidRequest | ไม่สามารถแปลงค่าเป็น json. |
| InvalidRequest | ไม่สามารถแปลง sortKey เป็นหมายเลขหรือสตริงที่ถูกต้อง. |
| TransformCallbackFailed | ไม่สามารถเรียกใช้ฟังก์ชันการแปลงได้. |
| RequestThrottled | คำขอ MemoryStores ล่าสุดเกินหนึ่งหรือหลายข้อจำกัด. |
| UpdateConflict | เกินจำนวนครั้งสูงสุดในการลองใหม่. |
การแก้ไขปัญหา
ตารางต่อไปนี้แสดงและอธิบายวิธีแก้ไขที่แนะนำสำหรับรหัสสถานะการตอบสนองแต่ละรหัส:
| ข้อผิดพลาด | ตัวเลือกการแก้ไขปัญหา |
|---|---|
| DataStructureRequestsOverLimit / PartitionRequestsOverLimit |
|
| TotalRequestsOverLimit | |
| DataStructureItemsOverLimit |
|
| DataStructureMemoryOverLimit | |
| TotalMemoryOverLimit | |
| DataUpdateConflict |
ตัวอย่างการยกเลิกคำขอ |
| Internal Error |
|
| InvalidRequest |
|
| ItemValueSizeTooLarge |
|
ทดสอบและแก้ไขใน Studio
ข้อมูลใน MemoryStoreService จะถูกแยกออกระหว่าง Studio และการผลิต ดังนั้นการเปลี่ยนแปลงข้อมูลใน Studio จะไม่ส่งผลต่อพฤติกรรมการผลิต ซึ่งหมายความว่าการเรียก API ของคุณจาก Studio จะไม่เข้าถึงข้อมูลการผลิต ทำให้คุณสามารถทดสอบหน่วยความจำและฟีเจอร์ใหม่ได้อย่างปลอดภัยก่อนที่จะนำไปใช้ในผลิต
การทดสอบใน Studio มี ข้อจำกัดและโควต้า เช่นเดียวกับการผลิต สำหรับโควต้าที่คำนวณตามจำนวนผู้ใช้ โควต้าที่ได้อาจมีขนาดเล็กมากเนื่องจากคุณเป็นผู้ใช้เพียงคนเดียวในการทดสอบใน Studio เมื่อทดสอบจาก Studio คุณอาจสังเกตเห็นความหน่วงที่สูงขึ้นเล็กน้อยและอัตราข้อผิดพลาดที่สูงขึ้นเมื่อเปรียบเทียบกับการใช้งานในผลิตเนื่องจากมีการตรวจสอบเพิ่มเติมที่ดำเนินการเพื่อยืนยันการเข้าถึงและสิทธิ์
สำหรับข้อมูลเกี่ยวกับวิธีการแก้ไขหน่วยความจำในเกมสดหรือเมื่อทดสอบใน Studio ให้ใช้ Developer Console.