首页 > 数据库 >Redis实现消息队列

Redis实现消息队列

时间:2023-07-26 12:33:31浏览次数:47  
标签:积压 队列 Redis 中间件 消息 内存

Redis基于内存,高性能并且提供多种数据结构供使用,那么对于Redis能不能作为消息队列?以及与专业的消息队列,如RocketMQ,Kafka等差距又在哪里?

Redis提供多种方式实现消息队列,基于List,基于Pub/Sub等,如今基本广泛使用的是Redis5.0之后推出的Stream流格式,其具有支持持久化,支持消息的多播、分组消费,支持消息的有序性,支持消费者组等特点,考虑到和专业消息队列之间的区别,这里主要从以下三个角度考虑Redis作为消息队列的利弊:

生产者:
当生产者在发布消息时,可能发生以下异常情况:

    消息未发送:网络故障或其它问题导致发布失败,中间件直接返回失败

    发送状态不确定:网络问题导致发布超时,可能数据已发送成功,但读取响应结果超时了

这两种情况都可以通过重发消息解决,生产者一般会设定一个最大重试次数,超过上限依旧失败,需要记录日志报警处理。也就是说,生产者为了避免消息丢失,只能采用失败重试的方式来处理。这也意味着消息可能会重复发送。根据实际情况,需要在消费者端考虑幂等性。

所以,无论是 Redis 还是专业的队列中间件,生产者在这一点上都是可以保证消息不丢的。

消费者
当消费者拿到消息后,还没处理完成,就异常宕机了,那消费者还能否重新消费失败的消息?

要解决这个问题,消费者在处理完消息后,需要向中间件发送一个ACK, Redis也是可以做到的。

Redis本身
Redis 在以下 2 个场景下,都会导致数据丢失。

AOF 持久化配置为每秒写盘,但这个写盘过程是异步的,Redis 宕机时会存在数据丢失的可能

主从复制也是异步的,主从切换时,也存在丢失数据的可能(从库还未同步完成主库发来的数据,就被提成主库)

像 RabbitMQ 或 Kafka 这类专业的队列中间件,在使用时,一般是部署一个集群,生产者在发布消息时,队列中间件通常会写「多个节点」,以此保证消息的完整性。这样一来,即便其中一个节点挂了,也能保证集群的数据不丢失。

消息积压
因为 Redis 的数据都存储在内存中,这就意味着一旦发生消息积压,则会导致 Redis 的内存持续增长,如果超过机器内存上限,就会面临被 OOM 的风险。Redis 的 Stream 提供了可以指定队列最大长度的功能,就是为了避免这种情况发生。

但 Kafka、RabbitMQ 这类消息队列就不一样了,它们的数据都会存储在磁盘上,磁盘的成本要比内存小得多,当消息积压时,无非就是多占用一些磁盘空间,相比于内存,在面对积压时也会更加「坦然」。

综上,可以看到,把 Redis 当作队列来使用时,面临以下 2 个问题:

1、Redis 本身可能会丢数据

2、面对消息积压,Redis 内存资源紧张

然而,Redis也并不是没有优点,如果你的业务场景足够简单,对于数据丢失不敏感,而且消息积压概率比较小的情况下,把 Redis 当作队列是完全可以的。而且,Redis 相比于 Kafka、RabbitMQ,部署和运维也更加轻量。

如果你的业务场景对于数据丢失非常敏感,而且写入量非常大,消息积压时会占用很多的机器资源,那么我建议你使用专业的消息队列中间件。

总结
大部分使用消息队列的场景都可以使用stream替代。基于redis的高性能和使用内存的机制使得其的性能优于大部分消息队列。在小规模场景会有更出色的表现。但是针对大流量的场景不推荐使用Redis,毕竟内存的大小是有限的,并且Redis也是不可靠的,这也是所有redis实现的消息队列的局限之处。
————————————————
版权声明:本文为CSDN博主「Cat凯94」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/loseyourself94/article/details/129133160

标签:积压,队列,Redis,中间件,消息,内存
From: https://www.cnblogs.com/zhc088/p/17582171.html

相关文章

  • iOS消息推送机制的实现
    iOS消息推送的工作机制可以简单的用下图来概括:Provider是指某个iPhone软件的Push服务器,APNS是ApplePushNotificationService的缩写,是苹果的服务器。上图可以分为三个阶段:第一阶段:应用程序把要发送的消息、目的iPhone的标识打包,发给APNS。 第三阶段:iPhone把发来的消息传递给相应......
  • 链表只有面试有用?Redis 之父说:我不同意
    几天前,Redis之父 SalvatoreSanfilippo(又名antirez)在Twitter上用Rust实现了一个糟糕的链表,引发了大家的讨论。在评论中,不少人觉得链表这种数据结构一无是处,于是几天后,antirez发了一篇博客。原文见:http://antirez.com/news/138antirez说:“从某些评论的语气中,我感觉到很多人......
  • 阻塞的队列
    BLockingQueue是一个阻塞的队列,最典型的应用场景就是生产者和消费者模式。生产者和消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此并不直接通信,而是通过阻塞队列进行通信,所以生产者生产完数据后不用等待消费者进行处理,而是直接扔给阻塞队列,消费......
  • 常见开源消息系统
    消息系统的作用:异步处理、削减峰值、减少组件之间的耦合。选择消息系统根据业务需要需要考虑以下几个方面:是否持久化吞吐能力高可用分布式扩展能力兼容现有协议易于维护其他,如消息丢失和重复的处理避免单点故障负载均衡常见消息系统协议:STOMPAMQP类似MEMCACHE的协议HTTP自定格式......
  • redis学习二十:redis哨兵监控
    是啥:吹哨人巡查监控后台master主机是否故障,如果故障了根据投票数自动将某一个从库转换为新主库,继续对外服务。作用:1.监控redis运行状态,包括master和slave2.当master宕机,能自动将slave切换成新master能干啥:主从监控:监控主从redis库运行是否正常消息通知:哨兵可以将故障转移的......
  • Redis的有序集合Zset为啥用跳表不用二叉树
    跳表和红黑树查找的时间复杂度都是logN,插入删除也是logN。范围查找貌似也都是O(k+logn),其中n是树中节点的数量,k是满足范围条件的节点数量。但是实现起来跳表要简单很多。1.zset有个很核心的操作叫范围查找,我们要查找某个范围区间的元素。跳表可以做到logN时间复杂度内的快......
  • cookie+session(这里使用redistemplate代替)实现单点登录流程
     user发起资源请求(带上回调的路径方便回调),通过判断是否浏览器的cookie中是否存在登录过的痕迹,比如有人登了,然后存了一个cookie到浏览器如果拿到了cookie是有东西的,则带上这个cookie的内容返回给client,如果没有东西,则继续登录,向session中存入userInfo,并给浏览器设置cookie......
  • 【学习笔记】单调队列和单调栈
    单调栈以这道题为例:P5788。我们考虑维护一个单调栈,里面存的是下标,使里面的下标对应的元素从栈顶到栈底是单调上升的。我们从\(n\rightarrow1\)枚举\(a_i\)对于每个\(i\),如果栈非空,令栈顶的下标为\(j\),若\(a_j\)不比\(a_i\)大,那么这个栈顶元素由于值又小,位置又靠后,如......
  • redis 取出指定集合
    Redis取出指定集合Redis是一种高性能的键值存储数据库,它支持多种数据类型,包括字符串、哈希、列表、集合和有序集合。在Redis中,集合是一种无序且唯一的数据结构,它可以存储多个元素。本文将介绍如何在Redis中取出指定集合的元素,并提供相关代码示例。Redis集合Redis集合是一个无序......
  • redis 切换db0到db1命令
    Redis切换DB0到DB1命令实现步骤作为一名经验丰富的开发者,你需要教导一位刚入行的小白如何实现Redis的DB0切换到DB1命令。下面是整个流程的步骤展示:步骤操作1连接Redis服务器2切换到DB03选择DB14验证切换成功接下来,让我们逐步教会小白每......