《游戏服务端架构·核心系统与契约》附录 B 系统契约模板

一份可直接用于评审的系统契约模板:数据所有权、读写权限、幂等键、一致性窗口、失败语义、SLA、保留期与降级责任,并给出账号、结算、支付、平台四个填写示例和常见错误清单,帮助团队把口头约定变成可检查的条目,并说明契约卡与故障清单如何配合使用。

为什么需要一份模板

卷二反复出现同一类争论:这个字段谁能写、重复回调怎么办、下游挂了谁负责、数据保留多久。争论本身不可怕,可怕的是每次都要从头吵一遍,最后靠会议纪要里的模糊句子收场。

契约模板的作用,是把这些争论变成固定栏目。填不满的栏目,就是尚未想清楚的地方;填出来互相矛盾的栏目,就是评审要先解决的问题。

模板不追求覆盖所有系统。它只要求每个核心系统在接入其他系统之前,至少能回答下面这些问题。

一、契约卡的最小字段

字段要回答的问题不合格表现
系统名与负责人谁拥有这个系统,出问题找谁只写团队名,没有值班负责人
拥有的数据哪些数据由本系统唯一写入“用户数据”这种模糊集合
写入者除本系统外,谁还能写;为什么多个服务都可写同一张表
读取者谁依赖这些数据,以什么方式读取方直接连库
幂等键写操作的唯一标识由谁生成“重复请求忽略”但没说怎么识别
一致性强一致还是最终一致,窗口多大所有字段都写“强一致”
失败语义超时、重复、部分成功分别返回什么只定义成功返回
SLA可用性、延迟、恢复时间只有“高可用”三个字
保留期与删除数据留多久,删除请求如何传导不写删除责任
降级依赖不可用时本系统怎么退化假设下游永远可用

一张契约卡通常一页到两页。超过两页,说明边界没有切干净。

二、填写顺序

建议按下面的顺序填,因为后面的栏目依赖前面的结论。

第一步:先定数据所有权

列出本系统拥有的实体和关键字段,逐项确认“唯一写入者”。如果一个字段需要两个系统写,先决定谁拥有,另一个改为通过接口或事件请求。

判据:能否用一个唯一约束或写入接口把“第二个写入者”挡住。挡不住,所有权就只是文档上的声明。

第二步:再定读写路径

  • 外部系统只能通过接口或事件读取,不允许直连数据库;
  • 读取方需要的是原始数据还是聚合结果,决定提供查询接口还是订阅事件;
  • 跨系统查询要明确一致性窗口,不要假设“刚写完就能读到”。

第三步:定义写操作的幂等语义

每个写操作回答三个问题:

  1. 幂等键是什么,由调用方还是服务方生成;
  2. 重复请求返回什么:原结果、冲突错误还是静默成功;
  3. 幂等记录保留多久,过期后重复请求会怎样。

第四步:写失败语义

至少覆盖五类失败:

失败返回调用方应该做什么
参数错误明确错误码修正后重试
未授权/越权拒绝,不泄露内部信息不要重试
资源冲突冲突码 + 当前状态读取后决定
暂时不可用可重试错误 + 建议退避退避重试
结果未知(超时)查询接口或幂等键用同一幂等键重试

“结果未知”最容易被忽略。调用方超时后既不能当成功,也不能当失败,必须有一个查询或幂等机制让它确认。

第五步:定 SLA 与降级

SLA 要分接口、分场景,不要给整个系统一个笼统数字。降级要写清楚:

  • 依赖不可用时,本系统返回缓存、默认值还是错误;
  • 降级期间哪些写操作被拒绝,恢复后如何补偿;
  • 谁有权触发降级,多久复审一次。

三、四个填写示例

3.1 账号服务

字段内容
拥有的数据账号主体、外部身份映射、设备绑定、注销状态
唯一写入者账号服务;游戏服只能读,不能改账号状态
幂等键绑定请求使用 provider + external_id + tenant
一致性账号创建强一致;跨游戏资料最终一致,窗口秒级
失败语义绑定冲突返回冲突码;注销中账号拒绝新绑定
SLA登录校验 P99 50ms;绑定 P99 300ms(示例值)
保留期账号主体保留至注销完成;审计日志按合规期限
降级账号库不可用时,登录校验走短期票据缓存,禁止新注册

关键点:账号状态只有一个写入者。游戏服可以缓存昵称和等级,但不能改账号的封禁、注销与绑定关系。

3.2 结算服务

字段内容
拥有的数据结算单、发奖记录、冲正记录
唯一写入者结算服务;战斗服只提交结算请求
幂等键battle_id + season_id(或业务定义的对局唯一键)
一致性结算单与发奖记录同事务;跨游戏资产最终一致
失败语义重复请求返回原结算单;发奖失败保留待重试状态
SLA结算请求受理 P99 100ms;发奖完成 P99 2s(示例值)
保留期结算单长期保留;原始战斗日志按成本分级
降级发奖通道不可用时进入待发队列,不丢结算单

关键点:先落结算单,再发奖。顺序反过来,一旦发奖后崩溃,就无法判断是否已发。

3.3 支付服务

字段内容
拥有的数据支付订单、渠道回调记录、退款单、对账差异
唯一写入者支付服务;游戏服只能查询订单状态
幂等键内部订单号;渠道回调按渠道单号去重
一致性订单状态强一致;发货通知最终一致,窗口分钟级
失败语义验签失败拒绝;重复回调返回已处理;金额不符挂起
SLA回调处理 P99 500ms;对账日终完成(示例值)
保留期订单与退款按财务与合规要求保留
降级渠道不可用时停止新下单,不停止已支付订单的发货

关键点:支付状态与发货状态分开。已支付未发货是合法中间态,必须有补偿任务,而不是靠人工发现。

3.4 平台能力

字段内容
拥有的数据能力注册表、租户配置、配额与 SLA 指标
唯一写入者平台服务;游戏侧只能申请配额与读取指标
幂等键能力开通请求使用 game_id + capability + version
一致性配置变更最终一致,窗口秒级;配额强一致
失败语义未开通能力返回明确错误;越权访问拒绝并审计
SLA按能力分别定义,不设统一数字
保留期审计日志长期保留;指标按成本滚动
降级单一游戏超配额时只限该租户,不影响其他游戏

关键点:SLA 按能力定义。账号可用性 99.95% 和推荐服务可用性 99.9% 不是同一件事,混在一个数字里无法追责。

四、评审时的十个问题

拿到一张契约卡,按顺序问:

  1. 这份数据如果出现两个写入者,哪一个约束会挡住第二个?
  2. 读取方是走接口还是直连库?直连的什么时候迁走?
  3. 幂等键由谁生成?重复请求返回什么?
  4. 超时后调用方如何确认结果?
  5. 部分成功时,已成功的部分如何回滚或补偿?
  6. 最终一致的窗口多大?窗口内读到旧值会怎样?
  7. SLA 是按接口还是按系统?故障时如何统计?
  8. 删除请求如何传导到缓存、日志和备份?
  9. 依赖不可用时,降级返回什么?谁有权触发?
  10. 上一次契约变更是什么时候?旧版本还支持多久?

十个问题里有两个答不上来,契约就不应该签字。

五、常见错误

错误后果纠正
把接口文档当契约只写了成功路径补失败语义、幂等和 SLA
所有权写成“共同维护”出事无人负责指定唯一写入者
幂等靠“客户端不会重试”网络超时必然重试服务端强制幂等键
所有数据都强一致成本高、跨区不可行按字段定一致性
SLA 只有一个总数无法定位与追责按接口/能力拆分
降级没有触发条件出事时不敢用或乱用写清阈值与授权人
删除只删主表合规风险删除任务覆盖缓存、日志、备份
契约从不复审实现早已偏离变更留版本与复审日期

六、一页纸模板

系统:____            负责人/值班:____
拥有的数据:____
唯一写入者:____      其他写入者及理由:____
读取方与方式:____
幂等键:____          重复请求返回:____
一致性:强一致 ____ / 最终一致 ____(窗口 ____)
失败语义:参数 ____ / 越权 ____ / 冲突 ____ / 不可用 ____ / 结果未知 ____
SLA:接口 ____ P99 ____;可用性 ____;恢复时间 ____
保留期:____          删除传导:____
降级:触发条件 ____;返回 ____;授权人 ____;复审 ____
版本:____            上次复审:____

模板本身不解决问题,它只是让“没想清楚”无处可藏。真正有价值的契约,是两个人分别填写后能得到同一份答案;如果填出来不一样,说明边界还需要再谈一次。

契约卡填完之后,建议和附录 C 的故障模式清单一起过一遍:每个失败语义,是否都有对应的可探测信号和兜底动作。两页纸对不上,系统就还没有准备好接入别人。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「books」更多文章

  1. 《互联网产品的 AI 架构·平台化与治理》附录 C 平台化评审清单
  2. 《互联网产品的 AI 架构·平台化与治理》附录 B 能力目录与配额字段速查
  3. 《互联网产品的 AI 架构·平台化与治理》附录 A 治理角色与职责速查