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;
        }
}
相关推荐
Flynn Liang31 分钟前
内存/Redis/PGVector/Milvus/ES 怎么选?Spring AI VectorStore 抽象与向量库选型对照表
redis·elasticsearch·milvus·rag·springai·pgvector·向量库
hweiyu002 小时前
Redis命令:SUNIONSTORE
redis·缓存
麻瓜code3 小时前
秒杀优化三连:Lua + 阻塞队列 + Redis Stream,响应从 3.4 秒到毫秒级
redis·junit·lua
没有气的汽水6 小时前
一次生产 Redis 内存打满的排查、清理和复盘
redis
hey you~7 小时前
云呼叫中心坐席自动分配实战:ACD 策略、Redis+Lua 实现与排查清单
数据库·redis·lua·云呼叫中心·acd·坐席分配·坐席状态机
我不会起名字3228 小时前
Redis pipeline 用了反而更慢:3 类误用与正确的批量姿势
redis·pipeline·lua·rtt·批量
Tsuki_tl8 小时前
【总结】Redis五大数据类型应用场景及基本命令
数据库·redis·后端·缓存·缓存中间件·redis命令·redis 五大数据类型
代码丰1 天前
大 JSON 放进 Redis 之后,如何用 Stream 解耦耗时任务?
redis·后端·系统架构
枫子有风1 天前
卡码网盘项目深挖
java·redis·jwt·es·pgvector
福大大架构师每日一题1 天前
redis 8.10.3正式发布:聚焦集群总线超大消息传播场景的安全修复,8.10.3 Latest更新解读
数据库·redis·安全