Communitygithub.com

后台任务队列设计

用于设计后台任务系统时,在 BullMQ / Sidekiq / RQ / Temporal / SQS 之间做选择,决定队列与工作流、并发与速率限制、构建死信队列或实现处理器幂等性。

后台任务队列设计 是什么?

该技能为 AI 代理用户提供了一套全面的后台任务队列设计参考,涵盖任务丢失、重复执行和无限重试三大故障模式。它详细对比了 BullMQ、Sidekiq、SQS 和 Temporal 等流行队列系统在不同场景下的适用性,并深入讲解了幂等性、可靠拉取和可见性超时、错误分类与死信队列、退避与抖动、并发与限流、内存管理等核心能力。文档还明确了何时应选择简单队列(如 BullMQ、Sidekiq、SQS)何时应选择持久化执行引擎(如 Temporal),并列举了常见反模式及相应的质量门控清单。该技能适用于 Node、Ruby、Python 和 Go 等技术栈,且不适用于出站 webhook 发布、事件流(Kafka)拓扑或进程内异步(事件循环)等场景。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/curiositech/windags-skills/tree/HEAD/skills/background-job-queue-design

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

后台任务队列设计 是做什么的?

一个后台任务系统从一开始就必须针对三种故障模式进行设计:任务丢失、重复执行和无限重试。选错了基础组件,接下来的一年你都在修复这三个问题。无论是 BullMQ、Sidekiq、SQS 还是 Temporal 的文档,业界反复达成的共识是:至少一次交付是唯一诚实的语义——设计每个处理器保持幂等,停止追逐精确一次。(Caduh — Queues 101)

根据你的问题跳转:

适用场景

  • 在 Node、Ruby、Python 或 Go 中设计新的后台任务系统。
  • 从 setTimeout / cron / 自建队列迁移到真正的消息代理。
  • Worker 崩溃导致任务丢失。
  • 生产环境的重试导致重复的副作用。
  • 在 BullMQ(Node + Redis)、Sidekiq(Ruby + Redis)、RQ / Celery / Dramatiq(Python)、Asynq(Go + Redis)、SQS(托管)或 Temporal(持久化执行)之间做选择。

核心能力

选择与工作匹配的基础组件

你的场景选择理由
简短、有副作用的任务(发送邮件、调整图片大小)在 Node 上BullMQ原生 Redis 支持、成熟的 DLQ、流程模式,典型吞吐量 ~5k 任务/秒/节点
同上,在 Ruby 上Sidekiq(Pro 版以获得可靠性)相同结构;Pro 版的 super_fetch 通过 LMOVE 实现可靠拉取(Sidekiq 维基)
多步骤工作流,涉及外部 API 扇出、持续数小时到数天的任务Temporal持久化执行;从事件历史重放(Temporal 文档)
AWS 原生、简单扇出、不愿管理 RedisSQS + Lambda托管式至少一次交付;可见性超时和 DLQ 是头等公民(AWS SQS DLQ)
跨区域、多租户隔离Temporal 或 SQS单个 Redis 无法干净地支持多区域
在数据库、邮件和支付系统中都需要精确一次都不选——设计为至少一次 + 幂等处理器代理内部的“精确一次”无法扩展到跨系统场景(Caduh)

隐藏的判断标准:恢复故事的复杂程度如何? 简单的 BullMQ 队列加重试足以处理“发送收据”。一个 12 步骤的购买工作流,需要等待 24 小时等待 webhook,这是 Temporal 工作流,而不是 12 个链式队列任务。

幂等性

这是强制性属性。每个流行队列的文档都以它开头。BullMQ 的幂等任务页面指出:“无论任务在第一次尝试时成功完成,还是最初失败后在重试时成功,都不应对系统的最终状态产生影响。” (BullMQ idempotent-jobs)

实用模式:

// 1. 幂等键来源于业务事件,而非队列。
//    如果有上游事件 ID(如 Stripe event.id、Shopify hook id),请使用它。
const job = await queue.add(
  'send-receipt',
  { orderId, amount },
  {
    jobId: `send-receipt:${orderId}`,   // BullMQ 在队列中通过 jobId 去重。
    attempts: 5,
    backoff: { type: 'exponential', delay: 1000 },
    removeOnComplete: { age: 3600, count: 1000 },
    removeOnFail:     { age: 86400 },
  }
);

// 2. 在处理器内部,同时也在副作用现场进行去重。
async function processSendReceipt(job) {
  const { orderId, amount } = job.data;
  // 如果已发送,则不做任何事。
  const sent = await db.queryOne(
    'INSERT INTO email_sends (idempotency_key, order_id) VALUES ($1, $2) ON CONFLICT DO NOTHING RETURNING id',
    [`send-receipt:${orderId}`, orderId]
  );
  if (!sent) return { skipped: 'already-sent' };
  await emailProvider.send({ to: ..., subject: ..., body: render(amount) });
}

jobId 在重复任务仍在队列中时进行去重。数据库唯一约束在 worker 崩溃、重试和重放时进行去重。两者都是必需的;仅靠 jobId 是不够的,因为 BullMQ 会移除已完成的任务,去重的窗口期会消失。

可靠拉取和可见性超时

当一个 worker 拉取任务后崩溃,会发生什么?

系统默认行为恢复
BullMQ任务有一个 lockDuration(默认 30s)。挂起任务检查器会在超时后重新入队(BullMQ production)Worker 必须延长锁或在 lockDuration 内完成;否则任务会运行两次
Sidekiq OSSPop 操作是非原子的;如果 worker 在 pop 和 process 之间死亡,任务会丢失升级到 Sidekiq Pro 的 super_fetch(Redis 6.2+ 使用 LMOVE 到私有工作队列)
Sidekiq Pro super_fetchLMOVE 到每个进程的工作列表。心跳在 60s 后过期;孤儿检查会扫描并重新入队(Sidekiq wiki)内置
SQS可见性超时(默认 30s,最长 12h)。如果未删除,消息在超时后重新出现将超时设置为大于处理器 p99 延迟;对长任务使用 ChangeMessageVisibility 延长
Temporal活动有心跳和重试策略。工作流历史在 worker 死亡后仍然存在从历史重放;你无需考虑这个问题

陷阱:lockDuration / 可见性超时短于处理器 p99 → 任务运行两次。长于可接受的恢复时间 → 崩溃的工作等待时间过长。先测量你的 p99,将超时设置为大约 3 倍,并对真正长时间运行的任务让处理器发送心跳/延长锁。

错误分类和死信队列

并非所有错误都应该无限重试。SQS 文档指出:“设置最大接收次数...以及将消息发送到 DLQ 的重驱策略(一旦超过阈值)。” (AWS SQS DLQ)

// 在抛出之前进行分类。永久性错误不应重试。
class PermanentError extends Error { constructor(m: string) { super(m); this.name = 'PermanentError'; } }
class TransientError extends Error { constructor(m: string) { super(m); this.name = 'TransientError'; } }

async function process(job) {
  try {
    const user = await db.user(job.data.userId);
    if (!user) throw new PermanentError('user-not-found');   // → 第一次尝试就进 DLQ
    if (user.suspended) throw new PermanentError('user-suspended');
    await externalApi.call(user);
  } catch (e) {
    if (e instanceof PermanentError) {
      // 立即进入 DLQ——重试无济于事。
      job.discard();    // BullMQ:阻止重试
      throw e;
    }
    throw e;            // 网络/超时 → 按尝试策略重试
  }
}

DLQ 还需要:

  • 对增长数量的告警(不仅仅是非零——“DLQ 永远有 3 件事”是正常的;“DLQ 每分钟增长 100”是个火灾)。
  • 一个重放工具(CLI 或管理 UI),以便运维人员可以修复上游 Bug,重放已进入死信的任务并清理 DLQ。
  • 仪表盘(参见 grafana-dashboard-builder)。

退避和抖动

仅指数退避是不够的。如果 1000 个任务都在 12:00:00 因为下游服务短暂故障而失败,简单的指数退避会让所有 1000 个任务在 12:00:01、12:00:03、12:00:07 精确地重试——这会产生惊群效应,可能导致下游服务持续宕机。添加完全抖动:

// AWS 风格的“完全抖动”:delay = random(0, exp_backoff)
const baseDelay = Math.min(2 ** attempt * 1000, 30_000);
const delay = Math.random() * baseDelay;

对于 BullMQ 推荐的基线,going-to-production 文档建议使用 retryStrategy 设置 1s 到 20s 之间的重试间隔。(BullMQ production)

并发和限流器

每个 worker 的并发数允许从一个进程中并行运行 N 个任务。多个 worker 会倍增这个数字。如果没有队列级别的限流器,你无法限制对下游的聚合调用:

// BullMQ — 此队列上所有 worker 的全局速率限制。
const queue = new Queue('outbound-emails', {
  connection,
  limiter: { max: 100, duration: 1000 }, // 整个集群每秒 100 封邮件
});

正确的形式:许多并发的 worker + 一个用于下游合约限制的队列限流器。Sidekiq 有等效的速率限制器;SQS 使用 Lambda 并发或每消息速率。

内存管理

BullMQ 生产环境最强调的一个陷阱:Redis 实例上的 maxmemory-policy noeviction。任何其他策略(allkeys-lru、volatile-lru)都会在压力下静默地驱逐排队中的任务。(BullMQ production)

此外:

  • removeOnComplete 设置激进(例如 { age: 3600, count: 1000 })。
  • 一旦切换到 DLQ 模式,removeOnFail 设置得更激进。
  • 启用 Redis AOF 持久化——appendfsync everysec 是 BullMQ 文档中提到的推荐配置。(BullMQ production)
  • Worker 设置 maxRetriesPerRequest: null 以防止 ioredis 在瞬时断开连接时抛出异常。(BullMQ production)
  • 队列端设置 enableOfflineQueue: false,使生产者快速失败而不是缓冲。

优雅关闭

process.on('SIGTERM', async () => {
  await worker.close();   // 停止接收新任务;完成正在处理的任务。
  await connection.quit();
  process.exit(0);
});
process.on('SIGINT', async () => { /* 相同 */ });

BullMQ 生产指南明确指出:在停止进程之前关闭 worker;默认挂起超时约为 30 秒。(BullMQ production)

队列 vs 工作流决策

Temporal 文档中一个有用的框架:“与在服务之间传递数据的消息队列不同,Temporal 编排整个流程……知道你在工作流中的位置、哪些已完成、哪些待办、哪些需要重试。” (Temporal blog)

flowchart TD
  A[后台工作] --> B{单个副作用还是管道?}
  B -->|单个| C[BullMQ / Sidekiq / SQS]
  B -->|多步骤| D{步骤持续秒级还是小时级以上?}
  D -->|秒级| E[BullMQ flows / Sidekiq batches]
  D -->|小时级以上或人工介入| F[Temporal / DBOS / Restate]
  C --> G{需要跨区域或多租户隔离?}
  G -->|是| H[SQS 或 Temporal — Redis 单集群无法胜任]
  G -->|否| I[使用 Redis 集群 + AOF + noeviction]

反模式

仅通过 Redis SET-NX 实现幂等性

症状: 在 Redis 短暂故障或重启期间,同一个任务运行两次并产生重复的副作用(扣费、邮件、工单)。 诊断: Redis 是一个缓存;它可能被驱逐、重启或分区。仅存在于 Redis 中的 SET-NX 去重是尽力而为的。 修复: 在副作用记录(例如 email_sends.idempotency_key)上使用带数据库唯一约束的幂等键。创建副作用的数据库事务本身就是去重的基础。

lockDuration 短于处理器 p99

症状: 出现挂起任务日志条目;同一个任务被两个 worker 处理。客户投诉。 诊断: 默认的 lockDuration 是 30s;处理器有时需要 45s;第二个 worker 拾取了它。 修复: 测量 p99,将 lockDuration 设置为大约 3 倍 p99,并在长时间运行的处理函数内部调用 job.extendLock()。或者拆分工作。

纯指数退避(无抖动)

症状: 下游短暂故障变成下游中断;1 万个任务在锁步中冲击正在恢复的服务。 诊断: 没有抖动,重试是相关的。 修复: 完全抖动退避。限制最大延迟以限定 DLQ 的超时时间。

Redis 上设置 maxmemory-policy allkeys-lru

症状: 队列在负载下神秘地丢失任务。没有错误。(BullMQ production) 诊断: Redis 驱逐了任务键以腾出空间。 修复: 设置 CONFIG SET maxmemory-policy noeviction 并在启动时断言。Worker 应拒绝启动,否则拒绝启动。

假装跨系统精确一次

症状: 向客户重复扣费;发送了两封相同的邮件。工程师确信“消息代理是精确一次的”。 诊断: 即使是 FIFO/精确一次的代理也不会将其保证扩展到你的数据库、邮件供应商、Stripe 和分类账。 修复: 将队列视为至少一次交付。在每个副作用边界实现幂等性。

死信队列无重放工具

症状: “DLQ 中有 3200 个任务。我们不知道里面有什么。” DLQ 变成了无人监控的墓地。 诊断: 建了 DLQ,但没建运维工具。 修复: 按 ID 重放、按时间范围重放、确认后清空。CLI 或管理 UI。经过测试。

长时间阻塞事件循环的工作

症状: BullMQ worker 进程挂起;心跳停止;锁超时;任务重新运行。 诊断: 与队列心跳在同一进程中执行 CPU 密集型工作;事件循环阻塞超过 lockDuration。 修复: 为 CPU 密集型工作生成子进程或工作线程。或者运行沙箱处理器(BullMQ 支持每任务进程沙箱)。

质量门控

  • 测试: 混沌测试——在任务处理过程中杀死 worker;断言任务重新运行且副作用未重复。
  • 测试: 重试风暴测试——让下游服务故障持续 60s;断言退避和抖动使重试分散(指标中无惊群效应)。
  • 每个处理器都是幂等的,并使用从业务事件派生的稳定幂等键。
  • 数据库级别的唯一约束支持任何 Redis 内的去重(jobId、SET-NX)。
  • lockDuration / 可见性超时 ≥ 3 倍测量的处理器 p99 延迟,并且长时间运行的处理程序会延长锁。
  • 永久性错误(PermanentError 类或等效)绕过重试直接进入 DLQ。
  • DLQ 告警:当增长率超过每分钟 N 条时触发告警,而不仅仅是计数 > 0。
  • DLQ 重放工具存在且经过测试(单次和范围重放)。
  • Redis:maxmemory-policy=noeviction,启用 AOF(appendfsync everysec),并在 worker 启动时断言。(BullMQ production)
  • removeOnComplete 和 removeOnFail 已配置。在长时间内追踪任务计数指标。

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

curiositech/windags-skills

Expert in 2000s-era music visualization (Milkdrop, AVS, Geiss) and modern WebGL implementations. Specializes in Butterchurn integration, Web Audio API AnalyserNode FFT data, GLSL shaders for audio-reactive visuals, and psychedelic generative art. Activate on "Milkdrop", "music visualization", "WebGL visualizer", "Butterchurn", "audio reactive", "FFT visualization", "spectrum analyzer". NOT for simple bar charts/waveforms (use basic canvas), video editing, or non-audio visuals.

curiositech/windags-skills

Expert legal research agent for finding and scraping expungement data state by state. Knows authoritative sources, URL patterns, Firecrawl configuration, and 2026 legal landscape.

curiositech/windags-skills

Expert in 3D computer vision labeling tools, workflows, and AI-assisted annotation for LiDAR, point clouds, and sensor fusion. Covers SAM4D/Point-SAM, human-in-the-loop architectures, and vertical-specific training strategies. Activate on '3D labeling', 'point cloud annotation', 'LiDAR labeling', 'SAM 3D', 'SAM4D', 'sensor fusion annotation', '3D bounding box', 'semantic segmentation point cloud'. NOT for 2D image labeling (use clip-aware-embeddings), general ML training (use ml-engineer), video annotation without 3D (use computer-vision-pipeline), or VLM prompt engineering (use prompt-engineer).

curiositech/windags-skills

Implement WCAG 2.2 AA/AAA compliance with automated testing, keyboard navigation, screen reader support, and focus management. Activate on: accessibility audit, WCAG compliance, keyboard navigation, screen reader, aria attributes, axe-core, focus trap. NOT for: design-level accessibility review (use design-accessibility-auditor), color contrast only (use css-in-js-architect).

curiositech/windags-skills

Time-blind friendly planning, executive function support, and daily structure for ADHD brains. Specializes in realistic time estimation, dopamine-aware task design, and building systems that actually work for neurodivergent minds.

curiositech/windags-skills

Designs digital experiences for ADHD brains using neuroscience research and UX principles. Expert in reducing cognitive load, time blindness solutions, dopamine-driven engagement, and compassionate design patterns. Activate on 'ADHD design', 'cognitive load', 'accessibility', 'neurodivergent UX', 'time blindness', 'dopamine-driven', 'executive function'. NOT for general accessibility (WCAG only), neurotypical UX design, or simple UI styling without ADHD context.

curiositech/windags-skills

>- Apply crisis decision-making research to agent routing, uncertainty triage, and coordination failure analysis in time-pressured systems. Use when diagnosing handoff failures, analytical paralysis, or expert judgment under incomplete information. NOT for routine coding, simple CRUD design, or static single-agent tasks with complete information.

curiositech/windags-skills

Extend and modify the admin dashboard, developer portal, and operations console. Use when adding new admin tabs, metrics, monitoring features, or internal tools. Activates for dashboard development, analytics, user management, and internal tooling.

curiositech/windags-skills

Conversation patterns and interaction protocols for multi-agent systems. Covers request/response, pub/sub, blackboard, delegation chains, debate, critique, consensus, fan-out/fan-in, supervisor-worker, and peer negotiation. Deep analysis of AutoGen conversation patterns, CrewAI delegation, LangGraph state passing, and FIPA-ACL performatives. Teaches how to design what agents say to each other and in what order. Activate on: "agent conversation", "agent protocol", "multi-agent debate", "agent delegation", "supervisor worker pattern", "agent voting", "consensus protocol", "fan-out fan-in", "agent negotiation", "blackboard pattern", "agent dialogue", "conversation topology", "agent handoff". NOT for: wire format or serialization (use agent-interchange-formats), orchestration infrastructure (use agentic-infrastructure-2026), single agent behavior (use agentic-patterns).

curiositech/windags-skills

Meta-agent for creating new custom agents, skills, and MCP integrations. Expert in agent design, MCP development, skill architecture, and rapid prototyping. Activate on 'create agent', 'new skill', 'MCP server', 'custom tool', 'agent design'. NOT for using existing agents (invoke them directly), general coding (use language-specific skills), or infrastructure setup (use deployment-engineer).

curiositech/windags-skills

AI-powered calendar management and agent-based scheduling coordination. Covers calendar APIs (Google Calendar, CalDAV/iCal), AI scheduling assistants (Reclaim, Clockwise, Motion, Cal.com), building custom calendar agents with MCP, multi-calendar merging, timezone management, focus block protection, meeting fatigue detection, and agent-to-agent meeting negotiation protocols. Activate on: "calendar agent", "AI scheduling", "calendar coordination", "meeting scheduling", "calendar API", "focus time protection", "calendar optimization", "Google Calendar MCP", "Reclaim", "Clockwise", "Motion", "Cal.com", "smart scheduling", "calendar-aware agent", "timezone scheduling", "agent negotiation meetings". NOT for: manual calendar UI component design (use form-validation-architect), project management scheduling or Gantt charts (use project-management-guru-adhd), general time-tracking or pomodoro apps (use adhd-daily-planner for time-awareness), building the agent itself from scratch (use agent-creator).

curiositech/windags-skills

Build and adopt production AI agent infrastructure in 2026. Covers framework selection (LangGraph, CrewAI, AutoGen, MCP), orchestration patterns, evaluation, observability, memory systems, and tool use. Also covers the SOCIAL dimension: how to sell agent infrastructure internally, change management, measuring ROI, building trust in autonomous systems, and scaling adoption across teams. Activate on: "agent infrastructure", "agent framework comparison", "which agent framework", "sell AI tools internally", "agent adoption", "agent observability", "agent evaluation", "MCP architecture", "agentic mesh", "enterprise AI agents", "AI change management", "agent ROI". NOT for: building specific agents (use ai-engineer), designing agent behavior patterns (use agentic-patterns), prompt tuning (use prompt-engineer).

curiositech/windags-skills

Fundamental patterns for effective agentic behavior. Teaches decomposition, tool orchestration, error recovery, context management, quality self-assessment, and knowing when to stop. Model-agnostic principles that make any agent more effective regardless of domain. Activate on: "how should I structure this agent", "agentic workflow", "agent patterns", "multi-step task", "tool orchestration", "/agentic-patterns", "decompose this", "agent best practices", "chain of actions", "when should the agent stop", "agent loop design". NOT for: creating agent infrastructure (use agent-creator), building DAGs (use windags-architect), specific tool implementation.

curiositech/windags-skills

Automated discovery and matching of agent skills for dynamic task routing and capability assessment

curiositech/windags-skills

Cryptographic security for agentic systems — zero-trust agent networking, signed message envelopes (JWS/JWE), capability-based security (ocaps), Merkle tree audit trails, WASM sandboxing, and formal verification. Covers CLI dev tool security, mTLS between agents, permission boundaries (least privilege for AI agents), and supply chain security for skills/plugins. Activate on: "agent security", "zero trust agents", "secure agent communication", "capability-based security", "ocap", "signed messages between agents", "agent audit trail", "sandbox agent execution", "agent permissions", "mTLS agents", "cryptographic verification", "agent supply chain", "OWASP agentic", "prove agent did X", "tamper-proof agent logs". NOT for: application-level SAST scanning (use security-auditor), network firewall rules (use infrastructure), SOC2/HIPAA compliance (organizational), or prompt injection defense (use prompt-engineer).

curiositech/windags-skills

Data structures and serialization formats for agent-to-agent communication. Covers message envelopes, structured output schemas, capability declarations, task handoff payloads, error/retry signaling, and context windows as data structures. Deep comparison of A2A protocol, MCP, OpenAI function calling, and LangChain message types. Teaches when to use rigid schemas vs free-form with validation, typed vs untyped, streaming vs batch. Activate on: "agent message format", "agent communication schema", "agent-to-agent protocol", "A2A protocol", "MCP message format", "structured output for agents", "agent interop", "interchange format", "agent serialization", "task handoff format", "capability declaration". NOT for: what agents say to each other (use agent-conversation-protocols), orchestration topology (use multi-agent-coordination), building agent infrastructure (use agentic-infrastructure-2026).

curiositech/windags-skills

Logic-based agent programming language implementing BDI architecture for practical autonomous agent development

curiositech/windags-skills

>- Design AgentSpeak(L)-style BDI agents with context-guarded plans, selection functions, and intention stacks. Use for interruptible autonomy, agent policy, and multi-agent orchestration in dynamic environments. NOT for simple rule engines, static planners, or centralized workflows.

curiositech/windags-skills

Foundational concurrent computation model where actors communicate exclusively through asynchronous message passing

curiositech/windags-skills

license: Apache-2.0 NOT for unrelated tasks outside this domain.

相关技能