Spring Boot 3.1迁移后Redis消息监听器无法启动求助
Spring Boot 3.1 + Spring Data Redis 3.1 迁移后Redis消息监听器启动失败问题
将Spring Boot从2.6.2版本迁移至3.1版本,同步升级spring-data-redis至3.1版本后,遇到Redis消息监听器Bean无法启动的问题。
报错信息
Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Failed to start bean 'jedisMessageListenerContainer'","logger_name":"org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext"}
相关配置
Redis消息监听器容器Bean配置
@Bean RedisMessageListenerContainer jedisMessageListenerContainer(JedisConnectionFactory jedisConnectionFactory, RedisKeyExpirationListener redisListener) { RedisMessageListenerContainer container = new RedisMessageListenerContainer(); container.setConnectionFactory(jedisConnectionFactory); container.addMessageListener(redisListener, new PatternTopic( "__keyevent@0__:expired")); container.setErrorHandler(e -> log.error("There was an error in redis key expiration listener container", e)); return container; }
其中RedisKeyExpirationListener实现了spring-data-redis中的MessageListener接口。
Jedis连接工厂配置
当前使用Jedis 4.4.2(也曾测试兼容的4.3.2版本)作为连接客户端,spring-boot-starter-data-redis版本为3.1.0,连接工厂实现如下:
@Bean public JedisPoolConfig jedisPoolConfig() { var jedisPoolConfig = new JedisPoolConfig(); jedisPoolConfig.setMaxTotal(10); jedisPoolConfig.setMinIdle(0); jedisPoolConfig.setMaxIdle(8); return jedisPoolConfig; } @Bean public JedisConnectionFactory jedisConnectionFactory(JedisPoolConfig jedisPoolConfig) { var jedisClientConfiguration = JedisClientConfiguration.builder() .usePooling() .poolConfig(jedisPoolConfig) .and() .readTimeout(Duration.ofMillis(1000L)) .useSsl() .build(); // 注:原代码未完整展示连接工厂的Redis配置(如主机、端口等),此处保留原文结构 }
调试与测试发现
- 调试发现
RedisMessageListenerContainer捕获TimeoutException后抛出:
该异常后续被Bean处理器转换为"Failed to start bean"异常。IllegalStateException("Subscription registration timeout exceeded", e); - 尝试将容器的
MaxSubscriptionRegistrationWaitingTime调至最长60秒,仍触发相同异常。 - 移除
RedisMessageListenerContainer上的addMessageListener调用后,应用可正常连接Redis;仅添加消息监听器时出现问题。 - 回退至Spring Boot 2.6.2及对应版本spring-data-redis时,消息监听器可正常工作并处理过期事件。
已尝试的解决方法
- 更新Jedis、Spring Boot、spring-data-redis及spring-boot-starter-data-redis至Spring Boot 3兼容的最新版本;
- 增大连接池配置参数及超时时间;
- 移除监听器验证应用可用性(无监听器时可正常运行);
- 改用
MessageListenerAdapter实现,让RedisKeyExpirationListener实现自定义MessageDelegate接口而非MessageListener接口,配置如下:
自定义接口:@Bean RedisKeyExpirationListener redisListener() { return new RedisKeyExpirationListener(); } @Bean MessageListenerAdapter redisListenerAdapter(RedisKeyExpirationListener redisListener) { return new MessageListenerAdapter(redisListener, "handleMessage"); } @Bean RedisMessageListenerContainer jedisMessageListenerContainer(JedisConnectionFactory jedisConnectionFactory, MessageListenerAdapter redisListenerAdapter) { RedisMessageListenerContainer container = new RedisMessageListenerContainer(); container.setConnectionFactory(jedisConnectionFactory); container.addMessageListener(redisListenerAdapter, new PatternTopic( "__keyevent@0__:expired")); container.setErrorHandler(e -> log.error("There was an error in redis key expiration listener container", e)); return container; }public interface MessageDelegate { void handleMessage(String message); void handleMessage(Message message, byte[] pattern); }
请求协助
请协助排查该问题的根本原因及可行的解决方法。
内容的提问来源于stack exchange,提问作者Michał Lipski
相关产品推荐
相关产品推荐

