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 với 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 nối dựa trên kỹ năng - Lưu thông tin người dùng, chẳng hạn như mức kỹ năng, trong một hàng đợi chung giữa các máy chủ, và sử dụng các máy chủ phòng chờ để thực hiện ghép nối định kỳ.
  • Trao đổi và đấu giá giữa các máy chủ - Cho phép thương mại toàn cầu giữa các máy chủ khác nhau, nơi người dùng có thể đấu giá cho các mặt hàng với giá thay đổi theo thời gian, 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 thứ hạng người dùng trên một bảng xếp hạng chung bên trong một bản đồ sắp xếp.
  • Kho hàng dùng chung - Lưu các mục và thống kê trong một bản đồ băm chung, nơi người dùng có thể sử dụng các mục hàng tồn kho đồng thời với nhau.
  • Bộ nhớ đệm cho Dữ liệu Bền vững - Đồng bộ hóa 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ộ đệm và cải thiện hiệu suất của 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 bị thu hồi sau khi hết hạn, và hạn ngạch bộ nhớ đượ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 theo cách 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 64KB + 1.2KB * [số lượng người dùng]. Hạn ngạch này á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 truy hồi kéo dài tám ngày trước khi hạn ngạch được đánh giá lại thành 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 làm 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 của bạn theo thời gian thực sử dụng biểu đồ Sử dụng Bộ nhớ.

Hạn chế 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ố 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ụ các đơn vị dựa trên số lượng mục được trả lại. 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ó tính là một đơn vị yêu cầu.

  • MemoryStoreQueue:ReadAsync()

    Tiêu thụ các đơn vị dựa trên số lượng mục được trả lại, giống như MemoryStoreSortedMap:GetRangeAsync(), nhưng tiêu thụ thêm một đơn vị 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 nhất hai đơn vị.

  • MemoryStoreHashMap:ListItemsAsync()

    Tiêu thụ [số phân vùng được quét] + [mục được trả lại] đơ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 sự linh hoạt để phân bổ các yêu cầu giữa các máy chủ miễn là tỷ lệ yêu cầu tổng cộng 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 một phản hồi lỗi khi dịch vụ hạn chế 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 của bạn theo 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 duy nhất, 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á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 tiễn tốt nhất

Để giữ cho mẫu 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 những thực tiễn 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 các 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 được cập nhật.

  • Đặt thời gian hết hạn ở mức 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ể sẽ tự động dọn dẹp dữ liệu cũ để ngăn chúng lấp đầy hạn ngạch sử dụng bộ nhớ của bạn.

    • Khô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 các mục không cần thiết một cách rõ ràng hoặc đặt mộ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 mục như một cơ chế an toàn để ngăn các mục không sử dụng lấp đầy 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 đấu giá, bạn chỉ cần duy trì mức giá cao nhất. Bạn có thể sử dụng MemoryStoreSortedMap:UpdateAsync() trên một khóa để giữ mức giá cao nhất thay vì giữ tất cả các mức giá trong cấu trúc dữ liệu của bạn.

  • Sử dụng lùi lại theo cấp số nhân để giúp duy trì mức dưới các hạn ngạch 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 lại 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 phân vùng.

    Thường dễ dàng hơn để quản lý dữ liệu trong các cấu trúc nhỏ hơn thay vì 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 việc sử dụng và giới hạn 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 bản đồ sắp xếp của riêng nó. Đối với một trò chơi cực kỳ 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ủa ID người dùng của họ.

  • Chia các khóa thường xuyên được truy cập trong các bản đồ băm với nhiều bản sao của khóa để phân bổ 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ữ.

  • Tham gia vào Dịch vụ Mở rộng.

    Bạn có thể tăng hạn ngạch Lưu trữ và Yêu cầu của mình bằng cách đăng ký 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, bạn có thể theo dõi mẫu sử dụng bộ nhớ của trò chơi của bạn, xem các hạn ngạch đã phân bổ hiện tại, 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 những 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, 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 (100MB).
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 không hợp lệ.
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 trong MemoryStoreQueue:ReadAsync() hoặc MemoryStoreSortedMap:UpdateAsync(). ReadAsync() được 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 (32KB).

Bảng sau liệt kê các trạng thái mã 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 công bố nơi này để sử dụng MemoryStoreService.
InvalidClientAccessMemoryStoreService phải được gọi từ máy chủ.
InvalidExpirationTimeThời gian trường 'expiration' phải từ 0 đến 3,888,000.
InvalidRequestKhông thể chuyển đổi giá trị sang 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 hồi phiên chuyển đổi.
RequestThrottledCác yêu cầu gần đây vào MemoryStores đã đạt 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. Hạn chế số lần bạn truy cập MemoryStoreService với một yêu cầu thất bại.
  • Triển khai một độ trễ ngắn giữa các yêu cầu.
  • Thực hiện thực tiễn tốt nhất, bao gồm:
    • Chia nhỏ cấu trúc dữ liệu của bạn nếu bạn nhận được một số lượng đáng kể 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 số lượng đáng kể 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 lùi lại theo cấp số nhân để tìm tỷ lệ hợp lý cho các yêu cầu gửi đi.
TotalRequestsOverLimit
DataStructureItemsOverLimit
DataStructureMemoryOverLimit
TotalMemoryOverLimit
DataUpdateConflict
  • Triển khai một độ trễ 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 tại cùng một thời điểm.
  • Đối với các bản đồ sắp xếp, hãy sử dụng hàm gọi lại trên phương thức MemoryStoreSortedMap:UpdateAsync() để hủy bỏ một yêu cầu sau một số lần thử nhất định, như mã mẫu dưới đây cho thấy:
  • Ví dụ 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ục là "..item.highestBid)
    return nil
    end, 1000)
    end
    placeBid("MyItem", 50)
    placeBid("MyItem", 40)
    print("xong")
  • Điều tra để xem liệu bạn có gọi MemoryStoreService một cách hiệu quả để tránh xung đột hay không. Về lý tưởng, 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 phương thức MemoryStoreQueue:RemoveAsync() cho các 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. Các ví dụ về tham số không hợp lệ bao gồm:
    • Một chuỗi rỗng
    • Một chuỗi vượt quá giới hạn độ dài
ItemValueSizeTooLarge
  • Chia nhỏ hoặc phân tách giá trị mục thành nhiều khóa.
    • Để tổ chức các khóa được nhóm lại, hãy sắp xếp chúng theo thứ tự 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 vào dữ liệu sản xuất, cho phép bạn kiểm tra bộ nhớ và các tính năng mới một cách an toàn trước khi chuyển sang 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 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 trong việc kiểm tra Studio. Khi kiểm tra từ Studio, bạn cũng có thể nhận thấy độ trễ hơi cao hơn 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 bộ nhớ trên các trò chơi trực tiếp hoặc khi thử nghiệm ở studio, 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.