Bộ nhớ

*Nội dung này được dịch bằng AI (Beta) và có thể có lỗi. Để xem trang này bằng tiếng Anh, hãy nhấp vào đây.

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.

  • MemoryStoreQueue:ReadAsync()

    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

Xem 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()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áiYê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áiMô tả
Thành côngThành công.
DataStructureMemoryOverLimitVượt quá giới hạn kích thước bộ nhớ cấp cấu trúc dữ liệu (100 MB).
DataUpdateConflictXung đột do cập nhật đồng thời.
AccessDeniedKhô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ộ.
InvalidRequestYêu cầu không có thông tin cần thiết hoặc có thông tin bị sai định dạng.
DataStructureItemsOverLimitVượt quá giới hạn số lượng mục cấp cấu trúc dữ liệu (1M).
NoItemFoundKhô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.
DataStructureRequestsOverLimitVượ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).
PartitionRequestsOverLimitVượt quá giới hạn đơn vị yêu cầu phân vùng.
TotalRequestsOverLimitVượt quá giới hạn đơn vị yêu cầu cấp vũ trụ.
TotalMemoryOverLimitVượt quá hạn ngạch bộ nhớ cấp vũ trụ.
ItemValueSizeTooLargeKí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áiMô tả
Lỗi nội bộLỗi nội bộ.
UnpublishedPlaceBạn phải xuất bản địa điểm này để sử dụng MemoryStoreService.
InvalidClientAccessMemoryStoreService phải được gọi từ máy chủ.
InvalidExpirationTimeTrường 'expiration' phải nằm trong khoảng từ 0 đến 3.888.000.
InvalidRequestKhông thể chuyển đổi giá trị thành json.
InvalidRequestKhông thể chuyển đổi sortKey thành một số hoặc chuỗi hợp lệ.
TransformCallbackFailedKhông thể gọi hàm callback chuyển đổi.
RequestThrottledCác yêu cầu MemoryStores gần đây đã chạm vào một hoặc nhiều giới hạn.
UpdateConflictVượ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ỗiTùy chọn khắc phục sự cố
DataStructureRequestsOverLimit / PartitionRequestsOverLimit
  • Thêm một bộ nhớ đệm cục bộ bằng cách lưu thông tin vào một biến khác và kiểm tra lại sau một khoảng thời gian nhất định, chẳng hạn như 30 giây.
  • Sử dụng biểu đồ Số lượng yêu cầu theo Trạng thái để xác minh rằng bạn nhận được nhiều phản hồi Thành công hơn Không tìm thấy mục nào. Giới hạn số lần bạn chạm vào MemoryStoreService với một yêu cầu thất bại.
  • Thực hiện một khoảng thời gian ngắn giữa các yêu cầu.
  • Thực hiện các thực hành tốt nhất, bao gồm:
    • Chia nhỏ các cấu trúc dữ liệu của bạn nếu bạn nhận được một lượng lớn phản hồi DataStructureRequestsOverLimit/PartitionRequestsOverLimit.
    • Chia nhỏ các khóa bản đồ băm của bạn nếu bạn nhận được một lượng lớn phản hồi PartitionRequestsOverLimit trên các cuộc gọi bản đồ băm.
    • Giảm hoặc nhóm các cuộc gọi đến các cấu trúc dữ liệu cụ thể hoặc các khóa bản đồ băm nếu bạn thấy phản hồi PartitionRequestsOverLimit.
    • Thực hiện một giảm dần theo cấp số nhân để tìm ra tỷ lệ hợp lý của các yêu cầu để gửi.
TotalRequestsOverLimit
DataStructureItemsOverLimit
DataStructureMemoryOverLimit
TotalMemoryOverLimit
DataUpdateConflict
  • Thực hiện một khoảng thời gian ngắn giữa các yêu cầu để tránh nhiều yêu cầu cập nhật cùng một khóa vào cùng một thời điểm.
  • Đối với các bản đồ đã sắp xếp, sử dụng hàm callback trên phương thức MemoryStoreSortedMap:UpdateAsync() để hủy một yêu cầu sau một số lần thử nhất định, như đoạn mã mẫu sau đây cho thấy:
  • Ví dụ về Hủy Yêu cầu
    local MemoryStoreService = game:GetService("MemoryStoreService")
    local map = MemoryStoreService:GetSortedMap("AuctionItems")
    function placeBid(itemKey, bidAmount)
    map:UpdateAsync(itemKey, function(item)
    item = item or { highestBid = 0 }
    if item.highestBid < bidAmount then
    item.highestBid = bidAmount
    return item
    end
    print("mặt hàng là "..item.highestBid)
    return nil
    end, 1000)
    end
    placeBid("MyItem", 50)
    placeBid("MyItem", 40)
    print("xong")
  • Điều tra xem bạn có đang gọi MemoryStoreService một cách hiệu quả để tránh xung đột hay không. Lý tưởng nhất, bạn không nên gửi quá nhiều yêu cầu.
  • Thường xuyên xóa các mục ngay khi chúng đượ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.
Lỗi nội bộ
InvalidRequest
  • Đảm bảo rằng bạn bao gồm các tham số chính xác và hợp lệ trong yêu cầu của mình. Ví dụ về các tham số không hợp lệ bao gồm:
    • Một chuỗi trống
    • Một chuỗi vượt quá giới hạn độ dài
ItemValueSizeTooLarge
  • Chia nhỏ hoặc tách giá trị mục thành nhiều khóa.
    • Để tổ chức các khóa nhóm, hãy sắp xếp chúng theo thứ tự bảng chữ cái bằng cách thêm một prefix vào khóa.
  • Mã hóa hoặc nén các giá trị đã lưu trữ.

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.

©2026 Roblox Corporation. Roblox, logo Roblox và Powering Imagination là các nhãn hiệu đã đăng ký và chưa đăng ký của chúng tôi tại Hoa Kỳ và các quốc gia khác.