连不上redis大概率是配置或网络问题:先检查redis://地址格式(docker中localhost需换宿主机ip或服务名),用redis-cli -u验证连通性,确认acl权限;任务不执行是因为未启动worker进程;队列需显式声明监听;dead队列任务需手动重试。

asynq 连不上 Redis 怎么快速定位
连不上不是 asynq 的问题,大概率是 Redis 连接配置或网络没通。先确认 redis:// 地址格式对不对,本地开发常用 redis://localhost:6379/0,但 Docker 或远程环境里 localhost 会指向容器自身,得换成宿主机 IP(如 redis://172.17.0.1:6379/0)或服务名。
常见错误现象:failed to dial redis: dial tcp [::1]:6379: connect: connection refused —— 说明 asynq 根本没找到 Redis 实例;redis: connection closed 则可能是认证失败或 timeout 太短。
- 检查
asynq.NewClient初始化时传的asynq.RedisClientOpt是否包含正确Addr和可选的Password - 用
redis-cli -u redis://localhost:6379/0 ping手动验证连通性,别跳过这步 - 如果 Redis 启用了 ACL(6.0+),确保用户有
+ping、+replconf、+psubscribe权限,asynq 内部依赖这些
任务注册后不执行,是不是没启 worker
asynq 不像 Celery 那样自动拉起 worker,client 端调用 client.Enqueue 只是把任务塞进 Redis,必须另起一个进程跑 asynq.ServeMux + asynq.Server 才会消费。漏掉这步,任务就永远卡在 pending 状态。
使用场景:Web 请求中触发异步发邮件、生成报表、清理缓存——这些逻辑写在 handler 里没问题,但执行它们的 worker 必须独立部署,不能和 HTTP server 共用同一个 main() 且没调 server.Run()。
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
- worker 进程启动后会打印类似
started asynq server: addr=... concurrency=10,没这行日志就是没跑起来 -
asynq.Server默认并发是 10,如果任务密集但 CPU 低,可以调高Concurrency;反之高 CPU 场景建议压到 2–4 避免线程争抢 - 别在 worker 里直接用
log.Fatal或 panic 后没 recover,会导致整个 worker 进程退出,后续任务全积压
如何让不同任务走不同队列,避免互相阻塞
asynq 默认所有任务都进 default 队列,但你可以用 asynq.Queue 选项显式指定。比如发短信和生成 PDF 耗时差异大,混在一个队列里,PDF 任务一多就会把短信任务堵住。
参数差异:队列名只是字符串,但会影响 Redis key 前缀(如 asynq:queue:email),所以命名要简洁、无特殊字符、小写。不支持嵌套或动态队列名,得提前定义好。
- 投递时:
client.Enqueue(task, asynq.Queue("email")) - worker 启动时需显式声明监听哪些队列:
asynq.NewServer(rdo, asynq.Config{Queues: map[string]int{"email": 5, "pdf": 2}}),数字是该队列的并发数 - 注意:没被监听的队列里的任务不会被消费,也不会报错,只会静默堆积 —— 这点容易被忽略
任务失败重试几次后进 dead queue,怎么捞出来重试
asynq 把重试耗尽的任务放进 asynq:dead,但它不会自动清理或通知你。想重试,得手动从 dead queue 拉出来再 Enqueue,不能靠重启 worker 解决。
性能影响:dead queue 本身不占资源,但大量堆积说明上游逻辑或下游依赖(如第三方 API)不稳定,长期不管会导致监控失真、磁盘增长(Redis RDB/AOF)。
- 用 CLI 工具查:
asynq stats --redis-addr localhost:6379看dead数量 - 用
asynq retry --id <task_id></task_id>单条重试;或asynq retry --queue email --limit 10批量捞 - 更稳妥的做法是在 worker 中加
mux.HandleFunc("send_email", func(ctx context.Context, t *asynq.Task) error { ... })里捕获特定错误(如net.ErrTimeout),主动调asynq.SkipRetry或降级处理,而不是等它进 dead
asynq pause/resume 模拟中断,看任务能否恢复。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










