关于 roblox-datastores
roblox-datastores 是面向 Roblox 体验开发者的数据持久化技能,介绍存储类型选择、安全写入、恢复和运维限制,涵盖 Roblox DataStore API。
主要功能
- 01选择 DataStore 类型
- 02安全的 UpdateAsync 写入模式
- 03玩家档案保存流程
- 04版本历史与恢复
- 05缓存、配额与监控
适用场景
- 01为玩家档案选择存储方式
- 02构建排行榜查询
- 03写入错误后的数据恢复
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ nonlooped/ roblox-suite --skill roblox-datastores安装后在 Claude Code 中输入/roblox-datastores确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/best-practices-and-gotchas.mdcore-operations-and-patterns.mdlimits-quotas-throttling-error-codes.mdtypes-of-datastores.mdversioning-metadata-recovery.mdscripts/BudgetMonitor.luaSafeDataStore.luatests/SafeDataStore.spec.lua详细介绍
roblox-datastores
将持久化操作保留在服务端。对于并发写入,请使用纯 UpdateAsync 转换函数;写入出错后,先协调后端状态,再重试或进行补偿。
官方来源:
- https://create.roblox.com/docs/cloud-services/data-stores
- https://create.roblox.com/docs/cloud-services/data-stores-vs-memory-stores
- https://create.roblox.com/docs/cloud-services/data-stores/versioning-listing-and-caching
- https://create.roblox.com/docs/cloud-services/data-stores/error-codes-and-limits
- https://create.roblox.com/docs/cloud-services/data-stores/best-practices
- https://create.roblox.com/docs/cloud-services/data-stores/data-stores-manager
- https://create.roblox.com/docs/cloud-services/data-stores/observability
- 引擎类:DataStoreService、GlobalDataStore、DataStore、OrderedDataStore、DataStoreOptions、DataStoreKeyInfo、DataStoreSetOptions 等(完整参考:https://create.roblox.com/docs/reference/engine)
对于临时队列、大厅和缓存,请使用 MemoryStoreService。选择存储时,请阅读 types-of-datastores.md。
交叉参考:
- roblox-networking/SKILL.md:了解任何写入前如何进行服务端权威验证。
- roblox-core/SKILL.md:了解服务获取模式、pcall 使用规范和 Luau 序列化规则。
- roblox-gamepasses/SKILL.md:当购买会影响持久化状态时请参考(加载时重新验证所有权)。
- roblox/SKILL.md:了解整体索引页和引擎 API 链接。
选择存储
-
数据是否临时/短暂、高频变更,或仅在服务器运行期间需要(队列、大厅、速率计数器、短期缓存)?
→ 使用 MemoryStoreService(队列、有序映射等)。DataStore 大材小用,且成本更高、速度更慢。请参阅参考资料和官方对比。 -
是否需要对排行榜或排名进行数值排序查询?
→ 使用 OrderedDataStore(通过 GetOrderedDataStore)。值必须为整数。没有版本控制/元数据。需要特殊处理 GetSortedAsync 和 DataStorePages 迭代。限制有所不同(请参阅参考资料/限制等)。 -
是否需要用于恢复/审计的版本控制、用户自定义元数据、键列表,或更丰富的 DataStore API(
ListKeysAsync、ListVersionsAsync、GetVersionAsync、GetVersionAtTimeAsync)? → 使用通过GetDataStore和DataStoreOptions创建的完整 DataStore(此方法会返回现代 DataStore 类)。这是重要玩家数据的首选。 -
只需要简单的键值持久化存储,不需要上述功能?
→ 使用DataStoreService:GetDataStore()(返回标准 DataStore)或DataStoreService:GetGlobalDataStore()(旧版全局存储,作用域为"u")。新项目优先使用命名的GetDataStore存储。
作用域与前缀(现代建议): 新项目优先使用键前缀(例如 "profiles/User_1234")并通过 ListKeysAsync 进行筛选,而非旧版作用域。作用域会自动添加到键前缀。要跨作用域列出键,请使用 DataStoreOptions.AllScopes=true 和空作用域字符串(请参阅参考资料)。
Studio 访问: 如果 Studio 需要调用后端 API,请使用专用测试体验。不要允许 Studio 会话读取或写入生产数据。
推荐的安全工作流
玩家数据档案模式(最常见)
完整示例和变体(包括会话锁定和档案模式)请参阅 references/best-practices-and-gotchas.md。
服务器高层流程(位于由 ServerScriptService 脚本 require 的 ModuleScript 中):
-
PlayerAdded 时:
- 使用 pcall + GetAsync 加载(如果之前可能发生过服务器问题,请考虑使用 UseCache=false,以确保读取到最新数据)。
- 与默认值合并。
- 将数据存储在服务器端表或档案对象中(例如
playerData[player.UserId] = data)。 - 应用任何 gamepass 权益(交叉参阅变现技能)或其他状态。
- 可选:向客户端触发 Remote,以同步初始 UI(绝不要信任客户端数据)。
-
游戏过程中:
- 修改内存中的档案。
- 定期自动保存(每 30-60s),使用 UpdateAsync 或 SetAsync,并提供适当的转换函数。
- 在重要事件发生时(购买、升级、交易),立即使用 UpdateAsync 保存以确保安全。
-
PlayerRemoving / BindToClose / 角色死亡时:
- 使用 pcall 执行最终保存。
- 清理内存中的数据。
- 对于 BindToClose,最多等待约 30 秒以完成最终保存(Roblox 提供的宽限期有上限)。
-
写入出错时:
- 使用验证模式:写入失败后,立即使用 UseCache=false 执行 GetAsync,检查后端的实际状态,再决定重试、退款或回滚。
对于可能由多个服务器并发修改的任何值,都应使用 UpdateAsync 和纯(不产生 yield)转换函数。从最后写入者的角度看,它会以原子方式先读取再写入。
序列化规则(至关重要): 仅支持 nil、布尔值、数字(不含 inf/-inf/nan)、字符串(有效 UTF-8)、buffer,以及由上述类型组成的表。不能包含函数、已保存表上的元表或循环引用。开发期间可对可疑数据使用 HttpService:JSONEncode,预览实际存储的内容。请参阅 references/core-operations... 。
使用 OrderedDataStore 的排行榜
在相关值发生变化时或保存时填充(使用 SetAsync 或 Increment)。
使用 GetSortedAsync(ascending, pageSize, min?, max?) 查询 → DataStorePages。使用 GetCurrentPage() + AdvanceToNextPageAsync() 遍历页面。
对于批量读取,使用 BatchGetAsync(keys) 在一个请求中获取多个有序条目。每个键计为一次 OrderedRead(配额请参阅 error-codes-and-limits;缺失的键会被省略)。
请记住:只支持数字;键为字符串;页面遍历有自身的限制;不支持版本控制。
可在 ScrollingFrame 中显示,或按需通过 UI 显示。如果希望快速进行全局访问,且不必重复查询,可在标准 DataStore 中缓存前 N 条。
完整的页面遍历示例和限制差异请参阅参考资料。
版本控制和恢复
对标准 DataStore(非 Ordered)执行的每次 Set/Update/Increment 都会创建按小时划分版本的备份:某个 UTC 小时内对某个键的首次写入会创建新的版本快照,该小时内的后续写入会覆盖这个小时的版本。版本备份在被替代约 30 天后过期;当前版本永不过期。
- ListVersionsAsync(key, sort, minDate?, maxDate?, pageSize?)
- GetVersionAsync(key, version)
RemoveVersionAsync已弃用。不要将其作为当前的清理 API;应保留版本以供恢复,并使用ListVersionsAsync、GetVersionAsync或GetVersionAtTimeAsync检查版本。- GetVersionAtTimeAsync(key, timestampMillis):查找特定过去时间点的当前版本。
- 若要回滚:读取所需版本,然后使用 SetAsync 将值和元数据写回(这会创建一个新的当前版本)。
在进行有风险的发布之前,也应使用每日 Snapshot Data Stores Open Cloud API。
Creator Hub 中的 Data Stores Manager 可用于浏览键、查看元数据/版本历史、比较版本并回滚(需具备适当权限)。
完整代码示例(包括“回滚到事故发生时刻”模式)请参阅 references/versioning-metadata-recovery.md。
缓存控制
默认情况下:GetAsync 的结果会在本地缓存 4 秒。在此时间窗口内后续的 Get 会返回缓存结果,且不会计入限制。写入会立即更新缓存。
如需在写入后验证(尤其是在发生错误后),或怀疑其他服务导致数据过时:
local opts = Instance.new("DataStoreGetOptions")
opts.UseCache = false
local value, info = store:GetAsync(key, opts)
这始终会访问后端,并计入配额。请谨慎但正确地使用。
参见 references/versioning-metadata-recovery.md(有关列举、缓存和序列化)以及 references/best-practices-and-gotchas.md。
限制、配额、限流和预算
限制分为体验级(随整个体验中的并发用户数变化)和每服务器级(可通过 DataStoreService:SetRateLimitForRequestType 配置)。体验级配额池由游戏服务器和 Open Cloud v2 的 Data Store 流量共享。大批量外部任务可能会限制在线玩家的请求(反之亦然)。
UpdateAsync 同时计入读取和写入预算。
进行繁重操作前,使用 DataStoreService:GetRequestBudgetForRequestType(Enum.DataStoreRequestType.XXX) 检查预算,并在必要时循环等待。
队列大小为 30;队列满时会产生限流错误(301-306 范围内的错误,或较新的 *Throttled 错误)。
所有错误代码的完整表格(从 101 KeyNameEmpty 到所有 *ExperienceThrottled 和 *GameServerThrottled 变体)、体验级公式(基础值 300 + 并发用户数 × N)以及服务器端错误,见 references/limits-quotas-throttling-error-codes.md。
可观测性仪表板(Creator Hub → Monitoring → Data Stores)会实时显示按 API/状态划分的请求数、配额使用百分比,以及存储字节数与上限的对比。
Data Stores Manager 会显示总大小与存储上限的对比(500 MB + 1 MB × lifetime users,按压缩后的最新版本大小计算)、每个 DS 的键数等。写入前请勿预先压缩值。
在服务器初始化早期调用 SetRateLimitForRequestType(每种类型调用一次),以提高迁移脚本或繁忙服务器的限制。计算公式为基础值 +(每玩家数值 × 玩家数)。各类型的限制条件见文档。
处理结果不确定的写入
每次数据存储调用都必须放在 pcall 中。
失败时:
- 记录具体的错误代码/消息。
- 使用有界指数退避和抖动重试读取。
- 将返回错误的已调用写入视为未知,而非已拒绝:使用
UseCache = false执行新的GetAsync以核对结果。 - 仅当调用方已证明整个操作具有幂等性时,才重放写入。切勿自动重放
IncrementAsync。 - 返回明确的
committed、rejected或unknown状态,以免购买/恢复代码将模糊结果误认为失败。
切勿假设失败的 Set/Update/Increment 意味着“未发生任何更改”。UpdateAsync 转换函数可能运行多次,不得让其产生挂起,也不得产生外部副作用。
RemoveAsync 会创建一个“墓碑”(Get 返回 nil),但旧版本仍可查询 30 天(除非明确移除)。
管理和监控
- 使用 Data Stores Manager(Creator Hub)进行检查、按前缀搜索键、比较/还原版本以及安排删除(带有冷却期)。Manager 的 Revert 按钮可将单个键还原到以前的版本。Restore 按钮用于恢复标记为待删除的数据存储,并非用于还原键值。在冷却期内恢复已删除的键,需要通过 Engine API 调用
UpdateAsync,或通过 Open Cloud 调用UpdateDataStoreEntry。 - 使用可观测性仪表板查看趋势并预测配额。
- 批量删除/迁移:使用 Open Cloud Data Stores API 或官方 Batch Processor CLI/工具。
- 设置存储上限即将达到或已超出时的通知。
- 定期检查用量。
参见 references/versioning-metadata-recovery.md(涵盖列举/缓存),以及管理器/可观测性页面(链接见 best-practices-and-gotchas.md)。
检查清单
每次执行关键写入前:
- 使用 pcall 包装,并明确处理已提交、已拒绝和未知状态
- 在可能发生竞争时使用 UpdateAsync,并使用纯转换函数
- 适当时提供 userIds 数组,以便进行 RTBF/GDPR 跟踪
- 使用完整 DataStore 时,每次写入都提供元数据(即使元数据未变)
- 确保值可序列化(开发期间使用 JSONEncode 测试)
- 统一键名规则并使用前缀,以便轻松列出
玩家加入/加载时:
- 根据实际情况,进行全新加载或考虑缓存
- 安全地合并默认值
- 在 PlayerAdded 时重新验证所有权(gamepasses 等),并重新发放尚未拥有的一次性消耗品奖励
- 仅向客户端同步非敏感的派生状态
发布有风险的数据逻辑变更前:
- 如果可用,通过 Open Cloud 创建每日快照
- 在体验副本中进行充分测试
持续进行:
- 监控 dashboard 和 manager
- 清理测试数据/临时数据
- 对无需在服务器停止后保留的数据使用 MemoryStores
- 优先采用更少的数据存储、规模更大的整体对象和键前缀
常见错误
- 从客户端/LocalScript 调用(会立即报错并造成安全漏洞)。
- 存储函数、元表或不可序列化的数据。
- 对有竞争的值使用 SetAsync(竞态条件会导致更新丢失或重复)。
- 忽略节流错误并持续发起请求(会导致请求被丢弃,让玩家感到沮丧)。
- 在正式运行的场所中硬编码 studio API 访问权限。
- 创建数百个细小的数据存储,而不是通过键/前缀进行组织。
- 依赖缓存的 Gets 来验证写入后的结果。
- 忘记 OrderedDataStore 没有版本控制且只支持整数。
- 未处理 RemoveAsync 已被调用的情况(nil + tombstone)。
- 超出存储配额却不进行监控(会导致意外费用,也可能造成写入失败)。
scripts 文件夹用法
scripts/ 目录包含标注成熟度等级的示例:
SafeDataStore.lua:经过审查的示例,包含自动读取重试、明确的写入状态、可选的幂等重放,以及不使用缓存的协调。BudgetMonitor.lua:用于检查预算的实验性示例。
请在专用的测试体验中调整并验证这些示例;此目录并非有版本控制的生产级库。
实际操作步骤
- 阅读相关的 references/ 文件,了解你要实现的功能。
- 使用此处和 references 中的模式与代码示例进行实现。
- 在负载下测试预算行为(使用多个测试服务器,或使用速率限制设置器进行模拟)。
- 尽早添加可观测性和告警。
- 使用 Manager/Dashboard 分析存储增长情况。
在信任持久化系统之前,请将本指南与静态分析、针对性测试、Studio 集成、可观测性和当前官方资料结合使用。
对于任何特定方法的权威类/属性参考,请务必交叉查阅 https://create.roblox.com/docs/reference/engine(搜索 DataStoreService、GlobalDataStore 等)。
参考索引
- best-practices-and-gotchas.md:设计玩家档案、会话锁定、保存或删除工作流。
- core-operations-and-patterns.md:实现读取、写入、转换或错误恢复。
- limits-quotas-throttling-error-codes.md:诊断节流、检查预算,或规划请求和存储用量。
- types-of-datastores.md:选择标准、有序或临时存储,并组织键。
- versioning-metadata-recovery.md:检查版本、保留元数据,或在事件发生后恢复数据。