如何保证最少消费一次redis的list队列数据
简使用pop,不能保证最少消费一次,比如pop超时可能中途丢失,或者消费者处理过程中异常而未能处理完。
解决此问题有多种方法:
1) 方法一:使用rpoplpush替代pop
这种方法相当于建立了一个回滚,由于操作是在redis端完成的,可保证数据不会丢,当消费者完成业务逻辑后,再清掉lpush的另一队列,这步有点类似于事务的commit提交。如果在处理过程中消费者异常重启,则在重启时先检查lpush的队列,完成处理后再清lpush的队列。
2) 方法二:使用lrange+ltrim替代pop
消费时先lrange拿到数据,处理完后再使用ltrim清掉已处理的数据(这步也类似于事务的commit提交)。
不过这里存在一个缺陷:同时只能有一个消费者,不能多线程多进程和多机器同时处理同一个队列,因此消费者存在单点问题,基于Zookeeper等来解决单点有些重,而且在切换会有些延迟,存在短暂停顿问题。
3) 方法三:使用eval(lua)+lrange+ltrim替代pop
站在redis端,list可看作是一个本地队列,借助eval+lua,可实际这个转换。既然是本地队列,则可轻松的实现多消费者并发消费(本质是串型的),通过lua取list中的数据,并维护list数据的移动。
第一步是lua方式取得数据,并更新消费偏移;第二步是lua方式提交更新(也类似于事务的commit提交)。
上述三种方法,方法二缺陷明显。而方法一如果消费者在提交前挂掉,另lpush队列中的数据需要另外处理。方法三相对好维护,即使消费者在提交前挂掉,另外的消费在提交时可以帮助解决消费位置移动(实际是调用ltrim)问题。
当然由于redis的主节点和复制节点间是异步复制,该机制存在的丢数据问题无法通过上述三个方法来解决。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义