Redis是否能用作消息队列


Redis是否可以作为消息队列?

关于Redis能不能做消息队列,主要是解决以下两个问题

  • 能否保证消息不丢失
  • 消息是否能够堆积

    使用List作为消息队列

    如果使用Redis作为消息队列,那么首先会使用List这个数据类型。生产者将数据放入List中,消费者从List中读取数据。
    那么会产生一个问题:消费者需要不断地从消息队列中读取数据。如果队列为空,那么就会出现CPU空转的情况。如果解决这个空转的问题呢?有两种方式
  1. 如果消息队列为空,那么就先让消费者休息一会,然后再尝试读取数据。这样又会引入一个问题,就是新的消息来了,消费者处理消息会存在延迟。
  2. 如果队列为空,消费者在拉取消息时就「阻塞等待」,一旦有新消息过来,就通知我的消费者立即处理新消息。Redis提供了阻塞式拉取消息的命令:BRPOP/BLPOP

缺点

  1. 不支持重复消费
  2. 消息丢失:消费者拉取到消息后,如果发生异常宕机,那这条消息就丢失了

使用发布订阅模型

Redis提供了PUBLISH/SUBSCRIBE 命令,来完成发布、订阅的操作。
Pub/Sub 最大的优势就是,支持多组生产者、消费者处理消息。

缺点

  1. 可能会导致信息丢失,消费者向队列发布消息,Redis就会转发给消费者的。这个过程是实时的,不存在任何的数据存储。
  2. 无法处理消息堆积。当消息积压时,有可能会导致消费失败和消息丢失。当生产者发布消息时,Redis先把消息写到对应消费者的缓冲区中。之后,消费者不断地从缓冲区读取消息,处理消息。

Redis新的数据类型Stream

Stream通过XADD和XREAD完成最简单的生产、消费模型:

  • XADD:发布消息
  • XREAD:读取消息

特点

  • 支持「阻塞式」拉取消息
  • 支持发布/订阅模式
  • 保证消息不丢失,重新消费。当一组消费者处理完消息后,需要执行 XACK 命令告知 Redis,这时 Redis 就会把这条消息标记为「处理完成」。
  • Stream 会写入到RDB和AOF做持久化。但是
  • 消息堆积时,Stream指定队列的最大长度,防止队列积压导致内存爆炸。当队列长度超过上限后,旧消息会被删除,只保留固定长度的新消息。因此依旧可能会导致丢失消息。

redis作为消息队列问题

Refer:https://mp.weixin.qq.com/s/3oFf0-v6Ba2iO7dIcXY-6A


文章作者: 彭峰
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 彭峰 !
  目录