题目重点:围绕题目强调的 schema 设计,拆分比赛/题目/参赛者/提交/判题结果/排行榜,解释唯一约束、判题重试、隔离执行与成绩重算。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练版本支持按开始/结束时间开放的比赛,参赛者报名后对多道题提交代码,异步判题并查看自己的提交和公开排行榜;先以每题最高分计分,排名按总分降序、达到该分的时间升序。
- 题目测试点和标准答案为受保护数据,参赛者不可直接读取;编程语言、时间/内存限制由题目版本确定。其他赛制如错误罚时或部分隐藏榜单是可配置追问,并非题目已知约束。
- 容量示例:10 万参赛者在 2 小时内各提交 10 次约 139 次提交/秒平均,临近截止的峰值可高很多;只是面试容量推演,不代表 Uber 内部流量。
解题路线
- 关系模型至少有 contests(id,startAt,endAt,rulesVersion,state),problems(id,statementVersion,testSetVersion,limits),contest_problems(contestId,problemId,ordinal,weight),registrations(contestId,userId,registeredAt),submissions(id,contestId,problemId,userId,language,sourceBlobRef,submittedAt,judgeState,attemptKey),judge_runs(submissionId,runVersion,workerId,state,verdict,score,startedAt,endedAt) 和 score_projection(contestId,userId,totalScore,tieTime,version)。
- 数据库约束:registrations 用 (contestId,userId) 唯一键;contest_problems 用 (contestId,problemId) 唯一键;submissions 的 (userId,contestId,attemptKey) 唯一保证客户端重试不多提交;judge_runs 的 (submissionId,runVersion) 唯一保证重复任务不把分数算两遍。提交时以服务器时间验证比赛窗口与报名身份,并固定题目/测试集版本。
- 提交事务先写 submission=PENDING 与 outbox 事件,随后判题工作器读取代码对象,在无网络、受限 CPU/内存/系统调用的隔离环境运行各测试点;结果写 judge_runs 并通过幂等状态转换更新提交 verdict。队列至少一次投递可接受,但每个 runVersion 只能有一个最终结果。
- 成绩投影从已终结的 judge_runs 重算每人每题最优分,再合成总分与到达时间;排行榜可用有序索引/缓存读 Top N,但数据库中可重放的原始提交与判题记录才是事实源。重判需产生新 runVersion,旧成绩在原规则下仍可审计;公布新榜单时按一个版本切换,避免半数选手新分、半数旧分。
- 提交代码与测试点要做访问控制和保留策略,运行环境隔离并限制出网;监控提交接受率、队列等待、判题耗时、重复任务、成绩投影延迟和排行榜版本。
手动走一遍
参赛者 U 对比赛 C 的题 P 以 attemptKey=abc 提交,API 写入 S1 并回 submissionId。网络超时后同 key 重试仍返回 S1。判题器两次收到 S1/runVersion=1,唯一约束使最终结果只落一次;若得 80 分,该题先前最高为 60,score_projection 从已判结果更新为 80,并把更新时间写成并列排序依据。
规模与取舍
提交量 S 是主存储增长项,源代码和测试输出宜放对象存储,关系库保存引用与元数据 O(S)。每次判题成本约测试点数×用户程序运行预算;榜单若每次从所有提交重算需 O(S),应预聚合为每个比赛/用户/题的最佳成绩后按有序索引取 Top K,最终全量重算仍保留审计能力。
易错点与追问
容易失分的边界
- 只建一个 submissions 表就直接按最新一条算分,漏掉重判版本、不同赛制与最优分规则。
- 队列重试导致重复判题结果修改排行榜两次,没有 attemptKey 和 judge run 版本唯一约束。
- 以客户端时间判定截止,允许用户改本地时钟延迟提交。
- 把用户代码直接在应用服务器执行,未隔离文件系统、网络和资源。
继续深挖
- 如果改为 ICPC 罚时规则,schema 中哪些事实事件不变,哪些 score_projection 逻辑要替换?
- 如何在比赛结束前隐藏部分榜单,又保证管理员审计与最终公布一致?
- 测试集发现错误需全量重判时,如何做新版本投影、进度可见性和原版本回退?
