基于Redis實(shí)現(xiàn)訂閱發(fā)布功能
背景
業(yè)務(wù)發(fā)展過程中,希望做到異步解耦,但是又不想引入MQ中間件,在中小型服務(wù)中,就可以考慮使用redis自帶的訂閱發(fā)布來解決這個問題。使用 Redis 實(shí)現(xiàn)消息的訂閱和發(fā)布時,可以通過 Spring Boot 集成 Redis 來方便地實(shí)現(xiàn)。
引入redis依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>配置 Redis
在 application.properties 文件中,添加 Redis 配置:
spring.redis.host=localhost spring.redis.port=6379
編寫代碼
Redis 配置
創(chuàng)建一個配置類來配置 Redis 的連接工廠和監(jiān)聽器:
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.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.data.redis.core.StringRedisTemplate;
@Configuration
public class RedisConfig {
@Bean
public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.addMessageListener(listenerAdapter, topic());
return container;
}
@Bean
public MessageListenerAdapter listenerAdapter(RedisMessageSubscriber subscriber) {
return new MessageListenerAdapter(subscriber, "onMessage");
}
@Bean
public ChannelTopic topic() {
return new ChannelTopic("messageQueue");
}
@Bean
public StringRedisTemplate template(RedisConnectionFactory connectionFactory) {
return new StringRedisTemplate(connectionFactory);
}
}創(chuàng)建消息訂閱者
編寫一個類來處理收到的消息:
import org.springframework.stereotype.Service;
@Service
public class RedisMessageSubscriber {
public void onMessage(String message, String channel) {
System.out.println("Received message: " + message + " from channel: " + channel);
}
}創(chuàng)建消息發(fā)布者
編寫一個發(fā)布者通過 Redis 模板發(fā)送消息:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MessagePublisher {
@Autowired
private StringRedisTemplate template;
@Autowired
private ChannelTopic topic;
@GetMapping("/publish")
public String publish(@RequestParam String message) {
template.convertAndSend(topic.getTopic(), message);
return "Message published: " + message;
}
}如果需要監(jiān)聽多個channel,可以通過RedisConfig中添加新的消息適配器。
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.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.data.redis.core.StringRedisTemplate;
@Configuration
public class RedisConfig {
@Bean
public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter1,
MessageListenerAdapter listenerAdapter2) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.addMessageListener(listenerAdapter1, topic1());
container.addMessageListener(listenerAdapter2, topic2());
return container;
}
@Bean
public MessageListenerAdapter listenerAdapter1(RedisMessageSubscriber subscriber) {
return new MessageListenerAdapter(subscriber, "onMessage");
}
@Bean
public MessageListenerAdapter listenerAdapter2(RedisMessageSubscriber subscriber) {
return new MessageListenerAdapter(subscriber, "onMessage");
}
@Bean
public ChannelTopic topic1() {
return new ChannelTopic("channelOne");
}
@Bean
public ChannelTopic topic2() {
return new ChannelTopic("channelTwo");
}
@Bean
public StringRedisTemplate template(RedisConnectionFactory connectionFactory) {
return new StringRedisTemplate(connectionFactory);
}
}同時RedisMessageSubscriber 也可以書寫多個來區(qū)分不同的業(yè)務(wù)場景下不同業(yè)務(wù)處理。
到此這篇關(guān)于Redis分布式系統(tǒng)的原理與實(shí)操的文章就介紹到這了,更多相關(guān)Redis分布式系統(tǒng)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Java使用Redis實(shí)現(xiàn)消息訂閱/發(fā)布的幾種方式
- springboot集成redis實(shí)現(xiàn)消息的訂閱與發(fā)布
- Springboot使用redisson?+?自定義注解實(shí)現(xiàn)消息的發(fā)布訂閱(解決方案)
- redis發(fā)布訂閱模式的實(shí)現(xiàn)
- 探索Golang?Redis實(shí)現(xiàn)發(fā)布訂閱功能實(shí)例
- springboot+redis自定義注解實(shí)現(xiàn)發(fā)布訂閱的實(shí)現(xiàn)代碼
- Springboot整合redis實(shí)現(xiàn)發(fā)布訂閱功能介紹步驟
- Docker?Compose+Nestjs構(gòu)建Dapr?Redis發(fā)布訂閱分布式應(yīng)用
- redis實(shí)現(xiàn)隊(duì)列的阻塞、延時、發(fā)布和訂閱
相關(guān)文章
redis配置standAlone版的jedisPool示例
這篇文章主要為大家介紹了redis配置standAlone版的jedisPool示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07
redis不能訪問本機(jī)真實(shí)ip地址的解決方案
這篇文章主要介紹了redis不能訪問本機(jī)真實(shí)ip地址的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07
從一個小需求感受Redis的獨(dú)特魅力(需求設(shè)計(jì))
Redis在實(shí)際應(yīng)用中使用的非常廣泛,本篇文章就從一個簡單的需求說起,為你講述一個需求是如何從頭到尾開始做的,又是如何一步步完善的2019-12-12
Redis集群的節(jié)點(diǎn)之間通信的實(shí)現(xiàn)
Redis集群的節(jié)點(diǎn)之間通過Gossip協(xié)議進(jìn)行通信,在Redis集群中,Gossip協(xié)議用于節(jié)點(diǎn)之間的狀態(tài)同步和故障檢測,下面就來詳細(xì)的介紹一下Redis集群節(jié)點(diǎn)通信,感興趣的可以了解一下2025-09-09
Redis+Caffeine實(shí)現(xiàn)雙層緩存的策略對比與詳細(xì)指南
在高并發(fā)場景下,緩存是提升系統(tǒng)性能和并發(fā)處理能力的關(guān)鍵手段,本文將基于Spring?Boot,從方案對比分析出發(fā),深入探討Redis、本地Caffeine與雙層緩存的實(shí)現(xiàn)與性能差異,并給出選型建議與實(shí)際效果驗(yàn)證2025-07-07
Redis內(nèi)存碎片率調(diào)優(yōu)處理方式
Redis集群因內(nèi)存碎片率超過1.5觸發(fā)告警,分析發(fā)現(xiàn)內(nèi)因與外因?qū)е聝?nèi)存碎片,內(nèi)因?yàn)椴僮飨到y(tǒng)內(nèi)存分配機(jī)制,外因?yàn)镽edis操作特性,使用Redis內(nèi)置內(nèi)存碎片清理機(jī)制可有效降低碎片率,但需注意可能影響性能,建議使用MEMORY命令診斷內(nèi)存使用情況,合理配置參數(shù)以優(yōu)化性能2024-09-09
Redis集群中節(jié)點(diǎn)更換IP后實(shí)現(xiàn)恢復(fù)集群且保留數(shù)據(jù)
本文介紹了如何在Redis集群中更改節(jié)點(diǎn)IP地址,并通過修改cluster-config-file文件中的IP地址并重啟所有節(jié)點(diǎn),成功恢復(fù)集群2026-03-03

