Redis实现消息队列
Redis 的消息队列不是专业的消息队列,它没有非常多的高级特性,没有 ack 保证,如果对消息的可靠性有着极致的追求,那么它就不适合使用。
异步消息队列
Redis 的 list(列表) 数据结构常用来作为异步消息队列使用,使用rpush/lpush
操作入队列,使用lpop/rpop
来出队列。
阻塞读
blpop/brpop
命令就是阻塞读。
阻塞读在队列没有数据的时候,会立即进入休眠状态,一旦数据到来,则立刻醒过来。消息的延迟几乎为零。用blpop/brpop替代前面的lpop/rpop,就解决了队列为空时,循环读取的问题。
如果线程一直阻塞在哪里,Redis 的客户端连接就成了闲置连接,闲置过久,服务器一般会主动断开连接,减少闲置资源占用。这个时候blpop/brpop
会抛出异常来,消费者的时候要小心,注意捕获异常,还要重试。
延时队列
延时队列可以通过 Redis 的 zset
(有序列表) 来实现。将消息序列化成一个字符串作为 zset
的value,这个消息的到期处理时间作为score,然后用多个线程轮询 zset
获取到期的任务进行处理,多个线程是为了保障可用性,万一挂了一个线程还有其它线程可以继续处理。因为有多个线程,所以需要考虑并发争抢任务,确保任务不能被多次执行。
Redis 的 zrem
方法是多线程多进程争抢任务的关键,它的返回值决定了当前实例有没有抢到任务,因为 loop
方法可能会被多个线程、多个进程调用,同一个任务可能会被多个进程线程抢到,通过 zrem
来决定唯一的属主。