提交链路是 Online Judge 的关键路径。用户提交代码,进队列,Worker 取出来,发给评测机,等结果,写回数据库。理论上简单。原版 Leverage 的实现是一个基于 Redis List 的自研队列——问题只在出事的时候才会暴露出来。
这篇文章讲我们为什么要换掉它,换成了什么样,以及一个关于消息投递的边界情况,让我不得不认真思考故障模式。
原来的队列
原代码有一个自研的 Queue<T> 类,底层用 Redis List 操作:
// 原版 queue.ts — 概念上类似这样
class Queue<T> {
async push(item: T): Promise<void> {
await this.redis.lpush(this.key, JSON.stringify(item))
}
async pop(): Promise<T | null> {
const result = await this.redis.brpop(this.key, 0) // 阻塞弹出,0=一直等
if (!result) return null
return JSON.parse(result[1]) as T
}
}
大约 9 分钟
