跳到主要内容

消息队列

队列如何承接异步任务?​

生产者 → 持久队列 → 消费者领取 → 执行 → 确认完成
失败或确认丢失 → 按策略重试
  • 消息队列: 暂存待处理工作,让生产和消费按各自速度推进,同一任务通常由一个消费者负责处理;
  • 收益: 削峰、解耦并允许独立扩容,前台不用等待长任务完成;
  • 结果语义: “已入队”与“业务已完成”是两个状态,应返回任务标识并允许查询结果;
  • 故障条件: 只有启用并正确配置持久化与确认机制,才能把离线期间的可靠缓冲作为保证;

推送、拉取和任务调度如何选择?​

  • 推送: 代理主动把可用消息交给消费者,减少主动轮询,但需要控制消费者接收速度;
  • 拉取: 消费者按自己的处理能力请求消息,可通过长轮询减少空轮询;
  • 延迟与定时: 在到期后才让消息可见,适合延后处理,不等于任务一定在精确时刻完成;
  • 任务队列: 在消息传递基础上管理任务执行、结果与调度,适合后台计算;

如何理解投递次数与顺序保证?​

保证含义应用需要处理什么
至少一次失败后可能重复投递幂等、去重
恰好一次在明确范围内避免重复生效事务边界、去重期限、外部副作用
FIFO指定范围内保持先入先出分区、并发处理和重试后的顺序
  • 幂等: 同一任务执行多次仍只有一次业务效果,例如以业务请求 ID 对结果做唯一约束;
  • 顺序范围: 分区或消息组内顺序不等于整个系统的全局顺序,发送顺序也不自动等于处理完成顺序;
  • 原文修正: FIFO 不自动保证端到端恰好一次,队列去重不能阻止外部服务被重复扣款;

无法处理的消息应该去哪里?​

  • 死信队列: 把超过重试次数或无法处理的消息隔离,以便检查和修复,避免堵住正常工作;
  • 毒消息: 因格式、数据或代码问题持续导致处理失败,重试前应判断是否有恢复可能;
  • 停止哨兵: 有些系统用 poison pill 表示主动要求消费者结束的控制消息,应与故障消息区分;
  • 安全: 生产与消费应分别鉴权,并按需求加密传输和存储,队列不能成为绕过权限的旁路;

消费赶不上生产时如何施加背压?​

  • 背压: 下游忙时限制上游进入速度,用有限队列避免无限积压耗尽内存、磁盘和等待时间;
  • 拒绝策略: 队满时根据接口语义返回繁忙或限流响应,让客户端在受控时间后重试;
  • 重试策略: 使用退避并加入抖动,避免所有客户端同时重试形成新的峰值;
  • 观测重点: 除队列长度外,还要观察最老消息年龄、消费失败率和生产消费速率差;
  • 原文示例: SQS、RabbitMQ、ActiveMQ、ZeroMQ,其中持久化与代理形态需要按产品区分;