Spring Boot集成Spring Session Redis遇主从Pub/Sub不支持问题求助
解决Spring Session Data Redis主从架构下Pub/Sub连接报错问题
首先咱们理清问题根源:你使用的RedisStaticMasterReplicaConfiguration确实不支持Pub/Sub功能,正如AWS文档提到的,主从架构下Redis本身不会跨节点传播Pub/Sub消息;而Spring Session需要通过Pub/Sub监听会话过期、删除、创建的事件通知,所以当它尝试用主从连接工厂订阅频道时,就会抛出Pub/Sub connections not supported with Master/Replica configurations的错误。
至于为什么会话保存和查询功能正常?因为这部分走的是主从读写分离逻辑(写操作走主节点、读操作优先从节点),和Pub/Sub是完全独立的模块,所以不影响核心会话功能,只是日志会持续打印报错信息。
下面给你两种可行的解决方案,你可以根据自身需求选择:
方案一:为Pub/Sub单独配置主节点连接工厂
如果你的应用需要监听会话事件(比如处理会话过期后的清理逻辑),可以创建两个独立的Redis连接工厂:一个用于普通会话读写(保留现有主从配置),另一个专门用于Pub/Sub(仅连接主节点)。
具体步骤:
- 定义主从连接工厂(用于会话读写):
@Bean("sessionRedisConnectionFactory") public LettuceConnectionFactory sessionLettuceConnectionFactory() { RedisStaticMasterReplicaConfiguration configuration = new RedisStaticMasterReplicaConfiguration( MASTER_HOST, MASTER_PORT); configuration.addNode(SLAVE_HOST, SLAVE_PORT); LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder() .readFrom(ReadFrom.REPLICA_PREFERRED) .build(); return new LettuceConnectionFactory(configuration, clientConfig); }
- 定义仅连接主节点的Pub/Sub专用连接工厂:
@Bean("pubSubRedisConnectionFactory") public LettuceConnectionFactory pubSubLettuceConnectionFactory() { RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration(MASTER_HOST, MASTER_PORT); // 如果你的Redis有密码认证,添加下面一行 // configuration.setPassword(RedisPassword.of("你的Redis密码")); return new LettuceConnectionFactory(configuration); }
- 修改
RedisMessageListenerContainer,指定使用Pub/Sub专用连接工厂:
@Bean public RedisMessageListenerContainer springSessionRedisMessageListenerContainer( RedisIndexedSessionRepository sessionRepository, @Qualifier("pubSubRedisConnectionFactory") RedisConnectionFactory pubSubConnectionFactory) { RedisMessageListenerContainer container = new RedisMessageListenerContainer(); container.setConnectionFactory(pubSubConnectionFactory); // 替换为专用连接工厂 if (this.redisTaskExecutor != null) { container.setTaskExecutor(this.redisTaskExecutor); } if (this.redisSubscriptionExecutor != null) { container.setSubscriptionExecutor(this.redisSubscriptionExecutor); } container.addMessageListener(sessionRepository, Arrays.asList( new ChannelTopic(sessionRepository.getSessionDeletedChannel()), new ChannelTopic(sessionRepository.getSessionExpiredChannel()) )); container.addMessageListener(sessionRepository, Collections.singletonList( new PatternTopic(sessionRepository.getSessionCreatedChannelPrefix() + "*") )); return container; }
- 确保会话仓库使用主从连接工厂:
通过@EnableRedisHttpSession指定连接工厂的引用:
@EnableRedisHttpSession(connectionFactoryRef = "sessionRedisConnectionFactory") public class SpringSessionConfig { // 上面的Bean定义放在这里 }
方案二:禁用Spring Session的Keyspace通知(简单但放弃事件监听)
如果你的应用不需要监听会话过期、删除等事件,直接禁用Keyspace通知即可,这样Spring Session就不会尝试创建Pub/Sub连接,报错自然消失。
具体实现:
自定义RedisIndexedSessionRepository并关闭Keyspace通知:
@Bean public RedisIndexedSessionRepository redisIndexedSessionRepository( @Qualifier("sessionRedisConnectionFactory") RedisConnectionFactory connectionFactory) { RedisIndexedSessionRepository repository = new RedisIndexedSessionRepository(connectionFactory); repository.setEnableKeyspaceNotifications(false); return repository; }
这样配置后,Spring Session不会再尝试订阅Redis频道,日志报错会消失,同时保留正常的会话读写功能。
内容的提问来源于stack exchange,提问作者yc.park
相关产品推荐
相关产品推荐

