文章目录
Lettuce是一个基于Netty的Redis客户端,可以使用较少的统一管理的IO线程处理全部的数据。Lettuce提供了同步,异步和响应式命令。
lettuce文档:https://lettuce.io/core/release/reference/
Lettuce读写命令流程
-
通过RedisClient初始化连接(netty参数,重试机制等等):
通过RedisClient.connect获取到连接StatefulRedisConnectionImpl在创建连接StatefulRedisConnectionImpl过程中,会初始化BootStrap、Channel和DefaultEndpoint等重要成员。StatefulRedisConnectionImpl绑定了一个Channel,Channel也绑定了IO线程(Bootstrap#connect)。
-
通过StatefulRedisConnectionImpl获取同步/异步/响应式连接,再执行Redis命令。
命令首先被封装成AsyncCommand,然后通过DefaultEndpoint发送命令,DefaultEndpoint内部会依靠Netty IO线程使用Channel异步发送命令,此时用户线程已经能获取到一个AsyncCommand,只是没有响应的数据。
命令的响应首先被Netty IO线程接收到,从绑定的对应channel的CommandHandler里面取出对应的AsyncCommand,解析且封装响应到output,此时之前用户线程就能从AsyncCommand拿到响应了。
看门狗重连机制
连接正常时的有序性
lettuce是通过DefaultEndpoint缓存本地命令,CommandHandler与redis服务器进行读写命令。每次在DefaultEndpoint会用sharedLock保证命令有序性,防止有重连或者未flush的情况;每次CommandHandler向服务端发送一条命令,就会往stack底部压入一条命令,TCP是有序的,Redis是单线程处理命令,所以从服务端响应过来了结果,能够对应上之前往stack压入的命令,这时CommandHandler只需要pop出来顶端的命令,即可对应上。
连接异常时的乱序现象
但是在连接有问题时,channel还是同一个的话,就不再是有序的了。比如本地先后发送了两条命令,redis响应第一条命令时连接断开,在第二条命令响应前连接又好了,就会导致客户端只收到第二条命令,并且会与第一条命令进行匹配,这样就乱序了。
看门狗重连
在channel不可用时,清空stack,关闭channel。通过io.lettuce.core.protocol.ReconnectionHandler#reconnect重新创建一个channel,由于Channel的BootStrap是同一个,所以其pipleline最终没有什么区别,功能一致,因为DefaultEndpoint是同一个对象。
看门狗配置
io.lettuce.core.ClientOptions#autoReconnect