公会战看起来像一个活动入口,实际是社交、赛程、奖励和公平性纠缠在一起的控制面。报名期间成员频繁进出公会,管理者可能临近截止时间调整阵容,服务器要生成对阵和战场实例,运营还希望支持延期、补偿和重赛。若报名只是一张 guild_war_signup 表,到了赛季中后期就会遇到各种争议:谁有资格参战,转会成员算不算,报名成功后公会解散怎么办,赛程生成失败是否影响整个分组。报名与锁定架构要把公会状态在关键时间点冻结。
典型场景
周五 20:00 公会战报名截止,20:05 生成分组,20:30 开战。某公会在 19:59 踢掉低战力成员并邀请高战力玩家,另一个公会会长在截止前一秒点击报名但网络重试。系统需要判断报名请求是否落在窗口内、成员名单以哪个时间点为准、战力快照是否可追溯、赛程生成是否幂等。这里不能依赖实时公会成员表,因为它会在报名后继续变化。
架构示意
flowchart TD
G["Guild Service"] --> S["Signup API"]
S --> V["Eligibility Validator"]
V --> L["Roster Lock Store"]
L --> M["Match Group Builder"]
M --> B["Battle Schedule"]
B --> I["Instance Provisioner"]
L --> A["Audit and Appeal Tools"]
报名是一个状态机,不是一个布尔字段
公会战报名至少包含 open、submitted、locked、grouped、scheduled、cancelled、rollback_pending 等状态。submitted 表示收到报名意图,locked 表示成员和关键属性已冻结,grouped 表示分组完成,scheduled 表示赛程实例创建完成。每个状态转换都要幂等,并记录操作人、时间、版本和来源。这样运营延期或回滚时,不需要直接改数据库猜状态。
成员名单和属性快照要同时冻结
冻结名单只记录玩家 id 还不够。公会战常常按等级、战力、职位、入会时间、禁赛状态判断资格。报名锁定时应保存这些属性快照,必要时还保存用于排序的战力计算版本。否则玩家报名后强化装备,争议就会变成“到底按报名时还是开战时计算”。不同游戏可以选择规则,但必须在架构上支持可追溯。
资格校验要和公会实时变更解耦
报名截止后,玩家退会、被踢、改名、封禁都不应该自动破坏已生成赛程。参战资格可以在开战前做二次校验,但二次校验只处理封禁、跨区异常等强规则,不应重新计算全部名单。这样能避免公会成员表抖动导致赛程不可复现。
赛程生成必须可重放、可解释
分组和匹配规则要固定输入:报名公会列表、冻结属性、种子、分区规则。生成结果写入 schedule_version,失败后可以用同一输入重放。不要让分组任务每次读取当前数据库状态,否则重试可能产生不同对阵。对玩家来说,赛程争议往往不是技术问题,而是信任问题;可解释日志能减少客服压力。
异常回滚优先回滚控制面,不直接删除战场
如果赛程生成后发现某批公会资格错误,回滚流程应该先冻结入口、标记 schedule_version 无效、创建新版本,再通知实例调度清理旧战场。直接删除战场实例会让已进入玩家掉线且缺少原因。控制面状态清楚后,运行时实例才能按指令收敛。
关键设计取舍
| 维度 | 架构处理 | 重点风险 |
|---|---|---|
| 报名窗口 | 接收报名意图并校验权限 | 重复提交和截止时间 |
| 锁定窗口 | 冻结名单和属性快照 | 成员变更争议 |
| 分组窗口 | 生成可重放对阵 | 随机种子和输入版本 |
| 开战窗口 | 实例创建和二次校验 | 战场容量和禁赛 |
落地检查清单
- 报名、锁定、分组、赛程生成拆成幂等状态机
- 冻结成员名单时保存关键属性和规则版本
- 分组任务输入固定并记录随机种子
- 开战前二次校验只处理强规则
- 运营回滚通过 schedule_version 生成新版本
一线排障与复盘建议
这个架构上线后,团队要提前准备几类排障入口。第一是按玩家、业务单号或场景 id 查询完整链路,能看到请求进入、状态变化、关键版本、外部依赖结果和最终响应。第二是按时间窗口查看异常分布,区分是全局配置错误、单分片容量问题,还是少量玩家边界条件触发。第三是保留人工修复入口,但修复入口必须写审计流水,记录修复前状态、修复后状态、操作人、审批单和影响范围。没有审计的手工修复,短期能救火,长期会破坏系统可信度。
容量评估也要贴近玩法节奏,而不是只看平均在线。运营开活动、赛季结算、跨服匹配、周常刷新和主播带队都会让请求集中到很短窗口。压测脚本应模拟重复点击、弱网重试、服务超时、实例重启和消息乱序,不要只跑顺滑路径。对于玩家资产、资格、奖励、处罚这类敏感链路,压测结果里要额外检查幂等流水和最终状态,不只是吞吐量。
上线前可以采用影子模式:生产请求仍走旧逻辑,新架构旁路计算结果并记录差异。差异样本要由服务端、策划和客服一起看,因为有些差异来自旧逻辑 bug,有些来自新规则理解错误。等差异收敛后,再按小区服、低风险玩法或内部账号灰度。灰度期间观察错误码、超时、回滚次数、人工工单和玩家反馈,确认系统在真实噪声下仍然可解释。
快照字段与版本设计
公会战锁定快照建议包含 guildId、seasonId、signupVersion、leaderId、memberIds、memberJoinTime、memberRoles、powerSnapshot、banStatus、serverId 和 ruleVersion。powerSnapshot 不是实时战力,而是按报名规则计算出的参赛战力。若游戏允许隐藏战力或临时 buff,快照里还要记录计算时排除了哪些加成。
signupVersion 非常关键。报名后每次重新锁定阵容都生成新版本,赛程生成只读取某个已冻结版本。若会长在报名截止前多次调整阵容,旧版本保留但不参与赛程。这样玩家争议时可以看到最终生效的是哪个版本,而不是数据库当前公会成员表。
故障案例:截止前后成员变更争议
某项目公会战截止时间是 20:00,服务端使用数据库时间判断报名,但成员服务和报名服务部署在不同机器,时间相差近 3 秒。一个公会在 19:59:59 邀请高战力玩家,报名服务认为成功,成员服务的入会时间却落在 20:00:02。对手投诉后,研发很难解释这名玩家是否合规。
修复方案是所有报名相关操作都使用活动控制面的 logicalTime。成员变更进入公会事件日志,报名锁定时按 logicalTime 截取事件流,生成阵容快照。机器物理时间只用于日志,不用于资格裁决。这个改动也让补偿和重算更可靠,因为同一批事件用同一个逻辑截止点可以重放出相同名单。
赛程生成的容量保护
大型公会战报名截止后,分组、排序、战场创建会同时发生。控制面应先冻结报名入口,再分批生成分组。不要让玩家查询赛程的请求直接触发生成,否则热门公会页面可能造成重复任务。赛程生成任务写入 progress,前端查询时返回“生成中”和预计时间即可。
战场实例也不必一次性全部创建。可以提前创建高优先级战场,低优先级战场在开战前几分钟预热。实例调度失败时,scheduleVersion 不应失效,而是进入 provisioning_retry。只有规则输入错误才需要废弃赛程版本。区分规则错误和资源错误,回滚代价会小很多。
公平性与运营干预
运营常常需要处理特殊情况:某区服停机、某公会被误封、比赛延期。架构上可以支持干预,但必须让干预显式进入赛季日志。例如延期只改变 battleStartAt,不改变报名锁定时间;重赛生成 rematchVersion,并保留原战果;取消某公会资格要记录处罚依据和影响的对阵。玩家可以接受规则内的运营处理,很难接受看不见的后台改表。
上线验收指标
公会战报名锁定上线前,先用历史赛季数据回放。把历史公会成员事件、报名操作和战力变化输入新控制面,看生成的锁定名单与旧结果差异。差异不一定都是错误,但每一类差异都要能解释。尤其要关注截止时间附近入会、会长转让、公会改名、成员封禁、跨区迁移这些边界。
压测脚本要模拟大量公会在截止前一分钟提交、重复提交、撤回再提交、成员批量变更和赛程生成任务重试。回滚条件包括同一公会出现多个有效 signupVersion、赛程输入不固定、已锁定名单被实时成员表覆盖、对阵版本无法重放。运营后台也要验收,因为真正出问题时第一响应通常不是研发,而是活动运营。
团队协作边界
公会战控制面必须把运营操作产品化。延期、重赛、取消资格、重新分组、手工锁定名单都可能发生,但每个操作都应有权限、审批、影响预览和审计日志。研发不要把这些动作留成临时 SQL,因为赛季活动最容易在周末和晚上出问题,临时 SQL 风险很高。
客服侧也要看到玩家视角的解释:报名是否成功、自己是否在锁定名单、为什么不能参战、当前对阵版本是多少。玩家争议通常来自信息不透明,不一定来自系统错误。
常见误区
第一个误区是把报名截止当作简单时间判断,却没有统一逻辑时间,导致不同服务对“截止前”理解不同。第二个误区是只冻结公会 id,不冻结成员和战力快照,后续任何成员变化都会影响争议判断。第三个误区是赛程生成失败后直接重跑,却没有固定输入和随机种子,导致两次结果不同。公会战是强社交玩法,任何不可解释都会被玩家放大。
数据保留建议
公会战数据至少保留完整赛季加一个申诉周期。报名快照、赛程版本、战斗结果和运营干预记录不要随活动结束立即归档删除。赛季奖励通常会延迟发放,玩家也可能在数天后才发现资格问题。保留可查询数据,比事后从日志仓库拼事实更可靠。
补充一点:赛季结束后不要只保留冠军结果,报名失败、公会弃权、重赛原因和资格剔除也要进入赛季档案。这些边缘记录在下次制定规则时很有价值。
总结
公会战报名系统的难点不是写一个入口按钮,而是让赛季规则在高并发、社交变更和运营干预下仍然可解释。冻结快照和版本化赛程,是减少争议的关键。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。