刚开始项目用的是redis单点,但是生产环境是redis集群,没办法,只能将项目的redis连接方式进行修改。
单点的时候使用的是xml的方式生产bean
<!-- redis 配置 -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="${redis.pool.maxTotal}"/><!-- 连接池中最多可以有多少个jedis实例 默认值是8-->
<property name="maxIdle" value="${redis.pool.maxIdle}"/><!-- 连接池中最多有多少个空闲的jedis实例 默认值是8-->
<property name="minIdle" value="${redis.pool.minIdle}"/><!-- 连接池中最小有多少个空闲的jedis实例,默认值是0 -->
<property name="testOnBorrow" value="${redis.testOnBorrow}"/>
</bean>
<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:host-name="${redisHost}" p:port="${redisPort}" p:password="${redisPass}" p:pool-config-ref="poolConfig"/>
<bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
<property name="connectionFactory" ref="connectionFactory"/>
</bean>
<!--spring session . 禁用 To disable the automatic configuration -->
<util:constant
static-field="org.springframework.session.data.redis.config.ConfigureRedisAction.NO_OP"/>
所以改用集群的时候也是采用xml的方式生产bean
<!-- redis 配置 -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="${redis.pool.maxTotal}"/><!-- 连接池中最多可以有多少个jedis实例 默认值是8-->
<property name="maxIdle" value="${redis.pool.maxIdle}"/><!-- 连接池中最多有多少个空闲的jedis实例 默认值是8-->
<property name="minIdle" value="${redis.pool.minIdle}"/><!-- 连接池中最小有多少个空闲的jedis实例,默认值是0 -->
<property name="testOnBorrow" value="${redis.testOnBorrow}"/>
</bean>
<bean id = "jedisCluster" class="redis.clients.jedis.JedisCluster">
<constructor-arg index="0" >
<set>
<!-- set集合中存储了HostAndPort用于设置集群中的每个的节点的IP和端口 -->
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="${redis1.host}"/>
<constructor-arg name="port" value="${redis1.port}"/>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="${redis2.host}"/>
<constructor-arg name="port" value="${redis2.port}"/>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="${redis3.host}"/>
<constructor-arg name="port" value="${redis3.port}"/>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="${redis4.host}"/>
<constructor-arg name="port" value="${redis4.port}"/>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="${redis5.host}"/>
<constructor-arg name="port" value="${redis5.port}"/>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="${redis6.host}"/>
<constructor-arg name="port" value="${redis6.port}"/>
</bean>
</set>
</constructor-arg>
<constructor-arg index="1" value="${redis.timeout}"/>
<constructor-arg index="2" value="${redis.socket.timeout}"/>
<constructor-arg index="3" value="${redis.maxAttempts}"/>
<constructor-arg index="4" value="${redis.auth}"/>
<!-- 引入连接池的配置使用连接池进行连接redis -->
<constructor-arg index="5" ref="poolConfig"/>
</bean>
但是修改后项目启动报:“nested exception is redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool”
连接失败了?什么鬼?
查了下资料可能是jedis版本的问题:jedis 2.9.0的版本无法兼容从节点失连情况,在从节点丢失,应用重启的情况下无法正常启动项目,所以修改了jedis版本为2.9.3。(注意先排除自带的2.9.0版本)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.3</version>
</dependency>
再次启动项目,好家伙,报了一个新的错误:“nested exception is redis.clients.jedis.exceptions.JedisClusterException: CLUSTERDOWN The cluster is down”
啥情况,集群挂了?用工具测试了下,连接没问题,说明集群没挂。百思不得其解,没办法,只能修改生产bean的方式来试下了。
首先将xml中配置reids的部分注释掉,再新增redis配置类JedisClusterConfig,类名注意加上注解@Configuration
@Bean
public JedisCluster getJedisCluster() {
log.info("进入redis集群初始化方法:访问集群地址为:"+nodes);
//获取服务器数组(这里要相信自己的输入,所以没有考虑空指针问题)
String[] serverArray = nodes.split(",");
Set<HostAndPort> nodes = new HashSet<>();
for (String ipPort : serverArray) {
String[] ipPortPair = ipPort.split(":");
nodes.add(new HostAndPort(ipPortPair[0].trim(), Integer.parseInt(ipPortPair[1].trim())));
}
GenericObjectPoolConfig config = new GenericObjectPoolConfig();
config.setMaxTotal(maxTotal);
config.setMaxIdle(maxIdle);
//设置最小空闲数
config.setMinIdle(minIdle);
config.setMaxWaitMillis(maxWait);
//在获取Jedis连接时,自动检验连接是否可用
config.setTestOnBorrow(true);
//在将连接放回池中前,自动检验连接是否有效
config.setTestOnReturn(true);
//自动测试池中的空闲连接是否都是可用连接
config.setTestWhileIdle(true);
//连接耗尽时是否阻塞, false报异常,ture阻塞直到超时,默认true
config.setBlockWhenExhausted(false);
//表示idle object evitor两次扫描之间要sleep的毫秒数
config.setTimeBetweenEvictionRunsMillis(30000);
//表示idle object evitor每次扫描的最多的对象数
config.setNumTestsPerEvictionRun(10);
//表示一个对象至少停留在idle状态的最短时间,然后才能被idle object evitor扫描并驱逐;这一项只有在timeBetweenEvictionRunsMillis大于0时才有意义
config.setMinEvictableIdleTimeMillis(60000);
//需要密码连接的创建对象方式
//参数依次是:集群地址,链接超时时间,返回值的超时时间,链接尝试次数,密码和配置文件
return new JedisCluster(nodes,commandTimeout,10000,3,pwd,config);
}
重新启动项目,成功启动,就此,redis单点改集群成功解决!!!