Redis学习笔记7:基于springboot的Lettuce redis客户端keepAlive保活机制

Lettuce是基于netty来实现的,Netty支持通过设置ChannelOption.SO_KEEPALIVE属性来控制保活机制,底层实现是基于操作系统,操作系统的保活机制一般要等待7200秒,如centos的net.ipv4.tcp_keepalive_time设置;lettuce客户端另外提供了扩展保活机制,方便客户端灵活的控制保活机制的空闲时间、次数、间隔。

一个对springboot redis框架进行重写,支持lettuce、jedis、连接池、同时连接多个集群、多个redis数据库、开发自定义属性配置的开源SDK

xml 复制代码
<dependency>
    <groupId>io.github.mingyang66</groupId>
    <artifactId>emily-spring-boot-redis</artifactId>
    <version>4.3.9</version>
</dependency>

GitHub地址:https://github.com/mingyang66/spring-parent

一、Lettuce提供基于操作系统的保活机制
  • 通过SocketOptions属性设置keepAlive,默认:false
java 复制代码
 ClientOptions.Builder builder = this.initializeClientOptionsBuilder(properties);
        Duration connectTimeout = properties.getConnectTimeout();
        if (connectTimeout != null) {
            builder.socketOptions(SocketOptions.builder()
                    .keepAlive(true)
                    .build());
        }
  • io.lettuce.core.ConnectionBuilder#configureBootstrap设置保活参数
java 复制代码
 bootstrap.option(ChannelOption.SO_KEEPALIVE, options.isKeepAlive());
二、Lettuce提供扩展keepAlive保活机制
  • 通过SocketOptions属性设置扩展保活机制参数
java 复制代码
        ClientOptions.Builder builder = this.initializeClientOptionsBuilder(properties);
        Duration connectTimeout = properties.getConnectTimeout();
        if (connectTimeout != null) {
            builder.socketOptions(SocketOptions.builder()
                    .connectTimeout(connectTimeout)
                    .keepAlive(SocketOptions.KeepAliveOptions.builder()
                            //两次keep-alive之间的间隔
                            .interval(Duration.ofSeconds(5))
                            //连接空闲多久开始keep-alive
                            .idle(Duration.ofSeconds(5))
                            //keep-alive多少次之后断开连接
                            .count(3)
                            //是否开启保活连接
                            .enable()
                            .build())
                    .build());
        }
  • io.lettuce.core.ConnectionBuilder#configureBootstrap保活连接配置
java 复制代码
 public void configureBootstrap(boolean domainSocket,
            Function<Class<? extends EventLoopGroup>, EventLoopGroup> eventLoopGroupProvider) {
        ...
        SocketOptions options = clientOptions.getSocketOptions();
        EventLoopGroup eventLoopGroup = eventLoopGroupProvider.apply(eventLoopGroupClass);

        bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, Math.toIntExact(options.getConnectTimeout().toMillis()));

        if (!domainSocket) {
            //基于操作系统的keepAlive机制
            bootstrap.option(ChannelOption.SO_KEEPALIVE, options.isKeepAlive());
            bootstrap.option(ChannelOption.TCP_NODELAY, options.isTcpNoDelay());
        }

        bootstrap.channel(channelClass).group(eventLoopGroup);
				//开启扩展保活机制的前提是必须开启基于操作系统的保活机制
        if (options.isKeepAlive() && options.isExtendedKeepAlive()) {

            SocketOptions.KeepAliveOptions keepAlive = options.getKeepAlive();
						//判断是否可以使用IOUringProvider,即是否可用IO uring库。如果可用,调用IOUringProvider提供的applyKeepAlive方法,传入bootstrap(Netty的引导类)和keepAlive的参数(count、idle、interval),应用IOUringProvider提供的keepalive参数配置
            if (IOUringProvider.isAvailable()) {
                IOUringProvider.applyKeepAlive(bootstrap, keepAlive.getCount(), keepAlive.getIdle(), keepAlive.getInterval());
            } else if (EpollProvider.isAvailable()) {
              //判断是否可以使用EpollProvider,即是否可用Epoll网络库。如果可用,调用EpollProvider提供的applyKeepAlive方法,传入bootstrap和keepAlive的参数,应用EpollProvider提供的keepalive参数配置。
                EpollProvider.applyKeepAlive(bootstrap, keepAlive.getCount(), keepAlive.getIdle(), keepAlive.getInterval());
            } else if (ExtendedNioSocketOptions.isAvailable() && !KqueueProvider.isAvailable()) {
              //判断是否可以使用ExtendedNioSocketOptions,并且不可使用KqueueProvider。如果可用,调用ExtendedNioSocketOptions提供的applyKeepAlive方法,传入bootstrap和keepAlive的参数,应用ExtendedNioSocketOptions提供的keepalive参数配置
              ExtendedNioSocketOptions.applyKeepAlive(bootstrap, keepAlive.getCount(), keepAlive.getIdle(),
                        keepAlive.getInterval());
            } else {
                logger.warn("Cannot apply extended TCP keepalive options to channel type " + channelClass.getName());
            }
        }
    }
  • IOUring是Netty中的一个实验性模块,用于支持Linux上的IO uring库。IOUring是Netty中的一个实验性模块,用于支持Linux上的IO uring库
  • EpollProvider是Netty中的一个类,用于在Linux上提供基于Epoll的网络通信支持。Epoll是Linux内核提供的一种事件通知机制,用于处理大量并发连接的高性能I/O操作。它通过将文件描述符(包括套接字)注册到一个事件集合中,并且可以监听多个事件类型(如可读、可写、错误等),从而实现了高效的事件驱动模型。
三、SocketOptions.KeepAliveOptions保活机制参数配置类
java 复制代码
    public static class KeepAliveOptions {
       //默认保活机制检查次数上限
        public static final int DEFAULT_COUNT = 9;
			 //默认信道空闲2小时开始进行keep-alive
        public static final Duration DEFAULT_IDLE = Duration.ofHours(2);
			 //每次keep-alive的时间间隔,默认:75秒
        public static final Duration DEFAULT_INTERVAL = Duration.ofSeconds(75);

        private final int count;

        private final boolean enabled;

        private final Duration idle;

        private final Duration interval;

        private KeepAliveOptions(KeepAliveOptions.Builder builder) {

            this.count = builder.count;
            this.enabled = builder.enabled;
            this.idle = builder.idle;
            this.interval = builder.interval;
        }
}
相关推荐
Dlwyz3 小时前
redis-击穿、穿透、雪崩
数据库·redis·缓存
工业甲酰苯胺5 小时前
Redis性能优化的18招
数据库·redis·性能优化
Oak Zhang8 小时前
sharding-jdbc自定义分片算法,表对应关系存储在mysql中,缓存到redis或者本地
redis·mysql·缓存
门牙咬脆骨8 小时前
【Redis】redis缓存击穿,缓存雪崩,缓存穿透
数据库·redis·缓存
门牙咬脆骨8 小时前
【Redis】GEO数据结构
数据库·redis·缓存
墨鸦_Cormorant10 小时前
使用docker快速部署Nginx、Redis、MySQL、Tomcat以及制作镜像
redis·nginx·docker
Dlwyz13 小时前
问题: redis-高并发场景下如何保证缓存数据与数据库的最终一致性
数据库·redis·缓存
飞升不如收破烂~14 小时前
redis的List底层数据结构 分别什么时候使用双向链表(Doubly Linked List)和压缩列表(ZipList)
redis
吴半杯15 小时前
Redis-monitor安装与配置
数据库·redis·缓存
会code的厨子17 小时前
Redis缓存高可用集群
redis·缓存