您对数据存储的请求可能由于连接不良或其他问题而失败。要处理错误并返回带有错误代码的消息,将数据存储功能包装在 pcall() 中。
例如,写入调用失败,如 UpdateAsync(),意味着游戏服务器未收到成功响应。这并不总能保证后端写入没有发生。在某些失败场景中,最终的写入状态可能在进行后续读取并且没有缓存时被调用者验证之前是未知的。
错误代码参考
| 错误代码 | 错误名称 | 错误消息 | 备注 | |
|---|---|---|---|---|
| 101 | KeyNameEmpty | 键名称不能为空。 | 检查输入到数据存储功能的键是否为空字符串。 | |
| 102 | KeyNameLimit | 键名称超过 50 个字符的限制。 | 检查输入到数据存储功能的键是否超过 50 的长度。 | |
| 103 | ValueNotAllowed | 不能在 DataStore 中允许 X。 | 一个错误的更新函数返回了类型为 X 的值。 | |
| 104 | CantStoreValue | 不能在 DataStore 中存储 X。 | 更新函数返回了类型为 X 的值,该值没有序列化。 | |
| 105 | ValueTooLarge | 序列化值超过 X 的限制。 | 如果您使用 SetAsync() 或 UpdateAsync() 设置值,则值的序列化长度不能超过大小 X。要检查数据的序列化长度,请使用 JSONEncode()。 | |
| 106 | MaxValueInvalid | MaxValue 必须是一个整数。 | 如果您要为 GetSortedAsync() 传递最大值,则必须是一个整数。 | |
| 106 | MinValueInvalid | MinValue 必须是一个整数。 | 如果您要为 GetSortedAsync() 传递最小值,则必须是一个整数。 | |
| 106 | PageSizeGreater | PageSize 必须在预定义范围内。 | OrderedDataStore 的最小页面大小为 1。 | |
| 106 | PageSizeLesser | PageSize 必须在预定义范围内。 | OrderedDataStore 的最大页面大小为 100。 | |
| 107 | MinMaxOrderInvalid | MaxValue 必须大于或等于 MinValue。 | 对于 GetSortedAsync(),最大值必须大于或等于最小值。 | |
| 301 | GetAsyncThrottle | GetAsync 请求被丢弃。请求被限制,但队列已满。 | GetAsync() 请求超过了最大队列大小,Roblox 无法以当前吞吐量处理请求。 | |
| 302 | SetAsyncThrottle | SetAsync 请求被丢弃。请求被限制,但队列已满。 | SetAsync() 请求超过了最大队列大小,Roblox 无法以当前吞吐量处理请求。 | |
| 303 | IncreAsyncThrottle | IncrementAsync 请求被丢弃。请求被限制,但队列已满。 | IncrementAsync() 请求超过了最大队列大小,Roblox 无法以当前吞吐量处理请求。 | |
| 304 | UpdateAsyncThrottle | UpdateAsync 请求被丢弃。请求被限制,但队列已满。 | UpdateAsync() 请求超过了最大队列大小,Roblox 无法以当前吞吐量处理请求。 | |
| 304 | TransformThrottle | UpdateAsync 请求被丢弃。请求被限制,但队列已满。 | UpdateAsync() 请求超过了最大队列大小,Roblox 无法以当前吞吐量处理请求。 | |
| 305 | GetSortedThrottle | GetSorted 请求被丢弃。请求被限制,但队列已满。 | GetSortedAsync() 请求超过了最大队列大小,Roblox 无法以当前吞吐量处理请求。 | |
| 306 | RemoveAsyncThrottle | RemoveAsync 请求被丢弃。请求被限制,但队列已满。 | RemoveAsync() 请求超过了最大队列大小,Roblox 无法以当前吞吐量处理请求。 | |
| 401 | DataModelNoAccess | 请求失败。DataModel 在体验关闭时无法访问。 | DataModel 未初始化,因为体验正在关闭。 | |
| 402 | LuaWebSrvsNoAccess | 请求失败。LuaWebService 在体验关闭时无法访问。 | LuaWebService 未初始化,因为体验正在关闭。 | |
| 403 | StudioAccessToApisNotAllowed | 无法从 Studio 向 DataStore 写入,因为 API 访问未启用。 | API 访问必须处于活动状态,以便在 Studio 中使用数据存储。 | |
| 404 | InternalError | OrderedDataStore 不存在。 | 与此请求相关的 OrderedDataStore 未找到。这可能是数据损坏的迹象。请稍后重试。 | |
| 501 | InternalError | 无法解析响应,因为数据可能已损坏。 | 服务器无法解析对您请求的响应。这可能是数据损坏的迹象。请稍后重试。 | |
| 502 | RequestRejected | API 服务拒绝了这次请求,错误为 X。 | 在处理 Roblox 服务器时发生了错误 X。请稍后重试。 | |
| 503 | InternalError | 数据存储请求成功,但未找到键。 | 请求的键在数据存储中未找到。这可能是数据损坏的迹象。请稍后重试。 | |
| 504 | InternalError | 数据存储请求成功,但响应格式不正确。 | 服务器无法解析对您请求的响应。这可能是数据损坏的迹象。请稍后重试。 | |
| 505 | InternalError | OrderedDataStore 请求成功,但响应格式不正确。 | 服务器无法解析对您的 OrderedDataStore 请求的响应。这可能是数据损坏的迹象。请稍后重试。 | |
| 509 | OperationNotAllowed | 数据存储操作在个人 RCC 上被阻止,以防止可能的数据损坏。 | 在私人 RCC 通道上阻止数据存储写入。 | |
| 511 | AttributeSizeTooLarge | 元数据属性大小超过 X 限制。 | 序列化的元数据大小超过了 X 的限制。值 X 是动态的。如果大小更改,值也会更改。 | |
| 512 | UserIdLimitExceeded | UserID 大小超过 X 限制。 | 用户提供的用户 ID 数组的长度超过了 X 的限制。 | |
| 513 | AttributeFormatError | 属性 userId 格式无效。 | 提供的用户 ID 不是数字。 | |
| 513 | AttributeFormatError | 属性元数据格式无效。 | 元数据不是一个表。 | |
| GetVersionAsyncThrottle | GetVersionAsync 请求被丢弃。请求被限制。 | GetVersionAsync() 请求超过了最大队列大小,Roblox 无法以当前吞吐量处理请求。 | ||
| GetVersionAtTimeAsyncThrottle | GetVersionAtTimeAsync 请求被丢弃。请求被限制。 | GetVersionAtTimeAsync() 请求超过了最大队列大小,Roblox 无法以当前吞吐量处理请求。 | ||
| ListDataStoresAsyncThrottle | ListDataStoresAsync 请求被丢弃。请求被限制。 | ListDataStoresAsync() 请求超过了最大队列大小,Roblox 无法以当前吞吐量处理请求。 | ||
| ListKeysAsyncThrottle | ListKeysAsync 请求被丢弃。请求被限制。 | ListKeysAsync() 请求超过了最大队列大小,Roblox 无法以当前吞吐量处理请求。 | ||
| ListVersionsAsyncThrottle | ListVersionsAsync 请求被丢弃。请求被限制。 | ListVersionsAsync() 请求超过了最大队列大小,Roblox 无法以当前吞吐量处理请求。 | ||
| RemoveVersionAsyncThrottle | RemoveVersionAsync 请求被丢弃。请求被限制。 | RemoveVersionAsync() 请求超过了最大队列大小,Roblox 无法以当前吞吐量处理请求。 | ||
| InvalidTimestamp | 时间戳必须是正数,并且不能超过十分钟。 | 提供给 GetVersionAtTimeAsync() 的时间戳无效。 | ||
| StandardReadExperienceThrottled | StandardRead 请求因体验限制而被限制。 | 对 GetAsync()、GetVersionAsync()、GetVersionAtTimeAsync() 或对标准数据存储的 UpdateAsync() 的读取超出了 StandardRead 体验级别速率限制。 | ||
| StandardWriteExperienceThrottled | StandardWrite 请求因体验限制而被限制。 | 对 SetAsync()、IncrementAsync() 或对标准数据存储的 UpdateAsync() 的写入超出了 StandardWrite 体验级别速率限制。 | ||
| StandardListExperienceThrottled | StandardList 请求因体验限制而被限制。 | 对标准数据存储的 ListKeysAsync()、ListVersionsAsync() 或 ListDataStoresAsync() 的请求超出了 StandardList 体验级别速率限制。 | ||
| StandardRemoveExperienceThrottled | StandardRemove 请求因体验限制而被限制。 | 对标准数据存储的 RemoveAsync() 的请求超出了 StandardRemove 体验级别速率限制。 | ||
| OrderedReadExperienceThrottled | OrderedRead 请求因体验限制而被限制。 | 对 GetAsync() 或对有序数据存储的 UpdateAsync() 的读取超出了 OrderedRead 体验级别速率限制。 | ||
| OrderedWriteExperienceThrottled | OrderedWrite 请求因体验限制而被限制。 | 对 SetAsync()、IncrementAsync() 或对有序数据存储的 UpdateAsync() 的写入超出了 OrderedWrite 体验级别速率限制。 | ||
| OrderedListExperienceThrottled | OrderedList 请求因体验限制而被限制。 | 对有序数据存储的 GetSortedAsync() 的请求超出了 OrderedList 体验级别速率限制。 | ||
| OrderedRemoveExperienceThrottled | OrderedRemove 请求因体验限制而被限制。 | 对有序数据存储的 RemoveAsync() 的请求超出了 OrderedRemove 体验级别速率限制。 | ||
| StandardReadGameServerThrottled | StandardRead 请求因游戏服务器限制或请求队列已满而被限制。 | 对 GetAsync()、GetVersionAsync()、GetVersionAtTimeAsync() 或对标准数据存储的 UpdateAsync() 的读取超出了 StandardRead 游戏服务器级别速率限制。 | ||
| StandardWriteGameServerThrottled | StandardWrite 请求因游戏服务器限制或请求队列已满而被限制。 | 对 SetAsync()、IncrementAsync() 或对标准数据存储的 UpdateAsync() 的写入超出了 StandardWrite 游戏服务器级别速率限制。 | ||
| StandardListGameServerThrottled | StandardList 请求因游戏服务器限制或请求队列已满而被限制。 | 对标准数据存储的 ListKeysAsync()、ListVersionsAsync() 或 ListDataStoresAsync() 的请求超出了 StandardList 游戏服务器级别速率限制。 | ||
| StandardRemoveGameServerThrottled | StandardRemove 请求因游戏服务器限制或请求队列已满而被限制。 | 对标准数据存储的 RemoveAsync() 的请求超出了 StandardRemove 游戏服务器级别速率限制。 | ||
| OrderedReadGameServerThrottled | OrderedRead 请求因游戏服务器限制或请求队列已满而被限制。 | 对 GetAsync() 或对有序数据存储的 UpdateAsync() 的读取超出了 OrderedRead 游戏服务器级别速率限制。 | ||
| OrderedWriteGameServerThrottled | OrderedWrite 请求因游戏服务器限制或请求队列已满而被限制。 | 对 SetAsync()、IncrementAsync() 或对有序数据存储的 UpdateAsync() 的写入超出了 OrderedWrite 游戏服务器级别速率限制。 | ||
| OrderedListGameServerThrottled | OrderedList 请求因游戏服务器限制或请求队列已满而被限制。 | 对有序数据存储的 GetSortedAsync() 的请求超出了 OrderedList 游戏服务器级别速率限制。 | ||
| OrderedRemoveGameServerThrottled | OrderedRemove 请求因游戏服务器限制或请求队列已满而被限制。 | 对有序数据存储的 RemoveAsync() 的请求超出了 OrderedRemove 游戏服务器级别速率限制。 |
服务器错误代码
| 错误名称 | 错误消息 | 备注 |
|---|---|---|
| DatastoreDeleted | 数据存储已被删除。 | 无法对数据存储执行操作,因为数据存储已被先前删除。 |
| DatastoreThrottled | 请求速率超过了 datastore 允许的最大值。 | 对单个数据存储发送了过多请求。 |
| InternalServerError | 发生内部服务器错误。 | Roblox 服务器上偶尔发生错误。请稍后重试,最好采用指数退避。 |
| InvalidExclusiveStartKey | 提供的独占起始键无效。 | 提供给列表操作(如 ListKeysAsync())的独占起始键(光标)无效。 |
| InvalidPlace | 提供的地点无效。 | 地点没有匹配的宇宙 ID。请稍后重试。 |
| InvalidTarget | 提供的目标无效。 | 有序数据存储键名称超过了 50 个字符的限制。 |
| InvalidUniverse | 提供的宇宙无效。 | 宇宙没有匹配的地点 ID。请稍后重试。 |
| InvalidUserIds | 提供的用户 ID 格式无效。 | 解析用户 ID 失败。 |
| KeyThrottled | 请求速率超过了允许的最大值。 | 请求速率超过了单个键允许的最大请求速率。 |
| KeyNotFound | 请求的键不存在。 | 该键不存在。 |
| N/A | 没有页面可以继续。 | 当您在最后一页上调用 Pages:AdvanceToNextPageAsync() 时,会发生此错误。 |
| StandardReadExperienceThrottled | 标准读取请求速率超过了体验允许的最大值。 | 对 GetAsync()、GetVersionAsync()、GetVersionAtTimeAsync() 或对标准数据存储的 UpdateAsync() 的读取超出了 StandardRead 体验级别速率限制。 |
| StandardWriteExperienceThrottled | 标准写入请求速率超过了体验允许的最大值。 | 对 SetAsync()、IncrementAsync() 或对标准数据存储的 UpdateAsync() 的写入超出了 StandardWrite 体验级别速率限制。 |
| StandardListExperienceThrottled | 标准列表请求速率超过了体验允许的最大值。 | 对标准数据存储的 ListKeysAsync()、ListVersionsAsync() 或 ListDataStoresAsync() 的请求超出了 StandardList 体验级别速率限制。 |
| StandardRemoveExperienceThrottled | 标准删除请求速率超过了体验允许的最大值。 | 对标准数据存储的 RemoveAsync() 的请求超出了 StandardRemove 体验级别速率限制。 |
| OrderedReadExperienceThrottled | 有序读取请求速率超过了体验允许的最大值。 | 对 GetAsync() 或对有序数据存储的 UpdateAsync() 的读取超出了 OrderedRead 体验级别速率限制。 |
| OrderedWriteExperienceThrottled | 有序写入请求速率超过了体验允许的最大值。 | 对 SetAsync()、IncrementAsync() 或对有序数据存储的 UpdateAsync() 的写入超出了 OrderedWrite 体验级别速率限制。 |
| OrderedListExperienceThrottled | 有序列表请求速率超过了体验允许的最大值。 | 对有序数据存储的 GetSortedAsync() 的请求超出了 OrderedList 体验级别速率限制。 |
| OrderedRemoveExperienceThrottled | 有序删除请求速率超过了体验允许的最大值。 | 对有序数据存储的 RemoveAsync() 的请求超出了 OrderedRemove 体验级别速率限制。 |
限制
数据模型有 限制。如果体验超过这些限制,服务会自动限制体验的数据存储使用,并导致未来的请求被放置在以下某个队列中:
- 设置
- 有序设置
- 获取
- 有序获取
队列中的请求按接收顺序进行处理。调用的函数会继续等待,只要它的请求仍在队列中。如果数据存储键本身被限制,请求将被放入队列中,但会暂时跳过。
每个队列限制为 30 个请求。当队列达到限制时,请求将以 301-306 范围内的错误代码失败,表示请求已完全丢弃。
访问限制
数据存储受 体验和服务器级别限制 的限制。体验级别限制与体验中的总并发用户数成比例,而服务器级别限制是可配置的,旨在作为创建者的工具使用。
体验限制
每个体验允许根据数据存储类型、请求类型和并发用户数进行一定数量的数据存储请求。对于每种数据存储类型和请求类型,限制在所有列出功能之间共享。
注意,UpdateAsync() 将消耗读取和写入请求预算。一次调用将减少两个限制。
标准数据存储
| 请求类型 | 函数 | 每分钟请求数量 |
|---|---|---|
| 读取 | GetAsync() GetVersionAsync() GetVersionAtTimeAsync() UpdateAsync() | 250 + concurrentUsers × 40 |
| 写入 | SetAsync() IncrementAsync() UpdateAsync() | 250 + concurrentUsers × 20 |
| 列表 | ListDataStoresAsync() ListKeysAsync() ListVersionsAsync() | 10 + concurrentUsers × 2 |
| 删除 | RemoveAsync() | 100 + concurrentUsers × 40 |
有序数据存储
| 请求类型 | 函数 | 每分钟请求数量 |
|---|---|---|
| 读取 | GetAsync() UpdateAsync() | 250 + concurrentUsers × 40 |
| 写入 | SetAsync() IncrementAsync() UpdateAsync() | 250 + concurrentUsers × 20 |
| 列表 | GetSortedAsync() | 100 + concurrentUsers × 2 |
| 删除 | RemoveAsync() | 100 + concurrentUsers × 40 |
服务器限制
每个服务器都有各请求类型的可配置速率限制,基于该服务器中的玩家数量。服务器在第一次创建时会获得一次性启动增加的请求预算。使用 GetRequestBudgetForRequestType() 确认当前服务器在任何给定时间可以进行的数据显示存储请求数量。
这些限制是 可由创建者配置 的,使用 SetRateLimitForRequestType() API。通过此 API,创建者可以为每个请求类型配置自己的数据存储速率限制。
如果未调用 API,则会应用以下 默认速率限制:
标准数据存储
| 请求类型 | DataStoreRequestType 枚举 | 函数 | 每分钟请求数量 |
|---|---|---|---|
| 读取 | StandardRead | GetAsync() GetVersionAsync() GetVersionAtTimeAsync() UpdateAsync() | 60 + numPlayers × 40 |
| 写入 | StandardWrite | SetAsync() IncrementAsync() UpdateAsync() | 60 + numPlayers × 40 |
| 列表 | StandardList | ListDataStoresAsync() ListKeysAsync() ListVersionsAsync() | 5 + numPlayers × 2 |
| 删除 | StandardRemove | RemoveAsync() | 60 + numPlayers × 40 |
| RemoveVersion (已废弃) | RemoveVersionAsync | RemoveVersionAsync() | 5 + numPlayers × 2 |
有序数据存储
| 请求类型 | DataStoreRequestType 枚举 | 函数 | 每分钟请求数量 |
|---|---|---|---|
| 读取 | OrderedRead | GetAsync() UpdateAsync() | 60 + numPlayers × 40 |
| 写入 | OrderedWrite | SetAsync() IncrementAsync() UpdateAsync() | 30 + numPlayers × 5 |
| 列表 | OrderedList | GetSortedAsync() | 5 + numPlayers × 2 |
| 删除 | OrderedRemove | RemoveAsync() | 30 + numPlayers × 5 |
数据限制
数据存储限制了每个条目可以使用的数据量。
数据存储名称、键名称和 范围 必须都在一定字符长度以内。使用 string.len() 检查它们的长度。
数据(键值)也作为字符串存储,无论其初始类型如何。您可以使用 JSONEncode() 函数检查数据的大小,该函数将 Luau 数据转换为序列化 JSON 表。
| 组件 | 最大字符数 |
|---|---|
| 数据存储名称 | 50 |
| 键名称 | 50 |
| 范围 | 50 |
| 数据(键值) | 每个键 4,194,304 |
元数据限制
用户定义的元数据字符数限制。
| 组件 | 最大字符数 |
|---|---|
| 键名称 | 50 |
| 值 | 250 |
| 键值对 | 300 |
吞吐量限制
每个键的吞吐量限制确保 Roblox 服务器上的性能最佳。每个限制适用于体验中所有服务器上的每个单独键,并随着时间的推移而刷新。
Roblox 检查与该键相关的配额使用情况,时间范围为最近的 60 秒。如果包括当前请求在内的使用量在吞吐量限制范围内,请求将被批准。如果使用量超过了限制,请求将被拒绝。
| 请求类型 | 限制 |
|---|---|
| 读取 | 每分钟 25 MB |
| 写入 | 每分钟 4 MB |
除了上述吞吐量限制外,Roblox 根据内部架构将数据组织成多个分区。因此,当后端服务器接收到对同一数据存储大量请求时,可能会导致进一步的限制。无论原因如何,限制都会表现为 DatastoreThrottled 或 KeyThrottled 错误,具体取决于单个数据存储或键是否超出了吞吐量限制。这些错误消息适用于标准和有序数据存储。
存储限制
为了提供可扩展和稳定的存储体验,未来数据存储将实施您存储使用量的体验级别存储限制。
此限制将是您每个体验的基本限制与基于您体验中的生命周期用户数量的每用户限制的总和。生命周期用户是指任何至少加入过您体验一次的用户。
存储限制将使用公式 最新版本存储限制总计 = 100 MB + 1 MB * 生命周期用户数量 计算。
您删除或替换的任何键,即使通过版本 API 仍可访问,也不计入体验的存储使用量。但是,通过 Open Cloud DeleteDataStore 方法完全删除的整个数据存储,在其 30 天处理期间继续记入您的存储使用量,直到它们被永久删除。