You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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(仅连接主节点)。

具体步骤:

  1. 定义主从连接工厂(用于会话读写):
@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);
}
  1. 定义仅连接主节点的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);
}
  1. 修改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;
}
  1. 确保会话仓库使用主从连接工厂:
    通过@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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 14:02:56