Redis相关知识

参考Redis 消息队列的三种方案(List、Streams、Pub/Sub) - 知乎 (zhihu.com)

各种开源的 MQ 已经足够使用了,为什么需要用 Redis 实现 MQ 呢?

优点:

  • 简单轻量:Redis是一个内存中的数据存储系统,具有轻量级简单 的特点。相比较专门的消息队列系统,使用Redis作为消息队列不需要引入额外的组件和依赖,可以减少系统的复杂性。
  • 速度快:由于Redis存储在缓存 中,它具有非常高的读写性能 。这对于需要低延迟的应用程序非常有优势。
  • 多种数据结构支持 :Redis提供了丰富的数据结构,如列表、发布/订阅、有序集合等。这使得Redis在处理不同类型的消息和任务时更加灵活。
  • 数据持久化:Redis可以通过将数据持久化到磁盘来提供数据的持久性。这意味着即使Redis重启,之前的消息也不会丢失。
  • 广泛的应用场景:Redis不仅可以用作消息队列,还可以用作缓存、数据库、分布式锁等多种用途。如果你的应用程序已经使用了Redis,那么使用Redis作为消息队列可以减少技术栈的复杂性。

缺点:

  • 缺少一些高级特性:相对于专门的消息队列系统,Redis在消息队列方面的功能可能相对简单。例如,它可能缺乏一些高级消息传递功能,如消息重试、消息路由、持久化消息等。
  • 可靠性和一致性:Redis的主要设计目标是提供高性能和低延迟,而不是强一致性和高可靠性。在某些情况下,Redis可能会丢失消息,或者在出现故障时可能无法提供持久性保证。

应用场景:

适用于简单的中小型项目 如果功能简单,访问量并不大 可以考虑

如果你的应用程序对可靠性和高级功能有严格要求,并且需要处理大量的消息和复杂的消息路由,那么使用专门的消息队列系统可能更合适。

消息队列有什么特点?

  • 三个角色:生产者、消费者、消息处理中心
  • 异步处理模式生产者 将消息发送到一条 虚拟的通道 (消息队列)上,而无须等待响应。消费者订阅 或是 监听 该通道,取出消息。两者互不干扰,甚至都不需要同时在线,也就是我们说的 松耦合
  • 可靠性:消息要可以保证不丢失、不重复消费、有时可能还需要顺序性的保证

Redis实现消息队列有几种方法?或者说有几种模型?

  • List
  • Streams
  • 发布、订阅(pub/sub) 模式

List 实现消息队列

Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。所以常用来做异步队列 使用。将需要延后处理的任务结构体序列化成字符串塞进 Redis 的列表,另一个线程从这个列表中轮询数据进行处理

使用 List 实现消息队列是一种点对点 的消息模型,并且消息一经发送出去,便从队列里删除 。如果由于网络原因消费者没有收到消息,或者消费者在处理这条消息的过程中崩溃了,就再也无法还原出这条消息。因此需要消息确认机制

消息确认机制:从一个 list 中获取消息的同时把这条消息复制到另一个 list 里(可以当做备份),而且这个过程是原子的。这样我们就可以在业务流程安全结束后,再删除队列元素,实现消息确认机制。

订阅与发布实现消息队列

我们都知道消息模型有两种

  • 点对点:Point-to-Point(P2P)
  • 发布订阅:Publish/Subscribe(Pub/Sub)

List 实现方式其实就是点对点的模式,下边我们再看下 Redis 的发布订阅模式(消息多播 ),这才是"根正苗红"的 Redis MQ

"发布/订阅"模式同样可以实现进程间的消息传递,其原理如下:

"发布/订阅"模式包含两种角色,分别是发布者和订阅者。订阅者可以订阅一个或者多个频道(channel),而发布者可以向指定的频道(channel)发送消息,所有订阅此频道的订阅者都会收到此消息。Redis 通过 PUBLISH 、 SUBSCRIBE 等命令实现了订阅与发布模式。

发布时若客户端不在线,则消息丢失,不能寻回 ;不能保证每个消费者接收的时间是一致的;若消费者客户端出现消息积压,到一定程度,会被强制断开,导致消息意外丢失。通常发生在消息的生产远大于消费速度时;Pub/Sub 模式不适合做消息存储,消息积压类的业务,而是擅长处理广播,即时通讯,即时反馈的业务。

Streams 实现消息队列

Redis 发布订阅 (pub/sub) 有个缺点就是消息无法持久化,如果出现网络断开、Redis 宕机等,消息就会被丢弃。而且也没有 Ack 机制来保证数据的可靠性,假设一个消费者都没有,那消息就直接被丢弃了。

Stream 提供了消息的持久化和主备复制功能,可以让任何客户端访问任何时刻的数据,并且能记住每一个客户端的访问位置,还能保证消息不丢失。

它就像是个仅追加内容的**消息链表**,把所有加入的消息都串起来,每个消息都有一个唯一的 ID 和对应的内容。而且消息是持久化的。

Redis如何保证消息有序

Redis 是一个开源的内存数据存储系统,它被广泛用于实时应用程序中,包括消息队列系统。在使用 Redis 作为消息队列时,消息的顺序性是一个重要的问题。下面是一些方法,可以帮助 Redis 保证消息的顺序:

  1. 使用单线程处理消息:Redis 是单线程的,这意味着它可以逐个处理消息,确保消息的顺序性。当消息到达 Redis 时,可以依次处理它们,而不用担心并发操作导致顺序混乱。

  2. 使用有序集合(ZSet):有序集合是 Redis 中的一种数据类型,它按照元素的分数进行排序。可以将消息的序列号作为元素的分数,将消息内容作为元素的值。通过使用有序集合,可以按照序列号的顺序存储消息,并通过分数范围查询来获取消息。

  3. 使用自增序列号:可以为每个消息分配一个唯一的自增序列号,并将消息放入 Redis 的列表或有序集合中。当需要获取消息时,可以按照序列号顺序遍历列表或有序集合,以保证顺序性。

  4. 使用 Redis 事务:Redis 支持事务操作,可以将多个操作封装在一个事务中。通过使用事务,可以确保多个消息的连续操作在同一个事务中执行,从而保证消息的顺序性。

  5. 使用 PUB/SUB 模式:Redis 提供了发布订阅(PUB/SUB)模式,可以实现一对多的消息传递。在发布消息时,可以指定消息的频道(channel),订阅者按照订阅顺序接收消息。通过使用 PUB/SUB 模式,可以保证订阅者按照顺序接收消息。

需要注意的是,尽管 Redis 可以通过上述方法保证消息的顺序性,但在分布式环境下,由于网络延迟和节点故障等原因,仍然可能发生消息的顺序混乱。因此,在设计使用 Redis 作为消息队列时,需要综合考虑系统的可靠性和性能需求,并采取适当的策略来保证消息的顺序。

相关推荐
白鹭1 小时前
MySQL源码部署(rhel7)
数据库·mysql
666和7771 小时前
Struts2 工作总结
java·数据库
还听珊瑚海吗1 小时前
SpringMVC(一)
数据库
星期天要睡觉3 小时前
MySQL 综合练习
数据库·mysql
Y4090013 小时前
数据库基础知识——聚合函数、分组查询
android·数据库
JosieBook4 小时前
【数据库】MySQL 数据库创建存储过程及使用场景详解
数据库·mysql
处女座_三月4 小时前
改 TDengine 数据库的时间写入限制
数据库·sql·mysql
酷ku的森4 小时前
Redis中的hash数据类型
数据库·redis·哈希算法