所谓延时队列就是延时的消息队列,下面说一下一些业务场景
实践场景
订单支付失败,每隔一段时间提醒用户
用户并发量的情况,可以延时2分钟给用户发短信
先来看看Redis实现普通的消息队列
我们知道,对于专业的消息队列中间件,如Kafka和RabbitMQ,消费者在消费消息之前要进行一系列的繁琐过程。
如RabbitMQ发消息之前要创建 Exchange,再创建 Queue,还要将 Queue 和 Exchange 通过某种规则绑定起来,发消息的时候要指定 routingkey,还要控制头部信息
但是绝大 多数情况下,虽然我们的消息队列只有一组消费者,但还是需要经历上面一些过程。
有了 Redis,对于那些只有一组消费者的消息队列,使用 Redis 就可以非常轻松的搞定。Redis 的消息队列不是专业的消息队列,它没有非常多的高级特性, 没有 ack 保证,如果对消息的可靠性有着极致的追求,那么它就不适合使用
异步消息队列基本实现
Redis 的 list(列表) 数据结构常用来作为异步消息队列使用,使用 rpush/lpush 操作入队列, 使用 lpop 和 rpop 来出队列
> rpush queue 月伴飞鱼1 月伴飞鱼2 月伴飞鱼3
(integer) 3
> lpop queue
"月伴飞鱼1"
> llen queue
(integer) 2
问题1:如果队列空了
客户端是通过队列的 pop 操作来获取消息,然后进行处理。处理完了再接着获取消息, 再进行处理。如此循环往复,这便是作为队列消费者的客户端的生命周期。
可是如果队列空了,客户端就会陷入 pop 的死循环,不停地 pop,没有数据,接着再 pop, 又没有数据。这就是浪费生命的空轮询。空轮询不但拉高了客户端的 CPU,redis 的 QPS 也 会被拉高,如果这样空轮询的客户端有几十来个,Redis 的慢查询可能会显著增多。
通常我们使用 sleep 来解决这个问题,让线程睡一会,睡个 1s 钟就可以了。不但客户端 的 CPU 能降下来,Redis 的 QPS 也降下来了
问题2:队列延迟<