redis实现消息队列

这篇具有很好参考价值的文章主要介绍了redis实现消息队列。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

背景

消息队列(Message Queue)是一种常见的软件架构模式,用于在分布式系统中传递和处理异步消息。它解耦了发送消息的应用程序和接收消息的应用程序之间的直接依赖关系,使得消息的发送者和接收者可以独立地演化和扩展。

消息队列的基本原理是发送者将消息发送到一个中间代理(即消息队列),然后接收者从该中间代理中消费消息。中间代理充当了消息的缓冲区,确保消息的可靠传递和持久化存储(根据需要),同时提供了高吞吐量、低延迟和可伸缩性。

redis实现消息队列,redis,数据库,缓存,java,springboot

相信在做分布式服务开发的时候,或多或少的使用到了消息队列,如主流的kafkarocketMQ。总结下来,消息队列的优点包括:

  • 异步通信:发送者和接收者之间的解耦,使得它们可以独立地操作和演化,无需实时等待回应。
  • 应用解耦:消息队列使不同的应用程序能够以独立的方式进行开发、部署和伸缩,降低了系统之间的耦合度。
  • 削峰填谷:消息队列可以作为缓冲区,处理突发的请求和高峰期的流量,从而减轻系统的压力。
  • 消息持久化:消息队列可以将消息持久化存储,确保在异常情况下不会丢失消息。
  • 可靠性和扩展性:消息队列提供了高可靠性和可伸缩性,通过多个消费者处理大量的消息。

总而言之,消息队列是一种强大的软件架构模式,通过解耦应用程序之间的依赖关系,提供了高可靠性、高吞吐量和可伸缩性的消息传递机制。它在构建分布式系统、处理异步任务和解决系统耦合等方面发挥着重要作用。

那今天的案例呢,没有使用到kafka rocketMQ, 而是继续我的专题redis

redis实现消息队列

list

list这种数据结构天然的支持消息队列,常用的命令如下:

命令 描述
LPUSH key value 在列表头部插入一个或多个值
RPUSH key value 在列表尾部插入一个或多个值
LPOP key 弹出并返回列表头部的一个值
RPOP key 弹出并返回列表尾部的一个值
LRANGE key start stop 获取列表中指定范围内的所有值
LLEN key 获取列表的长度

redis实现消息队列,redis,数据库,缓存,java,springboot

好的,这个shigen用Java的代码实现以下:

  • 创建消息队列服务类redisMessageQueueService

redis实现消息队列,redis,数据库,缓存,java,springboot

主要的是三个方法,发送数据、消费数据和判断消息队列是否为空。

  • 消息处理类messProcessor

redis实现消息队列,redis,数据库,缓存,java,springboot

这个类或者说是组件主要是处理消息,这里简单的在控制台输出打印。

  • 系统的接口messageQueueController

redis实现消息队列,redis,数据库,缓存,java,springboot

其实就是通过接口的方式调用messageQueueServie,实现消息的发送和接受消费。

那最终的效果是什么样的呢》我本地使用的是curl进行的进一步的测试。

list实现的方式测试效果:

redis实现消息队列,redis,数据库,缓存,java,springboot

最后,总结一下list实现消息队列的优缺点:

优点:

  • 简单易用:Redis的List数据结构操作简单,易于理解和使用。
  • 支持多样化操作:List数据结构提供了丰富的操作方法,如插入、删除、获取范围等。

缺点:

消息队列的设计最重要的就是消息的防丢失问题

  • 缺乏消息确认机制:List方式没有内置的消息确认机制,当消费者处理消息失败或发生异常时,消息可能会丢失。
  • 不支持消息持久化:Redis的List数据结构默认存储在内存中,当Redis重启或宕机时,消息也会丢失。
  • 不适合高并发场景:在高并发情况下,List方式可能存在性能问题,因为LPUSH和BRPOP是单线程操作,无法充分利用多核CPU的优势。
  • 不适合多订阅者。现在的list是一对一的模式,不支持一对多的模式。

pub/sub模式

针对list一对一的模式,pub/sub可以实现一对多的模式。

redis实现消息队列,redis,数据库,缓存,java,springboot

常见的redis操作命令如下:

命令 描述
PUBLISH channel message 将消息 message 发送到指定的频道 channel
SUBSCRIBE channel [channel …] 订阅一个或多个频道,接收这些频道中发布的消息
UNSUBSCRIBE [channel [channel …]] 取消订阅一个或多个频道
PSUBSCRIBE pattern [pattern …] 订阅一个或多个符合给定模式的频道
PUNSUBSCRIBE [pattern [pattern …]] 取消订阅一个或多个符合给定模式的频道
PUBSUB subcommand [argument [argument …]] 获取关于 Redis Pub/Sub 状态的信息

我们在控制台测试一下:

redis实现消息队列,redis,数据库,缓存,java,springboot

那具体的代码如何实现呢?这里依旧选取的是Java代码作为案例的设计。

  • 定义消息发布的接口并实现发送消息的操作MessagePublisherImpl

redis实现消息队列,redis,数据库,缓存,java,springboot

  • 消息订阅者messageSubscriberImpl

redis实现消息队列,redis,数据库,缓存,java,springboot

  • 配置类中加上redisMessageListenerContainer的bean

redis实现消息队列,redis,数据库,缓存,java,springboot

  • controller测试

redis实现消息队列,redis,数据库,缓存,java,springboot

服务运行,接口测试一下:

redis实现消息队列,redis,数据库,缓存,java,springboot

订阅多个topic的话,这样设置:

container.addMessageListener(messageListener, new PatternTopic("pub_channel"));
// 监听多个topic
container.addMessageListener(messageListener, new PatternTopic("pub_channel1"));

ok,貌似这种方式也显得很nice,至少比list的实现方式更nice,那它能解决实际的问题吗?我们总结一下这种方式的优缺点:

优点:

  • 实现了多个消费者订阅同一个topic

缺点

  • 数据不可靠:Redis 的 pub/sub 模式没有任何持久化机制,如果发布的消息在订阅者还没有收到前发生宕机,那么这些消息将会丢失。因此,如果需要确保数据的可靠性和持久化,需要使用 Redis 的其他数据结构或者使用 Redis 的 AOF 或 RDB 持久化机制。

  • 消息不能防止重复消费:Redis 的 pub/sub 模式不支持消息的确认和回调机制,因此,当订阅者收到消息时,无法对其进行确认,也就无法防止重复消费

那有什么好的解决方式呢?stream应需求而生。

stream

Redis 的 Stream 是一个基于时间序列的数据结构,用于存储和处理消息。Stream 可以看作是一个由消息组成的日志,每个消息都有一个唯一的 ID(可以是时间戳或其他方式生成),并且可以对消息进行按照时间的顺序和优先级进行排序。

Stream 可以支持多个消费者,并且可以保证每个消费者只能消费一次。Stream 还可以在一个组内进行消费者间负载均衡,以提高系统的可扩展性和高可用性。

常用的API如下:

API 描述
XADD 向指定的 Stream 中添加一个条目(消息)XADD key ID field string [field string …]
XDEL 从指定的 Stream 中删除一个或多个条目
XRANGE 获取指定范围内的条目
XREVRANGE 获取指定范围内的逆序条目
XLEN 获取 Stream 中的条目数量
XREAD 从一个或多个 Stream 中读取待处理的条目
XGROUP 创建、管理和操作消费者组
XACK 确认一个或多个已处理的条目
XCLAIM 批量方式对待处理的条目进行声明和处理
XPENDING 获取待处理的条目信息
XTRIM 删除指定范围之外的条目
XINFO 获取 Stream 的相关信息

参考文章:基于Redis的Stream类型的完美消息队列解决方案

添加和读取消息的命令测试如下:

redis实现消息队列,redis,数据库,缓存,java,springboot

shigen在敲命令的时候也觉得很繁琐,有点麻烦,还是期待Java代码的api去操作消息队列。

参考文章:redis灵魂拷问:如何使用stream实现消息队列 如何在Springboot中使用Redis5的Stream

  • 定义生产消息的messageProcuder

redis实现消息队列,redis,数据库,缓存,java,springboot

主要是用来实现消息的发送

  • 消息的接受messageReceiver

实现了消息的ack

redis实现消息队列,redis,数据库,缓存,java,springboot

  • 测试接口

redis实现消息队列,redis,数据库,缓存,java,springboot

测试中发现了如下错误:

redis实现消息队列,redis,数据库,缓存,java,springboot

使用stream并不适合用jedis作为连接池。因为我之前的案例都是基于jedis的,在这里果断的放弃了。

好了,以上就是《redis实现消息队列》的全部内容了。


shigen一起,每天不一样!文章来源地址https://www.toymoban.com/news/detail-708827.html

到了这里,关于redis实现消息队列的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Redis缓存数据库

    目录 一、概述 1、Redis  2、Redis的安装 Redis Windows环境设置 3、String: 字符串 3.1、字符串 3.2、数值 3.3、bitmap 4、Hash: 散列 5、List: 列表 6、Set: 集合 7、Sorted Set: 有序集合 常识: 磁盘:1.寻址:ms(毫秒)2.带宽:MB/s 内存:1.寻址:ns    (纳秒) 2.带宽:GB/s 秒--毫秒--微妙--纳秒

    2024年02月04日
    浏览(41)
  • redis实战-缓存数据&解决缓存与数据库数据一致性

    缓存( Cache),就是数据交换的 缓冲区 ,俗称的缓存就是 缓冲区内的数据 ,一般从数据库中获取,存储于本地代码。防止过高的数据访问猛冲系统,导致其操作线程无法及时处理信息而瘫痪,这在实际开发中对企业讲,对产品口碑,用户评价都是致命的;所以企业非常重视缓存技术,

    2024年02月12日
    浏览(38)
  • Redis缓存数据库(四)

    目录 一、概述 1、Redis Sentinel 1.1、docker配置Redis Sentinel环境 2、Redis存储方案 2.1、哈希链 2.2、哈希环 3、Redis分区(Partitioning)  4、Redis面试题 Redis Sentinel为Redis提供了 高可用解决方案 。实际上这意味着使用Sentinel可以部署一套Redis, 在没有人为干预的情况下去应付各种各样的失

    2024年02月05日
    浏览(41)
  • redis数据库缓存服务器

    redis比mysql访问数据快 非关系型数据库以键值对的方式存储数据 作用:加快访问速度,缓解数据库压力 redis最新版本7 特点 丰富的数据结构 list,set,hash等数据结构的存储 支持持久化 支持事务 “一个完整的动作,要么全部执行,要么什么也没有做” 支持主从支持高可用,支持

    2024年02月05日
    浏览(41)
  • Java使用Redis实现消息队列

    近期刷Java面试题刷到了“如何使用Redis实现消息队列”,解答如下: 一般使用 list 结构作为队列, rpush 生产消息, lpop 消费消息。当 lpop 没有消息的时候,要适当sleep 一会再重试。若不使用sleep,则可以用指令blpop(该指令在没有消息的时候,它会阻塞住直到消息到来) rp

    2024年02月21日
    浏览(33)
  • Redis如何保证缓存和数据库一致性?

    现在我们在面向增删改查开发时,数据库数据量大时或者对响应要求较快,我们就需要用到Redis来拿取数据。 Redis:是一种高性能的内存数据库,它将数据以键值对的形式存储在内存中,具有读写速度快、支持多种数据类型、原子性操作、丰富的特性等优势。 优势: 性能极高

    2024年01月16日
    浏览(52)
  • Redis---数据库和缓存如何保证一致性?

    用「读 + 写」请求的并发的场景来分析: 假如某个用户数据在缓存中不存在,请求 A 读取数据时从数据库中查询到年龄为 20,在未写入缓存中时另一个请求 B 更新数据。它更新数据库中的年龄为 21,并且清空缓存。这时请求 A 把从数据库中读到的年龄为 20 的数据写入到缓存

    2024年01月24日
    浏览(40)
  • Redis如何保障缓存与数据库的数据一致性问题?

    目录 一.最经典的数据库加缓存的双写双删模式 二. 高并发场景下的缓存+数据库双写不一致问题分析与解决方案设计 三、上面高并发的场景下,该解决方案要注意的问题 1.1 Cache Aside Pattern概念以及读写逻辑 (1)读的时候,先读缓存,缓存没有的话,那么就读数据库,然后取

    2023年04月21日
    浏览(33)
  • redis的缓存更新策略以及如何保证redis与数据库的数据一致性

    redis的缓存更新策略有这么几种: 1、由应用直接和redis以及数据库相连接:         查询数据时,应用去redis中查询,查不到的话再由应用去数据库中查询,并将查询结果放在redis;         更新数据时,由应用去触发redis数据的删除以及数据库的update。 2、应用只跟redi

    2024年02月13日
    浏览(37)
  • 数据库缓存服务——NoSQL之Redis配置与优化

    目录 一、缓存概念 1.1 系统缓存 1.2 缓存保存位置及分层结构 1.2.1 DNS缓存 1.2.2 应用层缓存 1.2.3 数据层缓存 1.2.4 硬件缓存 二、关系型数据库与非关系型数据库 2.1 关系型数据库 2.2 非关系型数据库 2.3 关系型数据库和非关系型数据库区别: 2.4 非关系型数据库产生背景 2.5 总结

    2024年02月15日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包