在某些业务场景中使用了redis
作为分布式缓存,在做业务活动的时候,比如秒杀活动,会一时间涌入大量的流量,这个时候和redis server
进行网络连接的话就比较耗费资源和时间,直接影响接口的响应时间。
针对这种某一时刻的突发性流量,使用连接池是比较合适的。
ps:spring-boot-starter-redis默认是不使用连接池的
SpringBoot 1.x
默认采用 Jedis
作为 redis
客户端连接池
SpringBoot 2.x spring-data-redis
默认采用 Lettuce
作为 redis
客户端驱动连接池
从 spring-boot-starter-redis 1.4.7.RELEASE
是默认使用jedis连接池
的最后一个版本
在 springboot1.4.7
之前的版本配置客户端连接池如下:
spring:
redis:
pool:
maxActive: 5000
maxIdle: 30
minIdle: 5
max-wait: 2000
在1.4.7
之后同时支持了jedis
和lettuce
两种连接池,配置方式也有点不同
Jedis
spring:
redis:
jedis:
pool:
maxActive: 5000 #最大连接数量
maxIdle: 30 #最大闲置数量
minIdle: 5 #最小闲置数量
max-wait: 2000 #从连接池中获取连接的最大等待时间
Lettuce
spring:
redis:
lettuce:
pool:
maxActive: 5000 #最大连接数
maxIdle: 30 #连接池最大空闲连接数.
minIdle: 5 #连接池最小空闲连接数.
max-wait: 2000 #从连接池中获取连接时的最大等待时间
time-between-eviction-runs: 60s #空闲对象逐出器线程的运行间隔时间.空闲连接线程释放周期时间.
ps:SpringBoot2.x开始默认使用的Redis客户端由Jedis变成了Lettuce,但是当Redis集群中某个节点挂掉之后,Lettuce将无法继续操作Redis,原因在于此时Lettuce使用的仍然是有问题的连接信息。
Lettuce支持redis 集群拓扑动态刷新,但是默认并没有开启,SpringBoot在集成Lettuce时默认也没有开启。并且在SpringBoot2.3.0之前,是没有配置项设置Lettuce自动刷新拓扑的。
解决方案:
升级到SpringBoot2.3.0或以上版本。并添加如下配置项
spring:
redis:
lettuce:
cluster:
refresh:
adaptive: true #拓扑动态感应即客户端能够根据 redis cluster 集群的变化,动态改变客户端的节点情况,完成故障转移。
period: 60s #刷新redis集群状态周期时间
timeout: 60s #连接redis的最大等待时间
在使用lettuce连接池时,创建连接工厂时依赖了commons-pool2
,记得引入依赖
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
Jedis
在实现上是直接连接的redis server
,如果在多线程环境下是非线程安全的,在多线程环境下每个线程都去拿Jedis
实例,当连接数量增多时,物理连接成本就较高了,这个时候只有使用连接池为每个Jedis
实例增加物理连接。
Lettuce
的连接是基于Netty
的,连接实例(StatefulRedisConnection
)可以在多个线程间并发访问,因为StatefulRedisConnection
是线程安全的,所以一个连接实例(StatefulRedisConnection
)就可以满足多线程环境下的并发访问,当然这个也是可伸缩的设计,一个连接实例不够的情况也可以按需增加连接实例。