Redisson报异常attempt to unlock lock, not locked by current thread by node id解决方案

2年前 (2022) 程序员胖胖胖虎阿
330 0 0

Redisson报异常attempt to unlock lock, not locked by current thread by node id解决方案

  • 问题背景
  • 解决方案
  • 总结
  • Lyric: 那想念的身影

问题背景

Redisson做分布式锁是目前比较流行的方式,但是在使用的过程中遇到一些坑:

  • Redisson的分布式锁只能通过创建锁的线程进行解锁,正所谓解铃还须系铃人,不是同一个线程解锁会报异常
  • 因为Redisson是为锁而生,所以一开始设计的时候,为了防止死锁,默认锁的过期时间为30S
  • 当时我居然傻到用单元测试来测试Redisson的分布式锁,我太傻了,单元测试之后马上就会结束项目运行,那么就没有线程持有锁了,更别说还需要同线程解锁了

报异常:

2022-05-07 10:10:36.005  INFO 67300 --- [           main] c.y.redisson.utils.DistributedRedisLock  : lock:true
2022-05-07 10:10:36.011  INFO 67300 --- [           main] c.y.redisson.utils.DistributedRedisLock  : lock.isHeldByCurrentThread: false
2022-05-07 10:10:36.039 ERROR 67300 --- [           main] c.y.redisson.utils.DistributedRedisLock  : DistributedRedisLock unlock [yuange] Exception:

java.lang.IllegalMonitorStateException: attempt to unlock lock, not locked by current thread by node id: 51f450d1-f832-4950-8e78-aec9a7484b8e thread-id: 1
	at org.redisson.RedissonBaseLock.lambda$unlockAsync$1(RedissonBaseLock.java:316) ~[redisson-3.16.8.jar:3.16.8]
	at java.util.concurrent.CompletableFuture.uniHandle(CompletableFuture.java:822) ~[na:1.8.0_221]
	at java.util.concurrent.CompletableFuture$UniHandle.tryFire(CompletableFuture.java:797) ~[na:1.8.0_221]
	at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:474) ~[na:1.8.0_221]
	at java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:1962) ~[na:1.8.0_221]
	at org.redisson.misc.RedissonPromise.trySuccess(RedissonPromise.java:83) ~[redisson-3.16.8.jar:3.16.8]
	at org.redisson.command.CommandBatchService.lambda$executeAsync$7(CommandBatchService.java:324) ~[redisson-3.16.8.jar:3.16.8]
	at java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:760) ~[na:1.8.0_221]
	at java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:736) ~[na:1.8.0_221]
	at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:474) ~[na:1.8.0_221]
	at java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:1962) ~[na:1.8.0_221]
	at org.redisson.command.RedisCommonBatchExecutor.handleResult(RedisCommonBatchExecutor.java:162) ~[redisson-3.16.8.jar:3.16.8]
	at org.redisson.command.RedisExecutor.checkAttemptPromise(RedisExecutor.java:476) ~[redisson-3.16.8.jar:3.16.8]
	at org.redisson.command.RedisExecutor.lambda$execute$3(RedisExecutor.java:172) ~[redisson-3.16.8.jar:3.16.8]
	at java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:760) ~[na:1.8.0_221]
	at java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:736) ~[na:1.8.0_221]
	at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:474) ~[na:1.8.0_221]
	at java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:1962) ~[na:1.8.0_221]
	at org.redisson.client.handler.CommandDecoder.decodeCommandBatch(CommandDecoder.java:318) ~[redisson-3.16.8.jar:3.16.8]
	at org.redisson.client.handler.CommandDecoder.decodeCommand(CommandDecoder.java:210) ~[redisson-3.16.8.jar:3.16.8]
	at org.redisson.client.handler.CommandDecoder.decode(CommandDecoder.java:137) ~[redisson-3.16.8.jar:3.16.8]
	at org.redisson.client.handler.CommandDecoder.decode(CommandDecoder.java:113) ~[redisson-3.16.8.jar:3.16.8]
	at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:510) ~[netty-codec-4.1.76.Final.jar:4.1.76.Final]
	at io.netty.handler.codec.ReplayingDecoder.callDecode(ReplayingDecoder.java:366) ~[netty-codec-4.1.76.Final.jar:4.1.76.Final]
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:279) ~[netty-codec-4.1.76.Final.jar:4.1.76.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.76.Final.jar:4.1.76.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.76.Final.jar:4.1.76.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.76.Final.jar:4.1.76.Final]
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.76.Final.jar:4.1.76.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.76.Final.jar:4.1.76.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.76.Final.jar:4.1.76.Final]
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.76.Final.jar:4.1.76.Final]
	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) ~[netty-transport-4.1.76.Final.jar:4.1.76.Final]
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:722) ~[netty-transport-4.1.76.Final.jar:4.1.76.Final]
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:658) ~[netty-transport-4.1.76.Final.jar:4.1.76.Final]
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:584) ~[netty-transport-4.1.76.Final.jar:4.1.76.Final]
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496) ~[netty-transport-4.1.76.Final.jar:4.1.76.Final]
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986) ~[netty-common-4.1.76.Final.jar:4.1.76.Final]
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.76.Final.jar:4.1.76.Final]
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.76.Final.jar:4.1.76.Final]
	at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_221]

2022-05-07 10:10:36.039 ERROR 67300 --- [           main] com.yg.redisson.main.RedissonTest        : unlock failed

解决方案

1 这个异常报错主要有两个原因,刚才的背景介绍中说过

  • 解锁需要创建锁的线程进行解锁,否则就报这个异常
  • 过期时间默认30S,超过30S秒,即使用同一个线程解锁也会报这个异常,因为锁已经不存在了

总结

  • 如果想使用不同线程都可以解锁,那么可以使用redis自带的setnx,可以在我的另一篇文章中看测试源码

作为程序员第 123 篇文章,每次写一句歌词记录一下,看看人生有几首歌的时间,wahahaha …
Redisson报异常attempt to unlock lock, not locked by current thread by node id解决方案Redisson报异常attempt to unlock lock, not locked by current thread by node id解决方案Redisson报异常attempt to unlock lock, not locked by current thread by node id解决方案

Lyric: 那想念的身影

相关文章

暂无评论

暂无评论...