springboot 整合Redis实现发布/订阅功能
Redis发布/订阅模式简介
-
什么是发布/订阅?
发布/订阅是一种消息通信模式,其中发送者(发布者)发布消息,多个接收者(订阅者)订阅并接收消息。发布者和订阅者之间没有直接联系,消息由消息中间件(如Redis)传递。
-
Redis 发布/定义的优点
- 高性能:Redis作为内存存储,具备极高的读写性能,能够快速处理发布和订阅消息
- 简单易用:Redis的发布/订阅接口简单,易于集成和使用
- 实时性强:发布的消息会立即传递给所有订阅者,具备高实时性
-
Redis发布/订阅的缺点
- 消息丢失:由于Redis是内存存储,如果Redis实例宕机,未处理的消息可能会丢失
- 无法持久化:Redis的发布/订阅模式不支持消息持久化,无法存储和检索历史消息
- 订阅者不可控:发布者无法控制订阅者的数量和状态,无法保证所有订阅者都能收到消息
- 无确认机制:发布者无法确认消息是否被订阅者接收和处理
正如上述中Redis的缺点,Redis 的发布订阅功能并不可靠,如果我们需要保证消息的可靠性、包括确认、重试等要求,我们还是要选择MQ实现发布订阅
Redis的发布/订阅应用场景:
对于消息处理可靠性要求不强
消息无需持久化
消费能力无需通过增加消费方进行增强
架构简单 中小型系统不希望应用过多中间件 -
redis 发布订阅命令
命令 描述 Redis Unsubscribe 命令 指退订给定的频道 Redis Subscribe 命令 订阅给定的一个或多个频道的信息 Redis Pubsub 命令 查看订阅与发布系统状态 Redis Punsubscribe 命令 退订所有给定模式的频道 Redis Publish 命令 将信息发送到指定的频道 Redis Psubscribe 命令 订阅一个或多个符合给定模式的频道
演示
-
添加依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency>
-
配置Redis
spring: #redis redis: # 地址 host: 127.0.0.1 # 端口,默认为6379 port: 6379 # 数据库索引 database: 0 # 密码 password: # 连接超时时间 timeout: 10s lettuce: pool: # 连接池中的最小空闲连接 min-idle: 5 # 连接池中的最大空闲连接 max-idle: 8 # 连接池的最大数据库连接数 max-active: 20 # #连接池最大阻塞等待时间(使用负值表示没有限制) max-wait: -1ms
-
创建Redis配置类
package com.example.demo.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.listener.PatternTopic; import org.springframework.data.redis.listener.RedisMessageListenerContainer; import org.springframework.data.redis.listener.adapter.MessageListenerAdapter; @Configuration public class RedisConfig { @Bean RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory, MessageListenerAdapter listenerAdapter) { //设置连接工厂RedisConnectionFactory RedisMessageListenerContainer container = new RedisMessageListenerContainer(); container.setConnectionFactory(connectionFactory); // 订阅订阅名称 micro 的通道 container.addMessageListener(listenerAdapter, new ChannelTopic("micro")); // 订阅名称 'test-' 开头的全部通道 container.addMessageListener(listenerAdapter, new PatternTopic("test-*")); return container; } @Bean public MessageListenerAdapter listenerAdapter(MessageReceiver receiver) { return new MessageListenerAdapter(receiver); } }
-
创建消息接收/发布类
创建一个消息发布类,用于发布消息
import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; @Component public class MessagePublisher { private final StringRedisTemplate redisTemplate; public MessagePublisher(StringRedisTemplate redisTemplate) { this.redisTemplate = redisTemplate; } public void publish(String channel, String message) { redisTemplate.convertAndSend(channel, message); } }
创建一个消息接收类,用于处理接收到的消息
import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.connection.Message; import org.springframework.data.redis.connection.MessageListener; import org.springframework.stereotype.Component; @Component @Slf4j public class MessageReceiver implements MessageListener { @Override public void onMessage(Message message, byte[] pattern) { //消息通道 String channel = new String(message.getChannel()); //消息内容 String messageBody = new String(message.getBody()); // 消息订阅的匹配规则,如 new PatternTopic("test-*") 中的 test-* String msgPattern = new String(pattern); log.info("接收消息: channel={} body={} pattern={} ", channel, messageBody, msgPattern); // 这里处理接收的消息 } }
-
编写controller测试
创建一个简单的控制,来测试发布订阅功能
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/api") public class PublisherController { @Autowired private MessagePublisher messagePublisher; @GetMapping("/publish") public String publish(@RequestParam String message) { messagePublisher.publish("micro", message); return "Message published: " + message; } }
通过本文,我们详细介绍了如何在 Spring Boot 中整合 Redis 实现发布/订阅功能,并提供了详细的代码示例。Redis 发布/订阅模式以其高性能和简单易用的特点,在实时消息传递场景中有着广泛的应用,但同时就如文中提到的小伙伴们也需要注意其消息丢失和无法持久化等缺点,需要根据实际业务需求选择。