likes
comments
collection
share

Redis如何实现延迟消息队列

作者站长头像
站长
· 阅读数 45

一、Redis如何实现消息队列

1、使用List

List最为简单和直接,主要通过lpushrpop存储和读取消息队列的(先进先出)

127.0.0.1:6379> lpush mq "firstMsg" #推送消息 firstMsg
(integer) 1
127.0.0.1:6379> lpush mq "secondMsg" #推送消息 secondMsg
(integer) 2
127.0.0.1:6379> rpop mq #接收到消息
"firstMsg"
127.0.0.1:6379> rpop mq #接收到消息
"secondMsg"
2、使用Zset

ZSet 实现消息队列的方式和 List 类似,zaddzrangebyscore 来实现存入和读取消息

二、Redis如何实现延迟消息队列

ZSet 多了一个分值(score)属性,用它来存储时间戳,用多个线程轮询Zset获取到期的任务进行处理,以此来实现延迟消息队列等,步骤如下:

  1. 利用 zadd 向集合中插入元素,以元素的时间戳(超时时间)作为 score
  2. 利用 zrangebyscore 以 0 < score <= 当前时间戳 进行获取需要处理的元素
  3. 当有满足的条件的元素, 先删除zrem该元素(保证不被其他进程取到),再进行业务逻辑处理;

问题一:延迟队列满足条件的元素为空(或者集合为空)时候,进程会频繁不断向 redis 服务获取满足条件元素,这样会造成 redis 服务资源占用和浪费 -> 可以在没有取到满足的条件时候让程序阻塞一段时间unsleep(10000),这种方法实际上就是用时间换取资源,注意控制阻塞时间长短,不宜太短,也不宜太长(影响即时性)

问题二:有可能出现 zrangebyscorezrem非一个客户端,即原子性问题 -> 采用 lua 脚本解决

三、Redis实现队列的的缺陷
  • 消息没有持久化,如果服务器宕机或重启,消息将会丢失
  • 没有ACK机制,如果消费失败,消息会丢失
  • 没有队列监控、出入对性能差
转载自:https://juejin.cn/post/7037860077855834119
评论
请登录