文章目錄
一、問題背景
1、問題原因
阿里云Redis分直連和代理模式,其中代理模式是不支持WAIT命令
的。
目前嘗試使用redisson實現分布式鎖的時候出現無法執行WAIT命令(實際分布式鎖命令是執行成功的,只是3.14.1及之后的redisson版本會報未知WAIT命令的錯誤)
Redisson 很早就會附加 WAIT 命令,只是從 3.14.1 開始才關注 WAIT 命令的執行結果。
Exception in thread "main" org.redisson.client.RedisException: ERR unknown command 'WAIT'. channel: [id: 0xf842ee1d, L:/192.168.1.20:52123 - R:/192.168.1.10:6379] command: (WAIT), params: [1, 1000]at org.redisson.client.handler.CommandDecoder.decode(CommandDecoder.java:343)at org.redisson.client.handler.CommandDecoder.decodeCommandBatch(CommandDecoder.java:247)at org.redisson.client.handler.CommandDecoder.decodeCommand(CommandDecoder.java:189)at org.redisson.client.handler.CommandDecoder.decode(CommandDecoder.java:117)at org.redisson.client.handler.CommandDecoder.decode(CommandDecoder.java:102)at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:510)at io.netty.handler.codec.ReplayingDecoder.callDecode(ReplayingDecoder.java:366)at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:279)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:722)at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:658)at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:584)at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496)at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:995)at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)at java.lang.Thread.run(Thread.java:750)
阿里云官方強調【暫不支持通過集群架構的Proxy節點(代理模式)執行WAIT命令,如有需要,您可以通過集群架構的直連地址
執行WAIT命令】),從而導致報錯。源碼層面的原因在于當進行加鎖或者解鎖操作時,redisson會判斷當前集群的redis節點數是否大于0來給命令數組對象增加WAIT命令,這個是所有版本的redisson都有。
2、阿里云對Redisson的支持
阿里云對Redisson的支持態度很模糊,表示不會特意去適配Redisson。
二、解決方案
1、繼續使用Redisson3.14.0版本
不去關注 WAIT 命令的執行結果,相當于沒有 WAIT 命令。
Redisson3.14.0版本雖然也使用了WAIT命令,但是沒有關注其結果,所以不會報錯。
2、阿里云redis改為直連模式
阿里云redis跳過代理,改為直連模式。
相當于直接連接redis。
3、升級Redisson版本到 3.47.0+
看這個Issue:https://github.com/redisson/redisson/issues/6716
實測確實可以解決。
Redisson有幾個中間版本也是可以解決這個問題的,但是最新版本是沒問題的,建議升級最新版本