讲师中心 微信公众号
AI工具推荐 视频效率加速

在Golang中如何高效监听并消费Redis ZSet到期的延迟消息

轻敏同学_6276

轻敏同学_6276

发布时间:2026-09-17 06:21:27

|

180人浏览过

|

来源于php中文网

原创

不能直接用ZRANGEBYSCORE+ZREM组合,因二者非原子执行存在竞态窗口:多worker同时扫描会重复获取同一消息,导致重复消费或panic丢失;ZPOPMIN不标记状态致崩溃任务无法恢复;必须用Lua脚本原子封装查、删、推三步,并用ZREMRANGEBYSCORE批量删除防性能下跌。

在golang中如何高效监听并消费redis zset到期的延迟消息

为什么不能直接用 ZRANGEBYSCORE + ZREM 组合

常见错误是轮询时先 ZRANGEBYSCORE 拿一批消息,再逐条 ZREM 删除——这中间存在竞态窗口。两个 worker 同时扫到同一时间窗口,都拿到 "order:123",一个成功消费并删掉,另一个也去删(可能部分失败),但消息体早已被取走,结果就是重复执行,或某条因 panic 没进业务逻辑就从 ZSET 消失,彻底丢失。

Redis 不保证多命令原子性;ZPOPMIN 看似能解决,但它只弹出不标记,worker 崩溃后任务无法恢复;ZREMRANGEBYSCORE 又无法区分“已取未处理”和“真到期”,容易误删。

  • 必须用 Lua 脚本把「查 + 删 + 推入待消费 LIST」三步锁死在 Redis 服务端执行
  • 脚本里用 ZREMRANGEBYSCORE 删除整段,不是逐条 ZREM,否则高并发下性能断崖下跌
  • 消息体必须带唯一 id 字段,消费端做幂等——Lua 原子性不是银弹,网络分区或脚本中断时仍可能漏删

如何写一个安全可用的 Lua 脚本

脚本核心是:用 ZRANGEBYSCORE 扫描带 WITHSCORES 的到期消息 → 提取所有 member → 用 ZREMRANGEBYSCORE 原子删除 → 用 RPUSH 批量推入目标 LIST。

示例脚本 delay_pop.lua

Golang Samber Do
Golang Samber Do

使用 samber/do 在 Golang 中实现依赖注入 — 服务容器、生命周期管理、作用域、健康检查、优雅关闭和模块组织

下载

立即学习go语言免费学习笔记(深入)”;

local keys = redis.call('ZRANGEBYSCORE', KEYS[1], '-inf', ARGV[1], 'WITHSCORES', 'LIMIT', 0, 100)
if #keys == 0 then return {} end
local members = {}
for i = 1, #keys, 2 do
  table.insert(members, keys[i])
end
redis.call('ZREMRANGEBYSCORE', KEYS[1], '-inf', ARGV[1])
for _, m in ipairs(members) do
  redis.call('RPUSH', KEYS[2], m)
end
return members
  • KEYS[1] 是 ZSET key(如 "delay_zset"),KEYS[2] 是目标 LIST key(如 "ready_list"
  • ARGV[1] 必须是当前毫秒时间戳字符串,用 strconv.FormatInt(time.Now().UnixMilli(), 10) 生成,别硬写死
  • 别用 time.Now().UnixNano()——Redis score 是 double 类型,纳秒转 float64 会丢失精度
  • LIMIT 0 100 控制单次最多拉取条数,防 OOM 和 Redis 阻塞

Go 中调用 Eval 时的关键细节

go-redis/v9 的 client.Eval 是入口,但参数传错就白忙活。常见问题包括:score 单位不一致、key 名拼错、context 超时没设、连接没复用。

  • ctx 必须带超时:ctx, cancel := context.WithTimeout(ctx, 3*time.Second),防止单次卡死阻塞 goroutine
  • KEYS 参数传的是真实 Redis key 名字符串,不是变量名;ARGV[]interface{},其中 ARGV[0] 是时间戳字符串
  • 别在 for 循环里反复 defer conn.Close()——连接必须复用,用 redis.NewClient() 初始化一次
  • 轮询前建议先 ZCOUNT delay_zset -inf ARGV[1] 判断有无到期项,避免空轮询打满 Redis QPS

轮询节奏与容错怎么配才不翻车

每 100ms 扫一次看似响应快,实则浪费连接、抬高 CPU、打满 Redis QPS;更糟的是空轮询时没限流,Redis 线程一直忙等。生产环境别这么干。

  • 基础轮询间隔设为 500ms ~ 1s,首次启动时用 ZCARD 预热,有积压立刻拉取
  • 扫描范围建议加缓冲窗口,比如查 now_ms - 5000now_ms,防 Redis 与应用服务器时间不同步
  • 消息体建议存 JSON,含 idpayloadcreated_at 字段,消费端用 id 做幂等判断
  • 真正难的不是怎么存消息,而是怎么让“已取未处理”的消息在崩溃后不丢、不重复、不错序——这要求每一步都带确认机制(如 LIST + ACK + DEL),而这些细节在裸 ZSET 轮询里全得自己补

热门AI工具

更多
LibLibAI
LibLibAI Hot

一款AI视频创作工具,主要用于国内领先的AI创意平台,以海量模型、低门槛操作与“创作-分享-商业化”生态,让小白与专业创作者都能高效实现图文乃至视频创意表达,适合需要提升相关任务效率的用户。

Lovart
Lovart Hot

一款面向视觉设计创作的AI设计平台,可通过智能体和画布工作流辅助制作海报、Logo、网页、PPT及其他视觉内容。

咔片AIPPT

一款在线AI演示文稿制作工具,可根据主题和内容需求辅助生成PPT结构与页面,提高演示材料制作效率。

立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

相关专题

更多
golang如何定义变量
golang如何定义变量

golang定义变量的方法:1、声明变量并赋予初始值“var age int =值”;2、声明变量但不赋初始值“var age int”;3、使用短变量声明“age :=值”等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

479

2024.02.23

golang有哪些数据转换方法
golang有哪些数据转换方法

golang数据转换方法:1、类型转换操作符;2、类型断言;3、字符串和数字之间的转换;4、JSON序列化和反序列化;5、使用标准库进行数据转换;6、使用第三方库进行数据转换;7、自定义数据转换函数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

576

2024.02.23

golang常用库有哪些
golang常用库有哪些

golang常用库有:1、标准库;2、字符串处理库;3、网络库;4、加密库;5、压缩库;6、xml和json解析库;7、日期和时间库;8、数据库操作库;9、文件操作库;10、图像处理库。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

956

2024.02.23

golang和python的区别是什么
golang和python的区别是什么

golang和python的区别是:1、golang是一种编译型语言,而python是一种解释型语言;2、golang天生支持并发编程,而python对并发与并行的支持相对较弱等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

751

2024.03.05

golang是免费的吗
golang是免费的吗

golang是免费的。golang是google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的开源编程语言,采用bsd开源协议。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

1406

2024.05.21

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

3854

2025.06.09

golang相关判断方法
golang相关判断方法

本专题整合了golang相关判断方法,想了解更详细的相关内容,请阅读下面的文章。

1714

2025.06.10

golang数组使用方法
golang数组使用方法

本专题整合了golang数组用法,想了解更多的相关内容,请阅读专题下面的文章。

3686

2025.06.17

Vibeknow在线使用入口合集
Vibeknow在线使用入口合集

本专题汇总了Vibeknow在线创作视频的官方入口及网页版使用教程,涵盖PPT、PDF、Word等文档一键转讲解视频的核心操作,并整理了免费版水印规则与手机端浏览器访问指南,助你快速将知识内容视频化。

0

2026.09.21

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
phpEnv手册
phpEnv手册

共0课时 | 0人学习

进程与SOCKET
进程与SOCKET

共6课时 | 0.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn