Redis如何实现消息队列
1、使用List
List最为简单和直接,主要通过lpush、rpop存储和读取消息队列的(先进先出)
ruby 代码解读复制代码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 类似,zadd 和 zrangebyscore 来实现存入和读取消息
二、Redis如何实现延迟消息队列
ZSet 多了一个分值(score)属性,用它来存储时间戳,用多个线程轮询Zset获取到期的任务进行处理,以此来实现延迟消息队列等,步骤如下:
利用 zadd 向集合中插入元素,以元素的时间戳(超时时间)作为 score
利用 zrangebyscore 以 0 < score <= 当前时间戳 进行获取需要处理的元素
当有满足的条件的元素, 先删除zrem该元素(保证不被其他进程取到),再进行业务逻辑处理;
问题一:延迟队列满足条件的元素为空(或者集合为空)时候,进程会频繁不断向 redis 服务获取满足条件元素,这样会造成 redis 服务资源占用和浪费 ->
可以在没有取到满足的条件时候让程序阻塞一段时间unsleep(10000),这种方法实际上就是用时间换取资源,注意控制阻塞时间长短,不宜太短,也不宜太长(影响即时性)
问题二:有可能出现 zrangebyscore 和 zrem非一个客户端,即原子性问题 -> 采用 lua 脚本解决
三、Redis实现队列的的缺陷
消息没有持久化,如果服务器宕机或重启,消息将会丢失
没有ACK机制,如果消费失败,消息会丢失
没有队列监控、出入对性能差