Skip to content

多级缓存启用同步本地缓存后,关闭应用时视乎有问题 #993

@missfmaster

Description

@missfmaster

opendjk17,jetcache2.7.8,springboot3.5.7

手动创建了一个多级缓存:

@PostConstruct
    public void init() {
        QuickConfig qc = QuickConfig.newBuilder("userCache")
            //.expire(Duration.ofSeconds(100))
            .cacheType(CacheType.BOTH)
            .syncLocal(true)  // 开启本地同步后,关闭应用时报一个错
            .localLimit(20)
            .build();
        userCache = cacheManager.getOrCreateCache(qc);
    }

redis操作基于spring-data-redis,在应用关闭时,报了一个错:

2025-11-06T03:18:40.316+08:00  WARN 19044 --- [ionShutdownHook] d.r.c.l.LettucePoolingConnectionProvider : LettucePoolingConnectionProvider contains unreleased connections
2025-11-06T03:18:40.325+08:00  WARN 19044 --- [ionShutdownHook] o.s.d.r.l.RedisMessageListenerContainer  : Unable to unsubscribe from subscriptions

org.springframework.data.redis.connection.PoolException: Returned connection io.lettuce.core.pubsub.StatefulRedisPubSubConnectionImpl@6e243864 was either previously returned or does not belong to this connection provider
	at org.springframework.data.redis.connection.lettuce.LettucePoolingConnectionProvider.release(LettucePoolingConnectionProvider.java:166) ~[spring-data-redis-3.5.5.jar:3.5.5]
	at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.release(LettuceConnectionFactory.java:1852) ~[spring-data-redis-3.5.5.jar:3.5.5]
	at org.springframework.data.redis.connection.lettuce.LettuceSubscription.doClose(LettuceSubscription.java:102) ~[spring-data-redis-3.5.5.jar:3.5.5]
	at org.springframework.data.redis.connection.util.AbstractSubscription.close(AbstractSubscription.java:105) ~[spring-data-redis-3.5.5.jar:3.5.5]
	at org.springframework.data.redis.listener.RedisMessageListenerContainer$Subscriber.closeSubscription(RedisMessageListenerContainer.java:1361) ~[spring-data-redis-3.5.5.jar:3.5.5]
	at org.springframework.data.redis.listener.RedisMessageListenerContainer$Subscriber.doUnsubscribe(RedisMessageListenerContainer.java:1324) ~[spring-data-redis-3.5.5.jar:3.5.5]
	at org.springframework.data.redis.listener.RedisMessageListenerContainer$Subscriber.lambda$unsubscribeAll$2(RedisMessageListenerContainer.java:1317) ~[spring-data-redis-3.5.5.jar:3.5.5]
	at org.springframework.data.redis.listener.RedisMessageListenerContainer$Subscriber.lambda$doInLock$9(RedisMessageListenerContainer.java:1445) ~[spring-data-redis-3.5.5.jar:3.5.5]
	at org.springframework.data.redis.listener.RedisMessageListenerContainer$Subscriber.doInLock(RedisMessageListenerContainer.java:1455) ~[spring-data-redis-3.5.5.jar:3.5.5]
	at org.springframework.data.redis.listener.RedisMessageListenerContainer$Subscriber.doInLock(RedisMessageListenerContainer.java:1444) ~[spring-data-redis-3.5.5.jar:3.5.5]
	at org.springframework.data.redis.listener.RedisMessageListenerContainer$Subscriber.unsubscribeAll(RedisMessageListenerContainer.java:1312) ~[spring-data-redis-3.5.5.jar:3.5.5]
	at org.springframework.data.redis.listener.RedisMessageListenerContainer.doUnsubscribe(RedisMessageListenerContainer.java:512) ~[spring-data-redis-3.5.5.jar:3.5.5]
	at org.springframework.data.redis.listener.RedisMessageListenerContainer.stopListening(RedisMessageListenerContainer.java:494) ~[spring-data-redis-3.5.5.jar:3.5.5]
	at org.springframework.data.redis.listener.RedisMessageListenerContainer.removeListener(RedisMessageListenerContainer.java:764) ~[spring-data-redis-3.5.5.jar:3.5.5]
	at org.springframework.data.redis.listener.RedisMessageListenerContainer.removeMessageListener(RedisMessageListenerContainer.java:587) ~[spring-data-redis-3.5.5.jar:3.5.5]
	at org.springframework.data.redis.listener.RedisMessageListenerContainer.removeMessageListener(RedisMessageListenerContainer.java:614) ~[spring-data-redis-3.5.5.jar:3.5.5]
	at com.alicp.jetcache.redis.springdata.SpringDataBroadcastManager.close(SpringDataBroadcastManager.java:104) ~[jetcache-redis-springdata-2.7.8.jar:na]
	at com.alicp.jetcache.SimpleCacheManager.lambda$close$0(SimpleCacheManager.java:44) ~[jetcache-core-2.7.8.jar:na]
	at java.base/java.util.concurrent.ConcurrentHashMap.forEach(ConcurrentHashMap.java:1603) ~[na:na]
	at com.alicp.jetcache.SimpleCacheManager.close(SimpleCacheManager.java:42) ~[jetcache-core-2.7.8.jar:na]
	at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:233) ~[spring-beans-6.2.12.jar:6.2.12]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroyBean(DefaultSingletonBeanRegistry.java:798) ~[spring-beans-6.2.12.jar:6.2.12]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingleton(DefaultSingletonBeanRegistry.java:748) ~[spring-beans-6.2.12.jar:6.2.12]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingleton(DefaultListableBeanFactory.java:1499) ~[spring-beans-6.2.12.jar:6.2.12]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingletons(DefaultSingletonBeanRegistry.java:707) ~[spring-beans-6.2.12.jar:6.2.12]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingletons(DefaultListableBeanFactory.java:1492) ~[spring-beans-6.2.12.jar:6.2.12]
	at org.springframework.context.support.AbstractApplicationContext.destroyBeans(AbstractApplicationContext.java:1222) ~[spring-context-6.2.12.jar:6.2.12]
	at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:1183) ~[spring-context-6.2.12.jar:6.2.12]
	at org.springframework.context.support.AbstractApplicationContext.close(AbstractApplicationContext.java:1129) ~[spring-context-6.2.12.jar:6.2.12]
	at org.springframework.boot.SpringApplicationShutdownHook.closeAndWait(SpringApplicationShutdownHook.java:147) ~[spring-boot-3.5.7.jar:3.5.7]
	at java.base/java.lang.Iterable.forEach(Iterable.java:75) ~[na:na]
	at org.springframework.boot.SpringApplicationShutdownHook.run(SpringApplicationShutdownHook.java:116) ~[spring-boot-3.5.7.jar:3.5.7]
	at java.base/java.lang.Thread.run(Thread.java:840) ~[na:na]

AI解释:

根据错误信息,这是一个与 Redis 连接池相关的异常。错误发生在关闭 StatefulRedisPubSubConnection 连接时,提示该连接已经被归还或不属于当前连接提供者。

问题分析

这个错误通常出现在以下几种情况:

  1. 重复释放连接:同一个连接被多次归还到连接池中
  2. 连接管理不当:连接在使用完毕后没有正确关闭或被错误地重新使用
  3. Spring Data Redis 与 JetCache 集成问题:特别是在应用关闭时,资源清理顺序不当

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions