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 作为消息队列时,需要综合考虑系统的可靠性和性能需求,并采取适当的策略来保证消息的顺序。

相关推荐
为java添砖加瓦1 小时前
【读写分离?聊聊Mysql多数据源实现读写分离的几种方案】
java·数据库·spring boot·后端·mysql·spring·mybatis
执键行天涯2 小时前
【JAVA高级】如何使用Redis加锁和解锁(一)、Lua脚本执行原理及流程
java·redis·lua
CoderIsArt2 小时前
数据库系列(1)常见的四种非关系型数据库(NoSQL)
数据库·nosql
ac-er88882 小时前
PHP常用缓存技术
开发语言·缓存·php
小大力3 小时前
简单的spring缓存 Cacheable学习
java·redis·缓存
SelectDB3 小时前
飞轮科技携手观测云亮相云栖大会,全方位展示阿里云数据库 SelectDB 版核心优势
数据库·云原生·云计算
今心上3 小时前
SQL 查询语句的顺序详解
数据库·sql
code.song3 小时前
教师工作量|基于springBoot的教师工作量管理系统设计与实现(附项目源码+论文+数据库)
数据库·spring boot·后端
Python私教3 小时前
macOS安装Redis教程, 通过brew命令, 时间是2024年9月26日, redis版本是0.7.2
数据库·redis·macos
API199701081104 小时前
深度探索与实战编码:利用Python与AWS签名机制高效接入亚马逊Product Advertising API获取商品详情
数据库·python·aws