mcpField
R
roblox-data

roblox-data

github.com/flatbedj数据与数据库047 次安装6 周前更新
代码仓库

关于 roblox-data

面向 Roblox 数据持久化、跨服务器临时状态和配额协调的技能,帮助设计 DataStoreService、MemoryStoreService 与 MessagingService 的使用方式。它强调数据类型选择、并发写入、缓存、配额和重试处理。

主要功能

  1. 01持久化数据结构与版本迁移
  2. 02DataStore 与 OrderedDataStore 选择
  3. 03MemoryStore 队列、映射与排序映射
  4. 04跨服务器消息协调
  5. 05并发、缓存、配额与重试策略

适用场景

  1. 01设计玩家存档与数据迁移
  2. 02构建匹配队列或临时跨服状态
  3. 03协调多个服务器的通知与状态更新
  4. 04排查数据服务节流和写入冲突

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/flatbedj/roblox-skills --skill roblox-data

安装后在 Claude Code 中输入/roblox-data确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
cross-server-messaging.md
data-store-best-practices.md
data-stores-guides.md
data-stores-vs-memory-stores-comparison.md
memory-store-best-practices-limits-and-observability.md
memory-stores-guides.md
versioning-listing-caching-limits-and-observability.md

详细介绍

roblox-data

适用场景

当任务主要涉及 Roblox 数据持久性、跨服务器共享状态或配额感知型协调时,请使用此技能:

  • 设计持久化玩家存档、类似全局配置的记录,或其他 DataStoreService 用法。
  • 在标准数据存储和有序数据存储之间进行选择。
  • 设计存档负载、架构版本、迁移和元数据。
  • 决定何时使用 SetAsync()、UpdateAsync()、IncrementAsync() 或版本 API。
  • 使用 MemoryStoreService 设计临时跨服务器系统。
  • 在内存存储队列、有序映射和哈希映射之间进行选择。
  • 使用 MessagingService 协调多个服务器。
  • 处理限流、请求预算、重试、退避、竞争和可观测性。
  • 分析过时读取、缓存行为、幂等性和多服务器正确性。

当任务主要涉及以下内容时,请勿使用此技能:

  • 远程事件安全、客户端到服务器的验证或一般游戏网络通信。
  • OAuth 流程、API 密钥设置或一般 Open Cloud 身份验证。
  • 数据服务以外的广泛引擎 API 查询。

决策规则

  • 对于可表示为数字、字符串、布尔值、表或缓冲区的持久化跨会话数据,请使用标准数据存储。
  • 仅当存储的值为数字,且主要需求是持久化排名或排序检索时,才使用有序数据存储。
  • 与其将相关字段分散到多个持久化键中,不如优先将一个相关对象存储在一个持久化键中。
  • 当多个服务器可能写入同一个键,或新值取决于当前值时,优先使用 UpdateAsync()。
  • 对于频繁、临时、用于协调且可以过期的共享数据,请使用内存存储。
  • 对于按键查找以及需要在大量键之间扇出查询的场景,请使用内存存储哈希映射。
  • 当顺序很重要,或需要按排序键进行范围读取时,请使用内存存储有序映射。
  • 对于有序工作处理、匹配队列或领取并移除工作流,请使用内存存储队列。
  • 对于短暂的广播信号、扇出通知或唤醒协调,请使用 MessagingService,而不要将其用作持久化事实来源。
  • 如果任务主要涉及远程调用、向客户端复制数据或信任边界,请转交给 roblox-networking。
  • 如果任务主要涉及通用运行时结构或脚本放置,请转交给 roblox-core。
  • 如果任务主要涉及成员查找、签名或类发现,请转交给 roblox-api。
  • 如果请求包含超出范围的内容,只回答其中与数据服务相关的部分,并排除其余内容。

说明

  1. 选择服务前,先判断状态类型:
    • 跨会话持久存在。
    • 临时存在,但跨服务器共享。
    • 仅用于广播协调。
    • 数值排名,还是任意结构化数据。
  2. 选择满足需求的最精简原语:
    • 持久对象使用标准数据存储。
    • 持久数值排名使用有序数据存储。
    • 键控的临时状态使用哈希映射。
    • 有序的临时状态使用有序映射。
    • 需要认领并处理工作项时使用队列。
    • 可从其他状态重新生成的通知使用消息传递。
  3. 对持久化存档,定义稳定的架构:
    • 尽可能让每个键对应一个自包含对象。
    • 在值中包含架构版本字段。
    • 仅在加载时,或加载后的首次写入时执行迁移。
    • 让键、作用域和存储名称简短且可预测。
  4. 设计并发写入:
    • 对有竞争的键,优先使用 UpdateAsync()。
    • 确保回调具有确定性,且不会让出执行权。
    • 对无效更新返回 nil,以中止更新。
    • 如果不打算清除现有元数据和用户 ID,就要保留它们。
  5. 设计读取时,考虑缓存行为:
    • 将 GetAsync() 视为会在本地短暂缓存的操作。
    • 只有在新鲜度足够重要、值得额外消耗预算时,才使用无缓存读取。
    • 除非设计考虑了数据过时的情况,否则避免在写入后立即从另一台服务器读取。
  6. 将配额纳入设计:
    • 在突发性持久写入前检查请求预算。
    • 如果能提升原子性并节省预算,就将相关的持久数据批量合并到一个对象中。
    • 在满足用例的前提下,尽量缩短内存存储的 TTL。
    • 处理完后立即移除队列和有序映射中的项目。
  7. 为重试和故障进行设计:
    • 使用 pcall() 包装网络调用。
    • 使用指数退避重试瞬时故障。
    • 当许多服务器可能同时重试时,加入抖动或错开重试时间。
    • 尽可能让可重试操作具有幂等性。
  8. 利用可观测性形成闭环:
    • 监控数据存储的请求数量、限流情况和配额使用情况。
    • 监控内存存储的内存使用量、请求单元使用量和限流状态。
    • 使用仪表板确认瓶颈来自全局配额、单键竞争还是热点分区。
  9. 将消息传递用作协调层,而非存储:
    • 发布精简事件。
    • 根据需要重新读取或更新数据存储或内存存储中的权威状态。
    • 假设消息可能延迟或重复,并确保处理程序能够安全处理。
  10. 确保指导内容不超出范围:
  • 聚焦于持久化、临时共享状态、配额和并发。
  • 不要偏离到远程安全、游戏玩法网络通信或身份验证流程。

使用参考资料

  • 打开 references/data-stores-guides.md,了解标准数据存储与有序数据存储、核心 CRUD 模式、元数据、序列化和存档结构决策。
  • 打开 references/data-store-best-practices.md,了解持久化架构布局、键组织、存储规范和清理策略。
  • 打开 references/versioning-listing-caching-limits-and-observability.md,了解版本历史、前缀列举、缓存行为、限制、请求预算、限流和仪表板。
  • 打开 references/memory-stores-guides.md,了解如何在队列、有序映射和哈希映射之间进行选择,以及各自的核心 API 模式。
  • 打开 references/memory-store-best-practices-limits-and-observability.md,了解 TTL 策略、分片、分区压力、请求单元预算、竞争处理和仪表板。
  • 打开 references/cross-server-messaging.md,了解主题设计、发布-订阅流程,以及将消息传递与持久或临时状态配合使用的协调模式。
  • 如果首先需要决定由哪一类服务负责存储数据,请打开 references/data-stores-vs-memory-stores-comparison.md。

检查清单

  • 将状态划分为持久状态、跨服务器临时状态或仅广播状态。
  • 所选服务符合持久性和排序要求。
  • 持久化键使用稳定的架构,并包含明确的版本字段。
  • 可能发生竞争时,持久化写入使用 UpdateAsync()。
  • 有序数据存储仅用于数值排名数据。
  • 已考虑缓存行为和读取过期数据的风险。
  • 设计中已考虑请求预算、配额和限流行为。
  • 内存存储的 TTL 有意设置得较短,并明确了清理路径。
  • 处理后移除队列项;排序映射或哈希映射中的过期项也会被清理。
  • 使用消息进行协调,而不是将其作为事实来源。
  • 重试逻辑使用 pcall() 和退避机制,而不是紧密循环。
  • 不包含远程安全、OAuth 或通用 API 查询相关内容。

常见错误

  • 在多个服务器可能并发写入的热点键上使用 SetAsync()。
  • 没有充分理由,却将一个持久化玩家档案拆分到多个互不相关的键中。
  • 使用有序数据存储来保存结构化数据块或元数据繁多的记录。
  • 忘记 GetAsync() 可能在几秒内返回缓存值。
  • 将内存存储当作持久化存储。
  • 需要随机键访问或扫描时,却使用队列,而哈希映射更适合这些场景。
  • 将所有哈希映射流量集中到一个热点键,导致触发分区限流。
  • 为临时内存存储项设置过长的 TTL,导致过期数据占满配额。
  • 将 MessagingService 作为可恢复状态的唯一事实来源。
  • 遇到限流或冲突时立即重试,引发协同重试风暴。

示例

选择合适的服务
  • 保存玩家档案:使用标准数据存储,每个玩家键对应一个对象。
  • 全时期金币排行榜:使用以玩家标识符为键、以数值为值的有序数据存储。
  • 匹配池:使用内存存储队列。
  • 带排名的跨服务器拍卖板:使用内存存储排序映射。
  • 以服务器 ID 为键的共享临时房间注册表:使用内存存储哈希映射。
  • 在各服务器间强制执行缓存刷新工作流:发送消息,并重新读取数据存储或内存存储。
对存在竞争的持久化保存使用 UpdateAsync()
local DataStoreService = game:GetService("DataStoreService")
local profileStore = DataStoreService:GetDataStore("PlayerProfiles")

local function saveCoins(userId, delta)
    return profileStore:UpdateAsync(("player/%d"):format(userId), function(current, keyInfo)
        current = current or {schemaVersion = 1, coins = 0}
        current.coins += delta
        return current, keyInfo:GetUserIds(), keyInfo:GetMetadata()
    end)
end
使用消息唤醒工作进程,而不是保存状态
-- Publish: "queue has work"
-- Receiver: read the queue or map, then process authoritative state there.

评论

支持 Markdown