Skip to content

Distributed Rate Limit 与 Queue Semantics

1. 为什么这组知识要一起学

理解缓存、Redis 原子能力和消息队列在限流、任务分发、重试、幂等与背压中的工程角色。

这几个知识点处在同一条工程链上。如果只记单个名词,很容易在真实系统里把责任放错层:例如让模型管理程序事实、让数据库 transaction 承担外部 API 原子性,或把一个 provider SDK 的行为误认为 Agent 的通用规律。

2. Mental Model

Cache、Redis 与 Queue 是不同抽象:cache 加速可重建数据,Redis 是数据结构/原子操作平台,queue 解耦生产与消费。

text
Producer/Request → Cache lookup / Queue enqueue → Redis primitives → Worker → durable result; miss/duplicate/failure 均有明确策略

3. 核心机制

Distributed Rate Limit

分布式限流可用 Redis 原子计数/滑窗/令牌桶,key 必须包含 tenant/user/provider scope 并设置过期。

Queue Semantics

bounded asyncio.Queue 用 put 的阻塞实现 backpressure;worker pool 消费任务,shutdown 时要停止接收并 drain/cancel。

At-least-once

消息系统常保证至少一次,因此消费者必须容忍重复;ack/visibility/lease 决定 worker crash 后是否重新投递。

4. 最小实现 / 伪代码

下面代码只表达边界和生命周期,不要求照抄到项目中:

python
async def worker(queue):
    while item := await queue.get():
        try:
            await process_idempotently(item)
        finally:
            queue.task_done()

真正实现时应把 I/O、状态持久化、错误翻译和策略注入拆成可测试组件,而不是把示例扩成一个巨型函数。

5. 在 Shadow Harness 中怎么落地

先在进程内实现 cache/queue contract,再根据跨进程需求换 Redis;worker 设计默认 at-least-once + idempotency。

建议为本章涉及的行为留下明确的 domain object、interface 和 trace event;只要一个关键行为只能通过读日志猜测,就说明 Runtime contract 仍不够清晰。

6. Production Engineering 检查项

  • key 包含 user/scope/version
  • TTL 不等于正确 invalidation
  • queue 有 retry/DLQ
  • 限流与并发限制分开

7. Failure Modes

7.1 cache 变唯一事实源

当出现「cache 变唯一事实源」时,检查 cache key scope/version、TTL/stale window、delivery/ack/retry/DLQ 与 worker idempotency。 这类问题通常需要修改 contract、policy、state 或 adapter,而不是只追加 Prompt。

7.2 缓存模型结果跨权限复用

当出现「缓存模型结果跨权限复用」时,检查 cache key scope/version、TTL/stale window、delivery/ack/retry/DLQ 与 worker idempotency。 这类问题通常需要修改 contract、policy、state 或 adapter,而不是只追加 Prompt。

7.3 消息重复导致副作用

当出现「消息重复导致副作用」时,检查 cache key scope/version、TTL/stale window、delivery/ack/retry/DLQ 与 worker idempotency。 这类问题通常需要修改 contract、policy、state 或 adapter,而不是只追加 Prompt。

7.4 unbounded queue 积压

当出现「unbounded queue 积压」时,检查 cache key scope/version、TTL/stale window、delivery/ack/retry/DLQ 与 worker idempotency。 这类问题通常需要修改 contract、policy、state 或 adapter,而不是只追加 Prompt。

8. Trade-offs

本地 cache 最快但不共享;Redis 共享但增加网络与运维;queue 提高解耦/削峰但不自动让任务更快。

设计记录最好明确:当前约束是什么、备选方案有哪些、为什么现在选这个、未来什么条件出现时需要重构。 这样 ADR 才能随着模型和基础设施变化被重新审视。

9. Experiment / Evaluation

压测 cache hit/miss、stampede、worker crash、重复 delivery、DLQ,验证 key scope 与 idempotent worker。

实验应固定数据集、版本和环境,至少记录 success、latency、token/cost、attempt/step 数以及失败类型;涉及随机模型时需要重复运行而不是只看一次结果。

10. 常见问题

基础:Distributed Rate Limit 最容易被误解的点是什么?

分布式限流可用 Redis 原子计数/滑窗/令牌桶,key 必须包含 tenant/user/provider scope 并设置过期。

机制:这些能力在一次 Run 的哪个生命周期阶段生效?

沿着 Producer/Request → Cache lookup / Queue enqueue → Redis primitives → Worker → durable result; miss/duplicate/failure 均有明确策略 找位置,并明确它的输入、输出、持久化事实和失败传播。

工程:如果这一层失败,应该由谁恢复?

先区分 transient failure、invalid input、permission、semantic failure 与 irreversible side effect。恢复策略属于拥有该状态与副作用的 Runtime/adapter,而不是交给模型自由决定。

设计:规模扩大 10 倍后,哪个假设最先失效?

优先检查 context/token、并发/连接池、catalog 大小、持久化吞吐、trace 体积、身份与租户隔离。不要默认“多加机器”能解决语义和一致性问题。

11. Sources

12. 本文结论

掌握本文的标准不是能背定义,而是能画出数据流、写出最小 contract、解释失败恢复,并用测试或 benchmark 证明设计没有只停留在概念层。

AI Engineering · Agent · Harness · Backend Systems