AI Infra / SWE · VO Coding without AI

Microsoft LLM 前置 SingleFlight:突发请求合并与 Batch 边界

同键并发请求共用一次飞行中的调用;不同键动态批处理是另一机制,需分别定义身份、取消、失败和公平性。

题目重点:同键并发请求共用一次飞行中的调用;不同键动态批处理是另一机制,需分别定义身份、取消、失败和公平性。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 训练版 SingleFlight 的 key 是模型版本、租户/授权范围、规范化 prompt、推理参数与安全策略版本的组合;只有请求完全可共享时才能同键。
  • 同键请求在首次调用完成前共享一个 Future;完成后立刻从 inFlight 删除,因此此组件不充当结果缓存。
  • 多个不同 key 可选进入微批处理器,批量窗口、最大 batch、每项结果映射和服务是否支持 batch 都必须先问;本题只给可选设计。
  • 一位等待者取消不取消其他等待者共享的上游调用;若所有等待者取消,是否取消上游取决于服务语义和资源成本。

解题路线

  1. 接收请求时先做身份/权限/配额检查,再生成无碰撞的结构化共享 key;绝不跨租户、敏感上下文或模型版本盲目复用回答。
  2. 在互斥保护的 map 中查 inFlight[key]:若存在则加入等待者;若没有则创建 Future 并注册唯一 leader。释放锁后 leader 才调用 LLM,避免在锁内执行慢 IO。
  3. leader 在 try/finally 中把结果或异常发布给所有等待者,并仅在 map[key] 仍是这个 Future 时删除;发布/删除顺序及新到请求的边界应由测试锁定。
  4. 若服务支持批量推理,独立批处理器可从多个 leader 请求中在短窗口内凑 batch,保留每个 key 的结果关联;SingleFlight 去掉相同 key 的重复工作,batch 提升不同 key 的吞吐,两者的超时/失败传播不同。
  5. 为一个 key 设最大等待者数量、总排队时长和资源预算;对恶意热键或超长生成做背压。监控 coalescing ratio、leader 延迟、等待者延迟、微批大小、取消与上游失败率。

手动走一遍

同一租户三个完全相同 prompt A 几乎同时到达,map 中只有一个 Future,LLM 调用一次,三者收到同一结果。另一个 prompt B 不可与 A SingleFlight 合并,但支持 batch 时可与 A 的 leader 一同送入批量推理。A 的一位客户端断线,不应使另两位得到取消错误;若 A 请求的授权范围不同,则 key 不同,不能共享。

规模与取舍

查找/注册 inFlight 预期 O(1),内存 O(K+W),K 为同时飞行的不同 key、W 为等待者数;同键上游调用从 W 次降到 1 次。微批额外排队延迟至多窗口 Δ 加调度抖动,收益取决于模型 batch 吞吐曲线,题目未明确。

易错点与追问

容易失分的边界

  • 把 SingleFlight 写成永久缓存,过期/权限语义错。
  • 只用 prompt 字符串做 key,跨租户或不同模型设置错误共享。
  • 在全局锁内调用 LLM,所有不同 key 串行阻塞。
  • leader 异常或超时后没有完成 Future/删除 map,等待者永久挂起。
  • 把不同 prompt 强行当相同请求合并,或把微批处理的结果次序映射错。

继续深挖

  • 流式 token 输出时晚到等待者是否补放历史 token?
  • 分布式多实例如何做跨实例同键合并,成本是否值得?
  • 上游 batch 部分项失败时怎样逐项完成 Future?
  • 等待者超时与 leader 继续执行的生命周期如何定义?
✓已复制微信号!