MemoryStoreService là một dịch vụ dữ liệu có thông lượng cao và độ trễ thấp cung cấp lưu trữ dữ liệu trong bộ nhớ nhanh chóng có thể truy cập từ tất cả các máy chủ trong một phiên trực tiếp. Bộ nhớ phù hợp cho dữ liệu thường xuyên và tạm thời thay đổi nhanh chóng và không cần bền vững, vì chúng nhanh hơn để truy cập và biến mất khi đạt đến thời gian sống tối đa. Đối với dữ liệu cần tồn tại qua các phiên, hãy sử dụng cửa hàng dữ liệu.
Cấu trúc dữ liệu
Thay vì truy cập trực tiếp vào dữ liệu thô, bộ nhớ có ba cấu trúc dữ liệu nguyên thủy được chia sẻ giữa các máy chủ để xử lý nhanh chóng: bản đồ đã sắp xếp, hàng đợi, và bản đồ băm. Mỗi cấu trúc dữ liệu phù hợp với một số trường hợp sử dụng nhất định:
- Ghép cặp dựa trên kỹ năng - Lưu thông tin người dùng, chẳng hạn như trình độ kỹ năng, trong một hàng đợi chia sẻ giữa các máy chủ, và sử dụng các máy chủ sảnh để thực hiện ghép cặp định kỳ.
- Giao dịch và đấu giá giữa các máy chủ - Cho phép giao dịch toàn cầu giữa các máy chủ khác nhau, nơi người dùng có thể đặt giá cho các mặt hàng với giá thay đổi theo thời gian thực, với một bản đồ đã sắp xếp của các cặp khóa-giá trị.
- Bảng xếp hạng toàn cầu - Lưu trữ và cập nhật xếp hạng người dùng trên một bảng xếp hạng chia sẻ bên trong một bản đồ đã sắp xếp.
- Kho hàng chia sẻ - Lưu trữ các mặt hàng và thống kê trong một bản đồ băm chia sẻ, nơi người dùng có thể sử dụng các mặt hàng kho hàng đồng thời với nhau.
- Bộ nhớ đệm cho dữ liệu bền vững - Đồng bộ và sao chép dữ liệu bền vững của bạn trong một cửa hàng dữ liệu vào một bản đồ băm bộ nhớ có thể hoạt động như một bộ nhớ đệm và cải thiện hiệu suất trò chơi của bạn.
Nói chung, nếu bạn cần truy cập dữ liệu dựa trên một khóa cụ thể, hãy sử dụng một bản đồ băm. Nếu bạn cần dữ liệu đó được sắp xếp, hãy sử dụng một bản đồ đã sắp xếp. Nếu bạn cần xử lý dữ liệu của mình theo một thứ tự cụ thể, hãy sử dụng một hàng đợi.
Giới hạn và hạn ngạch
Để duy trì khả năng mở rộng và hiệu suất hệ thống, bộ nhớ có hạn ngạch sử dụng dữ liệu cho kích thước bộ nhớ, yêu cầu API và kích thước cấu trúc dữ liệu.
Bộ nhớ có chính sách thu hồi dựa trên thời gian hết hạn, còn được gọi là thời gian sống (TTL). Các mục sẽ bị thu hồi sau khi hết hạn, và hạn ngạch bộ nhớ sẽ được giải phóng cho các mục mới. Khi bạn đạt đến giới hạn bộ nhớ, tất cả các yêu cầu ghi tiếp theo sẽ thất bại cho đến khi các mục hết hạn hoặc bạn xóa chúng thủ công.
Hạn ngạch kích thước bộ nhớ
Hạn ngạch bộ nhớ giới hạn tổng lượng bộ nhớ mà một trò chơi có thể tiêu thụ. Đây không phải là một giá trị cố định; thay vào đó, nó thay đổi theo thời gian tùy thuộc vào số lượng người dùng trong trò chơi theo công thức 64 KB + 1.2 KB * [số lượng người dùng]. Hạn ngạch áp dụng ở cấp độ trò chơi thay vì cấp độ máy chủ.
Khi người dùng tham gia trò chơi, hạn ngạch bộ nhớ bổ sung có sẵn ngay lập tức. Khi người dùng rời khỏi trò chơi, hạn ngạch không giảm ngay lập tức. Có một khoảng thời gian theo dõi là tám ngày trước khi hạn ngạch được đánh giá lại thành một giá trị thấp hơn.
Sau khi trò chơi của bạn đạt đến hạn ngạch kích thước bộ nhớ, bất kỳ yêu cầu API nào làm tăng kích thước bộ nhớ đều sẽ thất bại. Các yêu cầu giảm hoặc không thay đổi kích thước bộ nhớ vẫn thành công.
Với bảng điều khiển khả năng quan sát, bạn có thể xem hạn ngạch kích thước bộ nhớ của trò chơi trong thời gian thực bằng biểu đồ Sử dụng Bộ nhớ.
Giới hạn yêu cầu API
Một hạn ngạch đơn vị yêu cầu áp dụng cho tất cả các cuộc gọi API MemoryStoreService. Hạn ngạch này là 1000 + 120 * [số lượng người dùng đồng thời] đơn vị yêu cầu mỗi phút.
Hầu hết các cuộc gọi API chỉ tiêu thụ một đơn vị yêu cầu, với một vài ngoại lệ:
MemoryStoreSortedMap:GetRangeAsync()
Tiêu thụ đơn vị dựa trên số lượng mục được trả về. Ví dụ, nếu phương thức này trả về 10 mục, cuộc gọi sẽ tính là 10 đơn vị yêu cầu. Nếu nó trả về một phản hồi trống, nó sẽ tính là một đơn vị yêu cầu.
Tiêu thụ đơn vị dựa trên số lượng mục được trả về, giống như MemoryStoreSortedMap:GetRangeAsync(), nhưng tiêu thụ một đơn vị bổ sung mỗi hai giây trong khi đọc. Chỉ định thời gian đọc tối đa với tham số waitTimeout.
MemoryStoreHashMap:UpdateAsync()
Tiêu thụ tối thiểu hai đơn vị.
MemoryStoreHashMap:ListItemsAsync()
Tiêu thụ [số lượng phân vùng quét] + [mục được trả về] đơn vị.
Hạn ngạch yêu cầu cũng được áp dụng ở cấp độ trò chơi thay vì cấp độ máy chủ. Điều này cung cấp tính linh hoạt để phân bổ các yêu cầu giữa các máy chủ miễn là tổng tỷ lệ yêu cầu không vượt quá hạn ngạch. Nếu bạn vượt quá hạn ngạch, bạn sẽ nhận được phản hồi lỗi khi dịch vụ giới hạn các yêu cầu của bạn.
Với tính năng khả năng quan sát có sẵn, bạn có thể xem hạn ngạch đơn vị yêu cầu của trò chơi trong thời gian thực.
Giới hạn kích thước cấu trúc dữ liệu
Đối với một bản đồ đã sắp xếp hoặc hàng đợi đơn, các giới hạn kích thước và số lượng mục sau đây áp dụng:
- Số lượng mục tối đa: 1.000.000
- Kích thước tổng tối đa (bao gồm các khóa cho bản đồ đã sắp xếp): 100 MB
Giới hạn theo phân vùng
Thực hành tốt nhất
Để giữ cho mô hình sử dụng bộ nhớ của bạn tối ưu và tránh đạt đến giới hạn, hãy làm theo các thực hành tốt nhất sau:
Xóa các mục đã xử lý. Thường xuyên dọn dẹp các mục đã đọc bằng cách sử dụng phương thức MemoryStoreQueue:RemoveAsync() cho hàng đợi và MemoryStoreSortedMap:RemoveAsync() cho các bản đồ đã sắp xếp có thể giải phóng bộ nhớ và giữ cho cấu trúc dữ liệu luôn cập nhật.
Đặt thời gian hết hạn ở khoảng thời gian nhỏ nhất có thể khi thêm dữ liệu. Mặc dù thời gian hết hạn mặc định là 45 ngày cho cả MemoryStoreQueue:AddAsync() và MemoryStoreSortedMap:SetAsync(), việc đặt thời gian ngắn nhất có thể có thể tự động dọn dẹp dữ liệu cũ để ngăn chúng làm đầy hạn ngạch sử dụng bộ nhớ của bạn.
- Đừng lưu trữ một lượng lớn dữ liệu với thời gian hết hạn dài, vì điều này có nguy cơ vượt quá hạn ngạch bộ nhớ của bạn và có thể gây ra các vấn đề có thể làm hỏng toàn bộ trò chơi của bạn.
- Luôn xóa rõ ràng các mục không cần thiết hoặc đặt thời gian hết hạn ngắn cho mục.
- Nói chung, bạn nên sử dụng xóa rõ ràng để giải phóng bộ nhớ và thời gian hết hạn của mục như một cơ chế an toàn để ngăn các mục không sử dụng chiếm bộ nhớ trong một khoảng thời gian dài.
Chỉ giữ các giá trị cần thiết trong bộ nhớ.
Ví dụ, đối với một trò chơi nhà đấu giá, bạn chỉ cần duy trì giá thầu cao nhất. Bạn có thể sử dụng MemoryStoreSortedMap:UpdateAsync() trên một khóa để giữ giá thầu cao nhất thay vì giữ tất cả các giá thầu trong cấu trúc dữ liệu của bạn.
Sử dụng giảm dần theo cấp số nhân để giúp giữ dưới giới hạn yêu cầu API.
Ví dụ, nếu bạn nhận được một DataUpdateConflict, bạn có thể thử lại sau hai giây, sau đó là bốn, tám, v.v. thay vì liên tục gửi yêu cầu đến MemoryStoreService để nhận phản hồi chính xác.
Chia nhỏ các cấu trúc dữ liệu lớn thành nhiều cấu trúc nhỏ hơn bằng cách chia nhỏ.
Thường thì dễ quản lý dữ liệu trong các cấu trúc nhỏ hơn hơn là lưu trữ mọi thứ trong một cấu trúc dữ liệu lớn. Cách tiếp cận này cũng có thể giúp tránh các giới hạn sử dụng và tỷ lệ. Ví dụ, nếu bạn có một bản đồ đã sắp xếp sử dụng tiền tố cho các khóa của nó, hãy xem xét việc tách mỗi tiền tố thành một bản đồ đã sắp xếp riêng. Đối với một trò chơi đặc biệt phổ biến, bạn thậm chí có thể tách người dùng thành nhiều bản đồ dựa trên các chữ số cuối cùng của ID người dùng của họ.
Chia nhỏ các khóa được truy cập thường xuyên trong các bản đồ băm với nhiều bản sao của khóa để phân phối tải.
Nén các giá trị đã lưu trữ.
Ví dụ, hãy xem xét việc sử dụng thuật toán LZW để giảm kích thước giá trị đã lưu trữ.
Đăng ký vào Dịch vụ Mở rộng.
Bạn có thể tăng hạn ngạch Lưu trữ và Hạn ngạch Yêu cầu của mình bằng cách tham gia vào Dịch vụ Mở rộng.
Khả năng quan sát
Bảng điều khiển Khả năng quan sát cung cấp thông tin và phân tích để theo dõi và khắc phục sự cố sử dụng bộ nhớ của bạn. Với các biểu đồ cập nhật theo thời gian thực về các khía cạnh khác nhau của việc sử dụng bộ nhớ và yêu cầu API của bạn, bạn có thể theo dõi mô hình sử dụng bộ nhớ của trò chơi, xem các hạn ngạch hiện tại đã được phân bổ, theo dõi trạng thái API và xác định các vấn đề tiềm ẩn để tối ưu hóa hiệu suất.
Bảng sau liệt kê và mô tả tất cả các mã trạng thái của phản hồi API có sẵn trên biểu đồ Số lượng yêu cầu theo Trạng thái và Yêu cầu theo API x Trạng thái của Bảng điều khiển Khả năng quan sát. Để biết thêm thông tin về cách giải quyết các lỗi này, hãy xem Khắc phục sự cố. Đối với hạn ngạch hoặc giới hạn cụ thể mà một lỗi liên quan đến, hãy xem Giới hạn và Hạn ngạch.
| Mã trạng thái | Mô tả |
|---|---|
| Thành công | Thành công. |
| DataStructureMemoryOverLimit | Vượt quá giới hạn kích thước bộ nhớ cấp cấu trúc dữ liệu (100 MB). |
| DataUpdateConflict | Xung đột do cập nhật đồng thời. |
| AccessDenied | Không được phép truy cập dữ liệu trò chơi. Yêu cầu này không tiêu thụ đơn vị yêu cầu hoặc sử dụng hạn ngạch. |
| Lỗi nội bộ | Lỗi nội bộ. |
| InvalidRequest | Yêu cầu không có thông tin cần thiết hoặc có thông tin bị sai định dạng. |
| DataStructureItemsOverLimit | Vượt quá giới hạn số lượng mục cấp cấu trúc dữ liệu (1M). |
| NoItemFound | Không tìm thấy mục nào trong MemoryStoreQueue:ReadAsync() hoặc MemoryStoreSortedMap:UpdateAsync(). ReadAsync() sẽ kiểm tra mỗi 2 giây và trả về mã trạng thái này cho đến khi tìm thấy các mục trong hàng đợi. |
| DataStructureRequestsOverLimit | Vượt quá giới hạn đơn vị yêu cầu cấp cấu trúc dữ liệu (100.000 đơn vị yêu cầu mỗi phút). |
| PartitionRequestsOverLimit | Vượt quá giới hạn đơn vị yêu cầu phân vùng. |
| TotalRequestsOverLimit | Vượt quá giới hạn đơn vị yêu cầu cấp vũ trụ. |
| TotalMemoryOverLimit | Vượt quá hạn ngạch bộ nhớ cấp vũ trụ. |
| ItemValueSizeTooLarge | Kích thước giá trị vượt quá giới hạn (32 KB). |
Bảng sau liệt kê các mã trạng thái từ phía khách hàng, hiện không có sẵn trên Bảng điều khiển Khả năng quan sát.
| Mã trạng thái | Mô tả |
|---|---|
| Lỗi nội bộ | Lỗi nội bộ. |
| UnpublishedPlace | Bạn phải xuất bản địa điểm này để sử dụng MemoryStoreService. |
| InvalidClientAccess | MemoryStoreService phải được gọi từ máy chủ. |
| InvalidExpirationTime | Trường 'expiration' phải nằm trong khoảng từ 0 đến 3.888.000. |
| InvalidRequest | Không thể chuyển đổi giá trị thành json. |
| InvalidRequest | Không thể chuyển đổi sortKey thành một số hoặc chuỗi hợp lệ. |
| TransformCallbackFailed | Không thể gọi hàm callback chuyển đổi. |
| RequestThrottled | Các yêu cầu MemoryStores gần đây đã chạm vào một hoặc nhiều giới hạn. |
| UpdateConflict | Vượt quá số lần thử tối đa. |
Khắc phục sự cố
Bảng sau liệt kê và mô tả giải pháp được khuyến nghị cho mỗi mã trạng thái phản hồi:
| Lỗi | Tùy chọn khắc phục sự cố |
|---|---|
| DataStructureRequestsOverLimit / PartitionRequestsOverLimit |
|
| TotalRequestsOverLimit | |
| DataStructureItemsOverLimit |
|
| DataStructureMemoryOverLimit | |
| TotalMemoryOverLimit | |
| DataUpdateConflict |
Ví dụ về Hủy Yêu cầu |
| Lỗi nội bộ |
|
| InvalidRequest |
|
| ItemValueSizeTooLarge |
|
Kiểm tra và gỡ lỗi trong Studio
Dữ liệu trong MemoryStoreService được cách ly giữa Studio và sản xuất, vì vậy việc thay đổi dữ liệu trong Studio không ảnh hưởng đến hành vi sản xuất. Điều này có nghĩa là các cuộc gọi API của bạn từ Studio không truy cập dữ liệu sản xuất, cho phép bạn an toàn kiểm tra bộ nhớ và các tính năng mới trước khi đưa vào sản xuất.
Kiểm tra trong Studio có cùng giới hạn và hạn ngạch như sản xuất. Đối với các hạn ngạch được tính toán dựa trên số lượng người dùng, hạn ngạch kết quả có thể rất nhỏ vì bạn là người dùng duy nhất cho việc kiểm tra Studio. Khi kiểm tra từ Studio, bạn cũng có thể nhận thấy độ trễ cao hơn một chút và tỷ lệ lỗi tăng cao hơn so với việc sử dụng trong sản xuất do một số kiểm tra bổ sung được thực hiện để xác minh quyền truy cập và quyền hạn.
Để biết thông tin về cách gỡ lỗi một bộ nhớ trong các trò chơi trực tiếp hoặc khi kiểm tra trong studio, hãy sử dụng Bảng điều khiển Nhà phát triển.