asynq启动报“redis: dial tcp: connect: connection refused”说明客户端未连上redis,需先确认redis服务是否运行(redis-cli ping应返回pong),再检查asynq.redisclientopt中addr是否正确(docker环境勿用localhost,改用宿主机ip或服务名),并显式传入password字段(含空密码)。

Asynq 启动时提示 “redis: dial tcp: connect: connection refused” 怎么办
这说明 Asynq 客户端连不上 Redis,不是 Asynq 本身的问题,而是底层依赖没就位。常见于本地开发环境没启 Redis,或配置的地址/端口写错了。
- 先确认 Redis 是否运行:
redis-cli ping返回PONG才算通 - 检查 Asynq 初始化时传的
asynq.RedisClientOpt{Addr: "localhost:6379"}—— Docker 环境里别写localhost,得换成宿主 IP 或 docker network 别名(比如redis:6379) - 如果用了密码,必须显式传
Password字段,asynq.RedisClientOpt{Addr: "...", Password: "mypass"},空密码也要设为""
如何注册并触发一个带参数的异步任务
Asynq 不直接传函数闭包,而是靠任务类型(type)+ JSON 序列化参数来调度。类型名要全局唯一,否则 worker 拿到任务后不知道该调谁。
- 定义任务类型常量:
const SendEmailTaskType = "send_email" - 构造任务用
asynq.NewTask(SendEmailTaskType, map[string]interface{}{"to": "a@b.com", "subject": "Hi"}) - 入队用
client.Enqueue(task),支持设置延迟、重试次数等:client.Enqueue(task, asynq.ProcessIn(5*time.Second), asynq.MaxRetry(3)) - Worker 端注册处理器:
mux.HandleFunc(SendEmailTaskType, sendEmailHandler),handler 函数签名固定为func(ctx context.Context, t *asynq.Task) error
为什么任务执行失败后没重试,或者重试次数不对
Asynq 的重试逻辑由两层控制:任务入队时的 MaxRetry 选项,和 handler 返回的错误类型。只有返回非 asynq.SkipRetry 的 error,才会触发重试。
- 默认重试策略是指数退避,首次失败后约 1 秒重试,第二次约 2 秒,第三次约 4 秒……最大间隔 30 分钟
- 若想立刻重试,返回
asynq.Retry{Delay: 0};若想跳过重试,返回asynq.SkipRetry(比如参数校验失败这种永久性错误) -
MaxRetry(0)表示不重试,但 handler 仍需返回 error 才算失败 —— 返回nil就算成功,不会进重试队列
并发消费时多个 worker 处理同一任务怎么办
不会。Asynq 基于 Redis 的 BRPOP + Lua 脚本实现原子出队,天然保证“一个任务只被一个 worker 消费”。但要注意:如果你在 handler 里手动调用了 task.Retry() 或重复 Enqueue,那就可能产生重复任务。
- 避免在 handler 中主动
client.Enqueue相同 type + 相同 payload 的任务,除非业务明确需要幂等重发 - 关键逻辑加幂等判断:比如用 Redis SETNX 记录 task ID,或数据库唯一索引约束
- worker 启动时的 concurrency 参数(如
asynq.ServerConfig{Concurrency: 10})只控制单个进程内并发数,不影响跨实例一致性
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











