必须引入缓冲与节流,分清「单机轻量」和「多实例可靠」路径:单机用channel+定时/定量触发(如writech := make(chan writeop, 1024)),多实例则须用taskq或asynq对接redis实现持久化、重试、延时等可靠性保障。

直接用 go func() 启动 goroutine 处理大批量导入,十有八九会崩——连接池打满、内存暴涨、任务丢失、panic 杀光 worker。必须引入缓冲与节流,且要分清「单机轻量」和「多实例可靠」两种设计路径。
用 channel + 定时/定量触发做单机批量导入缓冲
适合内部系统、日志归档、配置同步等场景,不依赖 Redis,但进程退出即丢数据。
-
writeCh := make(chan writeOp, 1024):缓冲大小不能拍脑袋定;1024 是经验值,超 2000 易 OOM,低于 128 在高吞吐下易积压阻塞生产者 - worker 必须用
select等待双触发条件:case op := (攒够)或 <code>case (超时兜底),只靠数量或只靠时间都不稳 - 批量插入前检查
len(writeCh),超过阈值(比如 800)就该拒绝新写入并告警,而不是等 channel 满了才卡住 HTTP 请求 - 别在循环里反复调
db.Exec;一次INSERT INTO ... VALUES (?, ?), (?, ?), ...塞 100~500 行,MySQL 注意max_allowed_packet,PostgreSQL 注意statement_timeout
用 TaskQ 或 Asynq 接 Redis 做分布式可靠导入队列
用户上传 Excel 导入订单、后台定时跑清洗任务、多台机器协同处理报表——这类场景必须持久化、可重试、能延时,纯内存方案扛不住。
- TaskQ 的
RedisQueue默认走 List(LPUSH/BRPOP),简单但不支持 ACK;要 Exactly-Once,得显式启用 Streams 模式:taskq.NewRedisQueue(taskq.RedisConfig{UseStreams: true}) - Asynq 更适合导入类任务:原生支持
Retry、Delay、Timeout,失败任务自动进 retry 队列,不用自己轮询或补漏 - 别把
memqueue误用上生产;它连Close()都不保证 flush,重启=全量丢任务 - Redis 连接池大小必须显式设:
redis.PoolSize = runtime.NumCPU() * 4,否则高并发下大量connection refused
Gin 中启动异步导入时,Context 和错误怎么兜住
HTTP 接口接收上传文件后立即返回「已入队」,不代表任务成功;后续状态要靠轮询或 webhook,而中间环节最容易翻车。
- 必须调
c.Copy()再传进 goroutine,原c在 handler 返回后可能已被回收,读c.Request.FormValue会 panic - 任务函数内包一层
defer func() { recover() }(),否则单个 Excel 解析 panic 会导致整个 worker goroutine 退出,后续任务没人消费 - 别把错误 log 一打了事;导入失败要存到数据库标记
status = 'failed'并附带error_message,方便运营查原因 - 大文件上传建议先存临时目录(
os.CreateTemp),再发任务 ID 进队列;避免 goroutine 持有*multipart.FileHeader导致内存无法释放
批量导入的事务边界和幂等怎么控制
不是所有导入都允许重试,也不是所有重试都能自动续上;没想清楚这点,修复数据比重跑还费劲。
- 单批次导入建议用单事务包裹,但别把整个 10 万行塞一个事务——PG 会锁表,MySQL 可能触发
innodb_lock_wait_timeout - 按主键或业务唯一键做
INSERT ON DUPLICATE KEY UPDATE(MySQL)或ON CONFLICT DO UPDATE(PG),避免「先查再插」引发的竞态 - 任务 ID 要带业务上下文,比如
import:order:20260813:abc123,重试时可查 DB 判重,而不是盲目再执行 - 如果导入过程涉及下游服务(如发消息、扣库存),必须实现补偿逻辑;队列只管调度,不管业务一致性
真正难的不是把数据塞进队列,而是当某批 5000 行导入失败、重试三次仍卡在第 2371 行时,你能否快速定位是字段长度超限、还是关联数据被删了——日志结构、错误分类、任务元信息留存,这些比选哪个库更重要。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











