Redisson使用异常问题解决

问题一:

RedisConnectionException: Unable to init enough connections amount Only 23 from 32 were initialized.

连接数需要32个但是只有23个连上了,其余没连上告警

问题解决办法:

降低idlesize数

masterConnectionMinimumIdleSize

slaveConnectionMinimumIdleSize

subscriptionConnectionMinimumIdleSize

示例:

spring.redis.redisson.config.sentinelServersConfig.masterConnectionMinimumIdleSize = 2
spring.redis.redisson.config.sentinelServersConfig.slaveConnectionMinimumIdleSize = 2
spring.redis.redisson.config.sentinelServersConfig.subscriptionConnectionMinimumIdleSize = 1

问题二:

org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.NoClassDefFoundError: org/springframework/data/redis/connection/RedisStreamCommands\n",

_msg=["Handler dispatch failed; nested exception is java.lang.NoClassDefFoundError: org/springframework/data/redis/connection/RedisStreamCommands"]||throwable=["org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.NoClassDefFoundError: org/springframework/data/redis/connection/RedisStreamCommands\n","at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1055)\n","at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)\n","at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)\n","at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)\n","at javax.servlet.http.HttpServlet.service(HttpServlet.java:626)\n","at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)\n","at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)\n","at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)\n","at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\n","at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)\n","at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\n","at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\n","at org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:88)\n","at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n","at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\n","at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\n","at com.xiaojukeji.lathe.kettle.web.component.MdcInitFilterBean.doFilter(MdcInitFilterBean.java:28)\n","at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\n","at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\n","at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)\n","at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n","at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\n","at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\n","at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)\n","at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n","at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\n","at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\n","at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:94)\n","at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n","at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\n","at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\n","at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:114)\n","at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:104)\n","at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n","at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\n","at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\n","at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)\n","at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n","at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\n","at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\n","at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)\n","at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)\n","at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)\n","at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)\n","at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)\n","at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)\n","at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)\n","at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373)\n","at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)\n","at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)\n","at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1589)\n","at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)\n","at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)\n","at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)\n","at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\n","at java.lang.Thread.run(Thread.java:748)\nCaused by: java.lang.NoClassDefFoundError: org/springframework/data/redis/connection/RedisStreamCommands\n","at org.redisson.spring.data.connection.RedissonConnectionFactory.getConnection(RedissonConnectionFactory.java:113)\n","at org.springframework.data.redis.core.RedisConnectionUtils.doGetConnection(RedisConnectionUtils.java:134)\n","at org.springframework.data.redis.core.RedisConnectionUtils.getConnection(RedisConnectionUtils.java:97)\n","at org.springframework.data.redis.core.RedisConnectionUtils.getConnection(RedisConnectionUtils.java:84)\n","at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:212)\n","at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:185)\n","at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:172)\n","at com.xiaojukeji.lathe.kettle.process.AbstractEtlTaskProcessHandler.isTransitRunnable(AbstractEtlTaskProcessHandler.java:94)\n","at com.xiaojukeji.lathe.kettle.process.KtrScriptEtlTaskProcessHandler.processKtrTask(KtrScriptEtlTaskProcessHandler.java:66)\n","at com.xiaojukeji.lathe.kettle.service.admin.EtlRuleService.executeKettleKtrRuleTask(EtlRuleService.java:135)\n","at com.xiaojukeji.lathe.kettle.service.admin.EtlRuleService$$FastClassBySpringCGLIB$$6a2dd3bf.invoke(<generated>)\n","at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)\n","at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:752)\n","at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)\n","at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88)\n","at com.xiaojukeji.lathe.kettle.config.DefaultKettleServiceLogAspect.around(DefaultKettleServiceLogAspect.java:43)\n","at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n","at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n","at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n","at java.lang.reflect.Method.invoke(Method.java:498)\n","at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)\n","at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)\n","at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)\n","at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\n","at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93)\n","at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\n","at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)\n","at com.xiaojukeji.lathe.kettle.service.admin.EtlRuleService$$EnhancerBySpringCGLIB$$2f587a26.executeKettleKtrRuleTask(<generated>)\n","at com.xiaojukeji.lathe.kettle.web.controller.EtlRuleController.runKettleRuleTask(EtlRuleController.java:62)\n","at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n","at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n","at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n","at java.lang.reflect.Method.invoke(Method.java:498)\n","at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)\n","at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)\n","at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)\n","at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:892)\n","at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)\n","at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)\n","at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)\n","... 55 more\nCaused by: java.lang.ClassNotFoundException: org.springframework.data.redis.connection.RedisStreamCommands\n","at java.net.URLClassLoader.findClass(URLClassLoader.java:382)\n","at java.lang.ClassLoader.loadClass(ClassLoader.java:418)\n","at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:93)\n","at java.lang.ClassLoader.loadClass(ClassLoader.java:351)\n","... 95 more\n"]

检查redisson的版本与springboot和redis是否匹配

<think>我们正在讨论Redisson分布式锁的问题及其解决方案。根据引用资料,Redisson分布式锁虽然功能强大,但也存在一些潜在问题。我们需要分析这些问题并提供相应的解决方案。主要问题可能包括:1.锁续期机制(WatchDog)的潜在问题:虽然Watch Dog可以自动续期锁,防止业务执行时间过长导致锁过期,但在某些情况下(如长时间GC或网络延迟)可能导致锁被错误续期或释放。2.加锁/解锁的原子性问题Redisson使用Lua脚本保证原子性,但在极端情况下(如Redis主从切换)可能导致锁状态不一致。3.性能问题:在高并发场景下,大量线程争抢同一个锁可能导致Redis性能瓶颈。4.死锁问题:如果持有锁的客户端崩溃,且Watch Dog未能及时续期,锁会超时释放,但若崩溃发生在续期间隙,可能导致锁提前释放。5.集群环境下的问题:在Redis集群中,主节点宕机且从节点未同步锁信息时,可能导致多个客户端同时持有锁。解决方案:1.针对WatchDog机制:合理设置锁超时时间,确保业务逻辑在超时时间内完成;同时监控锁续期情况,避免长时间持有锁。2.使用Redisson提供的多把锁(联锁MultiLock)来增强一致性,但会降低性能。3.对于性能问题,可以考虑锁分段(将一个大锁拆分为多个小锁)或使用自旋锁(减少等待时间)。4.避免死锁:确保业务逻辑的健壮性,及时释放锁;同时,Redisson默认的锁超时时间为30秒,可根据业务调整。5.在集群环境下,可以使用Redisson的RedLock(红锁)算法,但该算法需要多个独立的Redis实例,且性能较低。注意:RedLock算法存在争议(如MartinKleppmann的文章),因此需根据业务场景权衡。下面我们详细展开。</think>### Redisson分布式锁的常见问题解决方案 Redisson分布式锁在实现分布式系统协调方面表现出色,但仍存在以下典型问题及应对策略: #### 一、锁续期机制问题(Watch Dog) **问题描述**: Watch Dog默认每30秒自动续期锁(可通过`Config.lockWatchdogTimeout`调整)。但在以下场景可能失效: 1. 业务执行时间超过锁有效期,且续期线程被阻塞(如长时间GC) 2. 网络分区导致续期请求失败 3. 客户端崩溃后产生僵尸锁(锁未被释放) **解决方案**: ```java // 示例:显式设置锁超时并关闭Watch Dog RLock lock = redisson.getLock("resourceLock"); try { // 手动指定10秒超时,不启用Watch Dog if (lock.tryLock(0, 10, TimeUnit.SECONDS)) { // 业务逻辑(必须能在10秒内完成) } } finally { if (lock.isLocked() && lock.isHeldByCurrentThread()) { lock.unlock(); } } ``` **优化建议**: 1. 根据业务最大耗时设置超时时间(建议:`业务最长时间 × 2`) 2. 添加JVM钩子保证进程退出时释放锁 3. 监控锁持有时间并设置报警阈值[^3] #### 二、集群故障切换问题 **问题描述**: Redis主从切换时可能导致锁丢失(异步复制延迟),引发多个客户端同时持有锁。 **解决方案**: ```java // 使用RedLock算法(需部署奇数个独立Redis实例) RedissonRedLock redLock = new RedissonRedLock( redisson1.getLock("lock1"), redisson2.getLock("lock2"), redisson3.getLock("lock3") ); redLock.lock(); try { // 业务逻辑 } finally { redLock.unlock(); } ``` **注意事项**: - RedLock性能下降约50%(需多数节点确认) - 网络分区时仍可能失效(需结合业务补偿机制)[^2] #### 三、锁重入与内存泄漏 **问题描述**: 重入锁的计数器未正确归零时,可能导致: 1. 锁永久驻留Redis(内存泄漏) 2. 其他客户端无法获取锁 **根本原因**: - 未匹配的`lock()`/`unlock()`调用 - 异常跳过解锁代码 **解决方案**: ```java RLock lock = redisson.getLock("reentrantLock"); lock.lock(); try { // 嵌套加锁 lock.lock(); try { // 内部逻辑 } finally { lock.unlock(); // 必须逐层释放 } } finally { lock.unlock(); // 确保最终释放 } ``` **最佳实践**: 1. 使用`tryLock()`替代`lock()`设置超时 2. 在`finally`块中检查锁状态再释放 3. 部署Redis内存监控(`maxmemory-policy`)[^4] #### 四、竞争条件下的性能瓶颈 **问题描述**: 高并发场景下,锁释放时的订阅/通知机制(Pub/Sub)可能导致: 1. Redis CPU飙升(大量`PUBLISH`命令) 2. 客户端线程阻塞(等待通知) **优化方案**: ```java // 启用异步加锁(非阻塞模式) RFuture<Boolean> lockFuture = lock.tryLockAsync(0, 10, TimeUnit.SECONDS); lockFuture.whenComplete((res, ex) -> { if (res) { try { // 业务逻辑 } finally { lock.unlockAsync(); } } }); ``` **性能调优**: 1. 拆分热点锁(如按用户ID分片) 2. 设置`redisson.executor`线程池大小 3. 使用`RLock.tryLock()`轮询替代订阅(牺牲实时性)[^4] ### 总结建议 | 问题类型 | 关键缓解措施 | 适用场景 | |------------------|---------------------------------------|------------------------| | 续期失效 | 合理超时+JVM钩子 | 长事务处理 | | 集群故障 | RedLock+业务补偿 | 金融/高一致性场景 | | 重入泄漏 | 严格匹配加解锁 | 递归调用 | | 性能瓶颈 | 锁分片+异步API | 高并发系统 | > **重要原则**:分布式锁无法100%可靠,需结合业务设计幂等、重试、状态机等容错机制[^2]。 --- ### 相关问题 1. Redisson的Watch Dog机制在哪些场景下可能失效?如何检测续期失败? 2. Redis集群主从切换时如何保证分布式锁的强一致性?RedLock算法有哪些局限性? 3. 如何避免Redisson重入锁导致的内存泄漏问题?有哪些监控指标? 4. 在高并发场景下,Redisson分布式锁的哪些配置参数对性能影响最大? 5. 除了Redisson,还有哪些分布式锁实现方案(如ZooKeeper)?各有什么优劣? [^1]: 分布式锁?一个注解就搞定了 [^2]: Redisson分布式锁 [^3]: RedissonLock-tryLock-续期 [^4]: Redisson框架
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值