33.1从零开始学springboot-一文读懂消息队列-发布订阅(附redis实现)

微服务学习路线 任务① 熟悉掌握Docker技术 114-115 观看四期114-115节 什么是Docker? Docker的镜像、仓库、容器的概念 如何在Docker上安装Redis Docker镜像如何加速? 如何将自己的微服务项目部署到Docker中 Docker的常用命令有那些 Docker中安装的软件如何修改配置呢? 使用docker安装mysql、nginx 任务②学习SpringBoot框架 27... 阅读详情

前言

实际生产中,我们经常会碰到这样的场景: 业务方触发了某些预料之中的bug,(比如项目中调用了第三方的服务,但是第三方的服务出问题导致无法访问,这类错,我们往往不会直接提示用户,而是选择屏蔽此类错误,写入错误日志),我们处理此类bug往往需要去生产导出日志记录,然后排查,最后找到第三方服务的提供者去解决问题.

那么,与其等“被动”业务反馈,能不能让这类问题“主动”推送给开发呢? 我们能不做个“错误预警”的服务.

消息推送技术,即是解决这类问题的良方.

消息队列

消息队列,一般我们会简称它为MQ(Message Queue),再介绍消息队列前,我们还是先简单解释一下队列这种数据结构

队列

队列是一种先进先出的数据结构

队列.png

如图,数据从队尾(右)进,从队头(左)出.

消息队列

消息队列可以简单的理解为:把要传输的数据放在队列中。
当我们需要使用消息的时候可以取出数据供自己使用。

消息队列的两种场景

从以上概念中我们不难看出有两个角色对队列至关重要,一个是放数据的,一个是取数据的.
当然,这两个角色都有是有规范的名字的,同时,消息队列有两种场景,在这两种不同的场景里,这两个角色名字是不同的:

  • 生产者消费者模式
    • 生产者: 放数据进队列
    • 消费者: 从队列取数据
  • 发布者订阅者模式
    • 发布者: 放数据进队列
    • 订阅者: 从队列取数据

场景区别

  • 生产者消费者模式(一对一)
生产者将生产消息放到队列里,多个消费者同时监听队列,谁先抢到消息谁就
会从队列中取走消息;即对于每个消息只能被最多一个消费者拥有。

包括三个角色:

  1. 消息队列
  2. 发送者(生产者)
  3. 接收者(消费者)

消息队列-生产消费.png

生产消费者模式特点:

  1. 每个消息只有一个接收者(Consumer)(即一旦被消费,消息就不再在消息队列中)
  2. 发送者和接收者间没有依赖性,发送者发送消息之后,不管有没有接收者在运行,都不会影响到发送者下次发送消息
  3. 接收者在成功接收消息之后需向队列应答成功,以便消息队列删除当前接收的消息
  • 发布者订阅者模式(一对多)
发布者将生产消息放到队列里,多个监听队列的消费者都会收到同一份消息;
即正常情况下每个消费者收到的消息应该都是一样的。

包括三个角色:

  1. 角色主题(Topic)
  2. 发布者(Publisher)
  3. 订阅者(Subscriber)

消息队列-发布订阅.png

发布订阅模式特点:

  1. 每个消息可以有多个订阅者
  2. 发布者和订阅者之间有时间上的依赖性。针对某个主题(Topic)的订阅者,它必须创建一个订阅者之后,才能消费发布者的消息
  3. 为了消费消息,订阅者需要提前订阅该角色主题,并保持在线运行

消息队列解决的问题

消息队列为了实现实现高性能,高可用,可伸缩和最终一致性架构,主要可以解决如下问题:

  • 异步处理
多应用对消息队列中同一消息进行处理,应用间并发处理消息,相比串行处理,减少处理时间

场景举例:
用户注册后,需要发注册邮件和注册短信.

传统的做法有两种

  1. 串行方式
将注册信息写入数据库成功后,发送注册邮件,再发送注册短信。
以上三个任务全部完成后,返回给客户端

串行.png

  1. 并行方式
将注册信息写入数据库成功后,发送注册邮件的同时,发送注册短信。以上三个任务完成后,返回给客户端。与串行的差别是,并行的方式可以提高处理的时间

并行.png

  1. 消息队列异步处理方式
将注册信息写入数据库,再将任务写入消息队列后,立即返回成功给客户端,
则总的响应时间依赖于写入消息队列的时间,
而写入消息队列的时间本身是可以很快的,基本可以忽略不计,
因此总的处理时间相比串行提高了2倍,相比并行提高了一倍

消息队列-异步.png

  • 应用耦合
多应用间通过消息队列对同一消息进行处理,避免调用接口失败导致整个过程失败

场景举例:
银行身份证人脸识别系统,用户上传身份证图片,人脸识别系统会对该图片进行人脸识别.

一般的做法是:
服务器接收到图片后,图片上传系统立即调用人脸识别系统,调用完成后再返回成功
应用耦合.png

该方法有如下缺点:

  1. 人脸识别系统被调失败,导致图片上传失败
  2. 延迟高,需要人脸识别系统处理完成后,再返回给客户端,即使用户并不需要立即知道结果
  3. 图片上传系统与人脸识别系统之间互相调用,需要做耦合

为了解决以上缺点,我们采用消息队列解决应用间的耦合问题:

消息队列的做法:
用户上传图片后,图片上传系统将图片信息顺序写入消息队列,直接返回成功;
人脸识别系统则定时从消息队列中取数据,完成对图片的识别。

图片上传系统并不需要关心人脸识别系统是否对这些图片信息的处理、以及何时对这些图片信息进行处理。事实上,由于用户并不需要立即知道人脸识别结果,人脸识别系统可以选择不同的调度策略,按照闲时、忙时、正常时间,对队列中的图片信息进行处理。

消息队列-应用耦合.png

  • 限流削峰
广泛应用于秒杀或抢购活动中,避免流量过大导致应用系统挂掉的情况

场景举例:
电商秒杀活动,常见的形式是数量极少的热门商品让大量的用户抢购
传统的做法是用户直接请求业务系统,但往往因为并发用户过大,或导致业务系统崩溃,或着出现超卖等等现象.

采用消息队列后,系统可以从消息队列中取数据,相当于消息队列做了一次缓冲
消息队列-限流削峰.png

采用消息队列处理秒杀有如下优点:

  1. 请求先入消息队列,而不是由业务处理系统直接处理,做了一次缓冲,极大地减少了业务处理系统的压力;
  2. 队列长度可以做限制,事实上,秒杀时,后入队列的用户无法秒杀到商品,这些请求可以直接被抛弃,返回活动已结束或商品已售完信息;
  • 消息驱动的系统
    场景举例:
    用户新上传了一批照片,人脸识别系统需要对这个用户的所有照片进行聚类,聚类完成后由对账系统重新生成用户的人脸索引(加快查询)。这三个子系统间由消息队列连接起来,前一个阶段的处理结果放入队列中,后一个阶段从队列中获取消息继续处理.

消息队列-消息驱动.png

使用消息队列有如下优点:

  1. 避免了直接调用下一个系统导致当前系统失败;
  2. 每个子系统对于消息的处理方式可以更为灵活,可以选择收到消息时就处理,可以选择定时处理,也可以划分时间段按不同处理速度处理;

Redis实现发布订阅模式

消息队列是分布式系统中重要的组件,使用消息队列主要是为了通过异步处理提高系统性能和削峰、降低系统耦合性。目前使用较多的消息队列有ActiveMQ,RabbitMQ,Kafka,RocketMQ,这些消息中间件我们暂时不讲,本章,我们使用最为简单的方式REDIS来实现消息队列的发布订阅模式.

Redis

Redis从2.X版本开始,就支持一种基于非持久化消息的、使用发布/订阅模式实现的事件通知机制.
所谓基于非连接保持,是因为一旦消息订阅者由于各种异常情况而被迫断开连接,在其重新连接后,
其离线期间的事件是无法被重新通知的(一些Redis资料中也称为即发即弃).
而其使用的发布/订阅模式,意味着其机制并不是由订阅者周期性的从Redis服务拉取事件通知,
而是由Redis服务主动推送事件通知到符合条件的若干订阅者.

通俗的来讲,Redis实现的发布订阅模式有如下注意点:

  • 基于Redis服务主动推送消息,而非订阅者循环拉取.
  • 消息即发即丢(就是消息一发布,就丢失了,不会保存)

Springboot+Redis实现

  • 引入redis依赖
    pom.xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
  • application.yml
spring:
  redis:
    port: 6379
    database: 0
    host: 127.0.0.1
    password: 123456
    jedis:
      pool:
        max-active: 8
        max-wait: -1ms
        max-idle: 8
        min-idle: 0
    timeout: 5000ms
server:
  port: 9999
  • redis配置类
package com.mrcoder.sbredispubsub.config.redis;


import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mrcoder.sbredispubsub.model.MessageSubscriber;
import com.mrcoder.sbredispubsub.utils.RedisPubSubUtil;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;


/**
 * @Description: Redis配置类
 */
@Configuration
@ConditionalOnClass({RedisTemplate.class})
public class RedisConfig {

    /**
     * Redis操作模板配置
     *
     * @param connectionFactory
     * @return
     */
    @Bean
    public RedisTemplate<?, ?> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<byte[], byte[]> template = new RedisTemplate<byte[], byte[]>();
        template.setConnectionFactory(connectionFactory);
        template.setKeySerializer(new StringRedisSerializer());
        template.afterPropertiesSet();
        return template;
    }

    @Bean
    public RedisTemplate<?, ?> redisTemplate(RedisConnectionFactory connectionFactory, Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer) {
        RedisTemplate<byte[], byte[]> template = new RedisTemplate<byte[], byte[]>();
        template.setConnectionFactory(connectionFactory);
        // 设置key/hashkey序列化
        RedisSerializer<String> stringSerializer = new StringRedisSerializer();
        template.setKeySerializer(stringSerializer);
        template.setHashKeySerializer(stringSerializer);

        // 设置值序列化
        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();

        template.setKeySerializer(new StringRedisSerializer());
        template.afterPropertiesSet();

        return template;
    }

    @Bean
    public RedisPubSubUtil redisPubSubUtil(@Qualifier("redisTemplate") RedisTemplate<String, Object> redis) {
        return new RedisPubSubUtil(redis);
    }

    /**
     * 序列化定制
     *
     * @return
     */
    @Bean
    public Jackson2JsonRedisSerializer<Object> jackson2JsonSerializer() {
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(
                Object.class);

        // 初始化objectmapper
        ObjectMapper mapper = new ObjectMapper();
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(mapper);
        return jackson2JsonRedisSerializer;
    }

    /**
     * 将订阅器绑定到容器
     *
     * @param connectionFactory
     * @param listener
     * @return
     */
    @Bean
    public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory, MessageListenerAdapter listener) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        container.addMessageListener(listener, new PatternTopic("redis.pubsub.*"));
        return container;
    }

    /**
     * 消息监听器,使用MessageAdapter可实现自动化解码及方法代理
     *
     * @param jackson2JsonRedisSerializer
     * @param subscriber
     * @return
     */
    @Bean
    public MessageListenerAdapter listener(Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer, MessageSubscriber subscriber) {
        MessageListenerAdapter adapter = new MessageListenerAdapter(subscriber, "onMessage");
        adapter.setSerializer(jackson2JsonRedisSerializer);
        adapter.afterPropertiesSet();
        return adapter;
    }

}
  • 定义消息实体类
package com.mrcoder.sbredispubsub.model;

import lombok.Data;

import java.util.Date;

@Data
public class SimpleMessage {
    private String publisher;
    private String content;
    private Date createTime;
}
  • 消息发布类
package com.mrcoder.sbredispubsub.utils;

import com.mrcoder.sbredispubsub.model.SimpleMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.ChannelTopic;

import java.util.Date;

/**
 * @Description: Redis发布订阅
 */
public class RedisPubSubUtil {

    private static final Logger logger = LoggerFactory.getLogger(RedisPubSubUtil.class);

    private RedisTemplate<String, Object> redisTemplate;

    public RedisPubSubUtil(RedisTemplate<String, Object> redisTemplate) {
        super();
        this.redisTemplate = redisTemplate;
    }

    public void publish(String publisher, String content) {
        logger.info("message send {} by {}", content, publisher);
        SimpleMessage simpleMessage = new SimpleMessage();
        simpleMessage.setContent(content);
        simpleMessage.setPublisher(publisher);
        simpleMessage.setCreateTime(new Date());
        ChannelTopic channelTopic = new ChannelTopic("redis.pubsub.msg");
        redisTemplate.convertAndSend(channelTopic.getTopic(), simpleMessage);
    }
}

  • 定义订阅者实体类
package com.mrcoder.sbredispubsub.model;

import com.mrcoder.sbredispubsub.utils.FastJsonUtil;
import org.springframework.stereotype.Component;

/**
 * @Description: 消息订阅类
 */
@Component
public class MessageSubscriber {
    public void onMessage(SimpleMessage simpleMessage, String pattern) {
        logger.info("topic {} received {}", pattern, FastJsonUtil.javaToJsonSnakeCase(simpleMessage));
    }
}

  • 控制器
package com.mrcoder.sbredispubsub.controller;
import com.mrcoder.sbredispubsub.utils.RedisPubSubUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.*;

@CrossOrigin
@RestController
public class RedisPubSubController {

    @Autowired
    private RedisPubSubUtil redisPubSubUtil;

    @GetMapping("redisPubSub")
    public void redisPubSub(){
        redisPubSubUtil.publish("echo", "testMessage"));
    }
}

改造

以上已经实现了基于redis简单的发布订阅了.

那么,在此之上我们多做一点来更好的理解发布订阅这块的内容.

  • 我们实现推送内容到企业微信
  • 我们实现读取文件的内容来推送(可用于版本新功能的发布推送)

项目地址:

https://github.com/MrCoderStack/SpringBootDemo/tree/master/sb-redis-pubsub

请关注我的订阅号

订阅号.png

SpringBoot编程基础教程:消息队列和异步处理 作者:禅与计算机程序设计艺术 1.背景介绍 在分布式系统中,消息队列(Message Queue)主要用于解决应用间通信的问题,它可以将生产者端产生的数据或者任务临时存放在消息队列中,等待消费者端调用,从而降低应用程序之间的耦合度。同时,消息队列还可以实现应用解耦、削峰填谷和流量削平等作用。Spri 阅读详情

相关推荐

Java学习路线超强总结(2020最新版)

我一直觉得,一个优秀的程序员,平时应该具备记录问题解决方案和总结知识点的习惯。 不管你是新手还是入行多年,Java的知识体系都是通用的,今天我替大家整理了一份最新的Java学习路线,包含了作为一个Java工程师在开发工作学习中需要用到或者可能用到的绝大部分知识。如有变化会随时更新。 2020最新Java学习路线 一、JavaSE 1.Java环境搭建 2.Java核心语法 3.面向对象 4.数组&算法 5.异常处理 6.常用类 7.集合&泛型 8.集合&数据结构 9.线程&通

Happy Simon 1111

消息队列简单入门:springboot

1.明白流程 exchange通过routingKey(一个规则)绑定着queue 。。。。。。。。。。。。。。。。。。。。。。。。。。。 用户指定:交换机,routingKey,消息。然后就可以把消息传给queue了。 开始:1.创建交换机 2。创建队列 3.通过routingKey绑定exchange和queue 这里routingKey注意一下:#是值:类似于order.abc...

weixin_44841849的博客 288

解决西门子Step 7 basic 找不到许可证问题

你在使用博图软件是否遇到过Step 7 basic 找不到许可证的问题呢!不言怕,今天我就来告诉你该如何处理吧!看步骤: 1.删除原授权的License: 打开Automation License Manager应用,然后我们可以发现仅有的License Key前面有一个时钟,说明它已经过期不可用,我们就要去寻求新的Key. 打开“我的电脑”,选择C盘,点击上方查看 点击选项–>查看 然...

让技术没有门槛 14万+

Spring Boot 消息队列 ActiveMQ 入门

1. 概述 如果胖友还没了解过分布式消息队列ActiveMQ,建议先阅读下艿艿写的《芋道 ActiveMQ 极简入门》文章。虽然这篇文章标题是安装部署,实际可以理解成《一文带你快速入门 ActiveMQ》,哈哈哈。 考虑这是 ActiveMQ 如何在 Spring Boot 整合与使用的文章,所以还是简单介绍下 ActiveMQ 是什么? FROM《JMS 消息服务器 ActiveMQ》 ActiveMQ 是 Apache 出品,最流行的,能力强劲的开源消息总线。 ActiveMQ 是...

weixin_42073629的博客 513

Vitis Model Composer闪退?手把手教你用命令行启动Vivado 2021后的System Generator

本文详细解析了Vitis Model Composer闪退问题的根本原因,并提供了命令行启动Vivado 2021后System Generator的完整解决方案。从环境变量配置、组件缺失排查到权限问题处理,手把手教你通过命令行深度排错,并分享高级自动化脚本和系统优化技巧,帮助开发者高效使用Vitis Model Composer与System Generator进行HDL开发。

weixin_26905487的博客 347

高速串行信号仿真避坑指南:为什么你的SIwave Xnet设置了却不出结果?

本文深入解析SIwave中Xnet功能在高速串行信号仿真中的常见问题,包括模型缺失、网络不完整和端口设置错误等关键误区。通过详细的电路元件模型验证、网络完整性检查及端口配置指南,帮助工程师有效解决仿真不出结果的问题,提升信号完整性分析效率。

weixin_29218963的博客 251

Spring Boot学习 RabbitMQ 消息队列 (一) 消息队列 基本概念 web端操作

Spring Boot学习 RabbitMQ 消息队列 基本概念 web端操作 Spring Boot学习 RabbitMQ 消息队列 (二) SpringBoot整合 设置消息确认机制,可靠抵达 ConfirmCallbac ReturnCallback 1. 基本概念 2.web端操作rabbitmq 2.1 添加交换机Exchange 2.2 创建队列 2.3 设置绑定关系 点击交换机列表进入交换机设置: 绑定成功: ...

NeverGiveUp 331

逆向工程实战:如何一步步破解京东APP的sign签名算法(附Frida脚本)

本文详细解析了京东APP的sign签名算法逆向工程实战,通过Frida脚本动态分析Java层和Native层的多层签名机制,揭示商业应用的加密协议设计。文章提供了完整的逆向工程方法论与工具链,帮助开发者深入理解移动应用安全防护体系,提升安全防御能力。

weixin_28622215的博客 915

redis 序列化对象问题

redis 序列化背景追根溯源RedisTemplateRedisSerializerJdkSerializationRedisSerializer总结 背景 最近在使用redis的发布订阅模式时,订阅类接收到的是字符串,习惯性的用JSON将字符串转成对象,结果就是各种报错,刚开始想不通,通过redis可视化工具看到的明明是JSON,把结果复制出来也是能通过JSON测试的,为什么通过发布订阅获取到的结果就不能转成对象呢? 追根溯源 为什么通过下面代码能正确获取到数据呢? @Autowired private

做一个有思想的技术人 4131

MacBook上玩转国民技术N32G430:从零搭建ARM开发环境(VSCode + pyOCD)

本文详细介绍了在MacBook上搭建国民技术N32G430的ARM开发环境,涵盖VSCode配置、pyOCD调试及一键编译烧录全流程。通过Homebrew安装工具链、配置Python环境及VSCode插件,开发者可在MacOS高效开发嵌入式应用,特别适合国产芯片N32G430的开发者参考。

weixin_30614109的博客 436

【Zephyr 系列 29】低功耗调试指南:电流测量、系统睡眠与功耗分析

Zephyr低功耗调试指南(150字摘要) 针对物联网设备续航需求,本文解析Zephyr低功耗调试方法:1️⃣ 机制:启用PM子系统和tickless idle,配置睡眠策略;2️⃣ 测量:推荐功耗分析仪捕捉μA级电流波动;3️⃣ 优化:管理唤醒源(如GPIO/RTC)、调整BLE广播/连接参数,挂起闲置外设;4️⃣ 分析:建立功耗文档,对比不同模式电流(如待机0.6mA vs广播3.2mA)。强调低功耗需系统性设计,初期即需纳入测试流程。下期将探讨Zephyr OTA升级实现。

hemoparrot的专栏 1180

33.2从零开始学springboot-一文读懂消息队列-生产消费(附redis实现)

前言 上一节我们使用Redis实现了发布订阅者模式,关于Redis实现的发布订阅模式的特点,我们也了解了 基于Redis服务主动推送消息,而非订阅者循环拉取. 消息即发即丢(就是消息一发布,就丢失了,不会保存) 那么,实际场景时,我们也会遇到如下的业务场景: 需要保存消息,按需取出 需要异步延迟处理消息,比如预定订单会先入消息队列,而后统一在一个时间集中处理 此时,发布订阅模式就不太适用了...

CTO技术的博客 373

cesium 实现经纬线绘制和经纬度标注

废话不对数直接上线效果图及代码 1.效果图 2.实现代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width,initial-scale=

一碗老面的博客 2569

【转】redis 消息队列发布订阅模式spring boot实现

 最近做项目的时候写到一个事件推送的场景。之前的实现方式是起job一直查询数据库,看看有没有最新的消息。这种方式非常的不优雅,反正我是不能忍,由于羡慕本身就依赖redis,刚好redis 也有消息队列的功能,就简单的使用redis 来实现这个消息推送。 之前参考网上的例子,发现全部来自一个地方,spring 官方的一个例子,某些打着“非官方例子”的头号,还是一样就复制了一下官方的例子,怕是自己都...

weixin_33843947的博客 152

使用 MATLAB/Simulink + Communications Toolbox + 5G Toolbox,构建一个2×2 MIMO-OFDM通信系统

本文通过Simulink+CommunicationsToolbox构建2×2 MIMO-OFDM通信系统,重点实现信道均衡滤波器(ZF与MMSE)的设计与应用。详细介绍了系统架构、建模步骤(包括信道估计、均衡器实现)和仿真场景设计,通过BER、星座图和EVM对比分析验证了MMSE均衡器在抑制噪声和信号恢复方面的优势。文章总结了MIMO均衡的核心原理与实践经验,并提出了扩展至大规模MIMO、深度学习均衡器等优化方向,为无线通信系统设计提供实用指导。

amy_mhd的博客 125

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

【SpringBoot框架篇】22.集成RocketMQ实现消息发布和订阅

集成RocketMQ实现消息的发布和订阅

皓亮君的博客 6130

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

【Redis】实战篇之黑马点评 10w字详解

比如数据库密码报错:java: 源值 8 已过时,将在未来发行版中删除原因:项目编译指定的 Java 源码版本为 8,但你当前使用的 JDK 版本较高(JDK11+、JDK17、JDK21)解决:我把1.8改为17报错:java: java.lang.ExceptionInInitializerErrorcom.sun.tools.javac.code.TypeTag :: UNKNOWN解决:修改lombok版本 修改springboot版本 修改MySQL驱动版本 报错:Loading class co

ashiho的博客 824

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

JB3-5-Redis(一)

搭建Redis容器,内存淘汰策略,过期删除策略,慢查询日志,延时双删,binlog,击穿/穿透/雪崩,大KEY,Redis数据类型,RDB,AOF,主从,哨兵,故障转移,分区集群等。

周航宇的博客 3066

2022中高级java面试题集

2022年最新中高级java面试题集

一步一步的往上爬 295

MQ 学习汇总

MQ 学习汇总 什么是MQ MQ全称为Message Queue,消息队列是应用程序和应用程序之间的通信方法。 MQ的三大主要作用 应用解耦、异步提速、流量削锋 应用解耦 系统的耦合性越高,容错性就越低,可维护性就越低。 异步提速模拟 一个下单操作耗时:20 + 300 + 300 + 300 = 920ms 用户点击完下单按钮后,需要等待920ms才能得到下单响应,太慢 用户点击完下单按钮后,只需等待25ms就能得到下单响应 (20 + 5 = 25ms)。 提升用户体验和系统吞吐量(单位时间内处理

qq_43121074的博客 232

谷粒商城Ⅱ

尚品汇

Crush_kylin的博客 1520

Springboot2 整合 Spring Data Redis 实现消息队列——发布/订阅模式

一般来说,消息队列有两种场景,一种是发布者订阅者模式,一种是生产者消费者模式。 生产者消费者模式: 就像我们用微信和好友(群聊除外)聊天一样,微信就是这个队列,我们可以和很多个好友聊天,但是每条消息只能发给一个好友。 发布者订阅者模式: 发布/订阅模型如图所示,和订阅公众号是一样的。多个消费者可以消费消息。发布者需要建立一个topic 然后消费者去订阅。 接下来用springboot2 + spring data redis 来实现来简单实现订阅者模式: spring data redis实

熙熙小学姐 1036

使用Spring Data Redis操作Redis(二)

    上一篇讲述了Spring Date Redis操作Redis的大部分主题,本篇介绍Redis的订阅和发布功能在Spring应用中的使用。   1. Redis的Pub/Sub命令  Redis的订阅和发布服务有如下图6个命令,下面分别对每个命令做简单说明。      publish: 向指定的channel(频道)发送message(消息)  subscribe:订阅指定channel,可...

weixin_33967071的博客 179

【Springboot】事件机制发布与订阅的使用实践

在Springboot中,事件机制(Event Mechanism)是一种强大的工具,**用于解耦组件之间的通信**。通过事件机制,组件可以通过发布和监听事件来进行交互。本文将介绍Springboot的事件监听机制的概念原理、其使用场景,并通过一个实践例子展示其使用过程。

分享技术,记录思考和感悟 1532

补习系列(13)-springboot redis 与发布订阅

目录 一、订阅发布 常见应用 二、Redis 与订阅发布 三、SpringBoot 与订阅发布 A. 消息模型 B. 序列化 C. 发布消息 D. 接收消息 小结 ...

weixin_34360651的博客 189

Springboot redis 入门示例

Springboot redis 入门示例 1. 概述 在快速入门 Spring Boot 整合 Redis 之前,我们先来做个简单的了解。在 Spring 的生态中,我们使用 Spring Data Redis 来实现对 Redis 的数据访问。市面上已经有 Redis、Redisson、Lettuce 等优秀的 Java Redis 工具库,为什么还要有 Spring Data Redis 呢?不要慌,我们先来看一张图:![](https://img-blog.csdnimg.cn/img_conve

大米饭 872
上一篇: 32.从零开始学springboot-一篇搞定Schedule定时任务
下一篇: 33.2从零开始学springboot-一文读懂消息队列-生产消费(附redis实现)
码哥说
博客等级 码龄8年 5645粉丝 172原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码哥说

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值