内存存储

*此内容使用人工智能(Beta)翻译,可能包含错误。若要查看英文页面,请点按 此处

MemoryStoreService 是一个高吞吐量和低延迟的数据服务,可以从活动会话中的所有服务器访问快速内存数据存储。 内存存储 适合频繁且临时的数据快速更改且不需要持久,因为它们更快地访问并在达到最大使用寿命时消失。对于需要在会话之间持续的数据,请使用 数据存储

数据结构

而不是直接访问原始数据,内存存储有三种原始数据结构在服务器之间共享快速处理:排序地图队列哈希地图。每个数据结构都很适合某些使用案例:

  • 技能基于匹配 - 将用户信息,例如技能等级,保存在服务器之间的共享 队列 中,并使用大厅服务器定期运行匹配。
  • 跨服务器交易和拍卖 - 启用不同服务器之间的通用交易,用户可以在具有实时变化价格的物品上投标,使用排序的键值对组合。
  • 全球排行榜 - 在排序地图内的共享排行榜中存储和更新用户排名。
  • 共享库存 - 将库存物品和统计数据保存在共享 哈希地图 中,用户可以同时使用库存物品与 друг другом。
  • 永久数据的缓存 - 将永久数据同步到数据存储库复制到内存存储库 哈希地图 中,以便作为缓存并提高体验性能。

一通用来说,如果您需要基于特定键访问数据,请使用哈希地图。如果需要订购该数据,请使用排序的地图。如果您需要按特定顺序处理数据,请使用队列。

限制和配额

为了保持可扩展性和系统性能,内存存储有数据使用限额为内存大小、API请求和数据结构大小。

内存存储有基于过期时间的驱逐政策,也称为存活时间(TTL)。项目在过期后被驱逐,内存配额被释放以用于新的入口。当您达到内存限制时,所有后续的写入请求都会失败,直到项目过期或您手动删除它们。

内存大小限制

内存配额限制体验可以消耗的内存总量。它不是一个固定值。相反,它随着时间的推移会根据体验中的用户数量变化以下公式: 64KB + 1KB * [用户数量] 。限额适用于体验级别,而不是服务器等级。

当用户加入体验时,额外的内存容量立即可用。当用户离开体验时,配额不会立即减少。在限额重新评估为更低值之前,有一个追溯期为八天。

体验达到内存大小限制后,任何增加内存大小的 API 请求都会失败。要求减少或不更改内存大小仍然成功。

使用观察性仪表板,您可以使用 内存使用 图表实时查看体验的内存大小配额。

API 请求限制

对于 API 请求限制,有一个 请求单元 额度适用于所有 MemoryStoreService API 调用。配额为 1000 + 100 * [同时用户数量] 每分钟的请求单位。

大多数 API 调用只消耗一个请求单元,但有一些例外:

请求限额也应用于体验级别而不是服务器等级别。这可以灵活地分配服务器之间的请求,只要总请求率不超过额度就行。如果您超过配额,当服务限制您的请求时,您将收到错误响应。

启用了可观察功能后,您可以实时查看体验的请求单位数量。

数据结构大小限制

对于单个排序的地图或队列,以下尺寸和物品数限制适用:

  • 最大物品数量: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 转换为有效的数字或字符串
转换调用失败无法调用变形回调函数。
请求限制最近的内存存储请求触发了一个或多个限制。
更新冲突超过了最大重试次数。

排除问题

下表列出并描述了每个响应状态代验证码的推荐解决方案:

错误排除问题选项
数据结构请求超限/分区请求超限

  • 通过保存信息到另一个变量来添加本地缓存,然后在一定时间间隔后重新检查,例如 30 秒。:
  • 使用 按状态请求数量 图表来验证您正在收到更多 成功 响应 than NoItemFounds 。限制你使用失败请求击中 MemoryStoreService 的次数。:
  • 实现请求之间的短延迟。:
  • 遵循最佳实践
  • ,包括:

    • 如果您收到大量的 数据结构请求超限 / 分区请求超限 响应,就会碎片化您的数据结构。:
    • 实现指数退出来找到合理的请求发送速率。
超过限制的总请求
数据结构项超出限制
数据结构内存超出限制
总内存超过限制
数据更新冲突
  • 实现短时间延迟,避免多个请求同时更新相同的键。:
  • 对于排序的地图,使用 方法上的回调函数,在一定数量的尝试后取消请求,如下代码示例所示:
  • Example of Aborting Request

    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("item is "..item.highestBid)
    return nil
    end, 1000)
    end
    placeBid("MyItem", 50)
    placeBid("MyItem", 40)
    print("done")
  • 调查以确定你是否有效地调用 MemoryStoreService 以避免冲突。理想情况下,你不应该发送过多的请求。:
  • 一旦使用 MemoryStoreQueue:RemoveAsync() 方法阅读队列和排序地图,就会一致删除项目。
内部错误
无效请求
  • 确保您在请求中包含正确且有效的参数。无效参数的例子包括:
    • 一个空字符串
    • 超过长度限制的字符串
物品价值尺寸太大
  • 将物品值拆分或分割为多个键。
    • 为了组织分类的键,通过将键添加 prefix 以字母顺序排序。
  • 编码或压缩存储值。

在工作室测试和调试

MemoryStoreService 中的数据是被隔离在 Studio 和生产之间的,因此更改 Studio 中的数据不会影响生产行为。这意味着从工作室发出的 API 调用不能访问生产数据,可以让您在进入生产之前安全测试内存存储和新功能。

工作室测试与生产具有相同的 限制和配额。对于基于用户数量计算的配额,由于您是唯一的用户进行 Studio 测试,因此最终配额可能很小。当从工作室测试时,您可能还会注意到较高的延迟和较高的错误率,这是因为进行验证访问和权限的一些额外检查所导致的。

要了解有关如何在实时体验或工作室测试时调试内存存储的信息,请使用开发者控制台