redis的主从复制我就不赘述了,各大博客都有写怎么配置的,我们来讲SpringBoot怎么配置读写分离:
方法应该有多种:可能的实现有利用AOP动态的获取redis连接工厂并注入对应的实例
本文的实现比较呆板,读写分离,主redis负责写,从redis负责读,有两个java配置类如下:
附加:java Config(java配置类)是Spring的一种编码风格,其他两种编码风格为XML和注解,Java Config风格在SpringBoot中搭配注解风格同时使用;
Maven需要引入的依赖:
<!--redis依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- redis集群使用 -->
<dependency>
<!-- springboot的parents依赖中有对版本号的控制,此处不需要添加版本号相关信息 -->
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
主redis对应的配置类:
package com.wang.ms.config;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;
//主redis对应的配置类
@Configuration
public class MasterRedisConfig {
//Redis连接池配置
@Bean
public JedisPoolConfig jedisPoolConfig(){
JedisPoolConfig masterConfig=new JedisPoolConfig();
masterConfig.setMaxTotal(1000);
masterConfig.setMaxIdle(1000);
masterConfig.setMaxWaitMillis(3000);
return masterConfig;
}
//redis主连接工厂
@Bean("masterRedisFactory")
@Primary
public JedisConnectionFactory masterJedisConnectionFactory(JedisPoolConfig jedisPoolConfig){
JedisConnectionFactory masterFactory=new JedisConnectionFactory();
masterFactory.setPort(6381);
masterFactory.setHostName("192.168.199.128");
masterFactory.setPoolConfig(jedisPoolConfig);
masterFactory.setTimeout(3000);
return masterFactory;
}
//构造redis主对应的Template
@Bean("masterRedisTemplate")
@Primary
public RedisTemplate masterRedisTemplate(@Qualifier("masterRedisFactory") JedisConnectionFactory jedisConnectionFactory){
RedisTemplate masterRedisTemplate=new RedisTemplate();
masterRedisTemplate.setConnectionFactory(jedisConnectionFactory);
masterRedisTemplate.setKeySerializer(new StringRedisSerializer());
masterRedisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
return masterRedisTemplate;
}
}
从redis对应的配置类:
package com.wang.ms.config;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;
@Configuration
//从redis对应的配置类
public class SlaveRedisConfig {
@Bean("slaveRedisFactory")
public JedisConnectionFactory slaveJedisConnectionFactory(JedisPoolConfig jedisPoolConfig){
JedisConnectionFactory slaveFactory=new JedisConnectionFactory();
slaveFactory.setPort(6379);
slaveFactory.setHostName("192.168.199.128");
slaveFactory.setPoolConfig(jedisPoolConfig);
slaveFactory.setTimeout(3000);
return slaveFactory;
}
@Bean("slaveRedisTemplate")
public RedisTemplate slaveRedisTemplate(@Qualifier("slaveRedisFactory") JedisConnectionFactory jedisConnectionFactory){
RedisTemplate slaveRedisTemplate=new RedisTemplate();
slaveRedisTemplate.setConnectionFactory(jedisConnectionFactory);
slaveRedisTemplate.setKeySerializer(new StringRedisSerializer());
slaveRedisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
return slaveRedisTemplate;
}
}
注意,我的redis主的端口是6381,redis从的端口是6379,@Primary不能缺省,即使形参注入时用了@Qualifier()也不能省,因为SpringBoot的AutoRedisConfig(一个Springboot的内部自动配置redis类没有用@Qualifier指定注入哪个redis连接工厂,所以当你项目中有两个redis连接工厂时,SpringBoot会报错,提示发现了两个工厂bean,但只期望一个),@Primary代表这个bean为主bean,如果有相同类型的bean,优先注入这个bean;
如果开启SpringBoot时报错:
redis.clients.jedis.exceptions.JedisConnectionException:
java.net.ConnectException: Connection refused: connect
因为我的redis主从都在虚拟机(Linux)上,redis.conf默认配置是bind 127.0.0.1,他只会监听本机(虚拟机)的端口并接受本机(虚拟机上)的客户端访问,而我现在的应用在主机(Windows)上,他要去访问虚拟机上的redis,则redis应该开启对ip(图中例子192.168.199.128,也就是虚拟机自己所在的ip地址)的监听,本地项目才能通过192.168.199.128去访问到虚拟机上的redis服务端口;
测试写入redis:
测试redis读出: