集成redis集群和单机redis区别主要在配置文件那里
1.引入maven包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<!-- <version>2.2.4.RELEASE</version>-->
<!-- 如使用jedis作为客户端,则需要排除内置的lettuce再引入jedis -->
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>io.lettuce</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
2.application.yml中加入集群中的所有主从节点,我这里是三主三从。
redis:
cluster:
nodes: 192.168.1.200:6379,192.168.1.200:8001,192.168.1.200:8002,192.168.1.200:8003,192.168.1.200:8004,192.168.1.201:6379
password: 123456 #密码(默认空)
timeout: 10000 #连接超时时长(单位毫秒)
jedis:
pool:
max-active: 1000 #连接池最大连接数(负值表示无限制)
max-wait: -1 #连接池最大阻塞等待时间(使用负值表示无限制)
max-idle: 8 #连接池中的最大空闲连接
min-idle: 5 #连接池中的最小空闲连接
3.配置类
@Configuration
public class RedisConfig {
@Resource
private RedisConnectionFactory factory;
@Bean
public RedisTemplate<String,Object> redisTemplate(){
RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
redisTemplate.setConnectionFactory(factory);
return redisTemplate;
}
@Bean
public HashOperations<String,String,Object> hashOperations(RedisTemplate<String,Object> redisTemplate){
return redisTemplate.opsForHash();
}
@Bean
public ValueOperations<String,String> valueOperations(RedisTemplate<String,String> redisTemplate){
return redisTemplate.opsForValue();
}
@Bean
public ListOperations<String,Object> ListOperations(RedisTemplate<String,Object> redisTemplate ){
return redisTemplate.opsForList();
}
@Bean
public SetOperations<String,Object> setOperations(RedisTemplate<String,Object> redisTemplate){
return redisTemplate.opsForSet();
}
@Bean
public ZSetOperations<String,Object> zSetOperations(RedisTemplate<String,Object> redisTemplate){
return redisTemplate.opsForZSet();
}
}
4.controller测试
@RequestMapping("/upload")
@RestController
@Api(value = "demo")
public class FileUploadController {
@Resource
private RedisTemplate redisTemplate;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
@ApiOperation(value = "单文件上传",notes = "多文件上传与此基本一致,只是需要MultipartFile[] uploadFiles 数组形式循环遍历即可")
@RequestMapping("/single")
public String upload(MultipartFile uploadFile, HttpServletRequest request){
String realPath = request.getSession().getServletContext().getRealPath("/uploadFile");
String format = sdf.format(new Date());
File folder = new File(realPath+format);
if (!folder.isDirectory()){
folder.mkdirs();
}
String oldName = uploadFile.getOriginalFilename();
String newName = UUID.randomUUID().toString()+oldName.substring(oldName.lastIndexOf("."),oldName.length());
try {
uploadFile.transferTo(new File(folder,newName));
String filePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+"/uploadFile/"+format+newName;
return filePath;
}catch (Exception e){
e.printStackTrace();
}
return "上传失败!";
}
@ApiOperation(value = "测试redis",notes = "")
@GetMapping("/getRedis")
public String getRedis( HttpServletRequest request){
ValueOperations<String,String> vo = redisTemplate.opsForValue();
vo.set("name","三国演义");
System.out.println(vo.get("name"));
return vo.get("name");
}
}
使用默认配置的话,到此就结束了。ps:我的环境是springboot2.2.4+redis.5.0.5,springboot默认已经配好基础配置了。
-----------------------------------------------------------------------------------------------------------------我是分割线---------------------------------------------------------------------------------------------------------------------------------------
SpringBoot2.x版本配置redis集群(Jedis and lettuce)
在SpringBoot1.x版本中,springboot默认使用集成jedis,在SpringBoot2.x版本中,SpringBoot默认集成lettuce。
Jedis vs Lettuce
1. Jedis使用直连方式连接Redis Server,在多线程环境下存在线程安全问题,需要增加连接池创建Jedis客户端多实例线程安全问题,基于传统I/O模式,是阻塞式传输!
2. Lettuce的连接是基于netty,在多线程环境下不存在线程安全问题,这个连接实例当然也是可伸缩的设计,也可以增加多实例连接,netty本身就基于NIO,从而提供了异步和同步数据访问方式,用于构建非阻塞的反应性应用程序。
可能一开始接触到的是jedis客户端吧,所以很多人更倾向也更熟悉jedis,虽然lettuce多线程安全而jedis默认多线程不安全。
使用SpringBoot2.3.4,Lettuce配置redis集群。
1. pom.xml配置
<properties>
<spring-boot.version>2.3.4.RELEASE</spring-boot.version>
<commons-pool.version>2.5.0</commons-pool.version>
</properties>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<!-- 依赖commons-pool2连接池 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>${commons-pool.version}</version>
</dependency>
2.yaml配置
#yaml配置
spring:
redis:
database: 0
cluster:
nodes: 127.0.0.1:7001,127.0.0.1:7002,127.0.0.1:7003,127.0.0.1:7004,127.0.0.1:7005,127.0.0.1:7006 #集群节点
password: xxxx #密码
lettuce:
pool:
max-active: 10 #连接池最大连接数
max-idle: 8 #连接池中最大空闲连接数
max-wait: -1ms #连接池最大等待阻塞时间
min-idle: 0 #连接池中最小空闲数
timeout: 5000 #访问超时时间
3. 配置RedisTemplate
@Configuration
public class RedisConfig {
@Bean
RedisTemplate<String, Serializable> redisTemplate(LettuceConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Serializable> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
@Bean
public CacheManager cacheManager(LettuceConnectionFactory factory) {
// 配置序列化
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
RedisCacheConfiguration redisCacheConfiguration = config
.serializeKeysWith(RedisSerializationContext.SerializationPair
.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair
.fromSerializer(new GenericJackson2JsonRedisSerializer()));
return RedisCacheManager.builder(factory).cacheDefaults(redisCacheConfiguration).build();
}
}
Jedis配置redis集群
<properties>
<spring-boot.version>2.3.4.RELEASE</spring-boot.version>
<jedis.version>3.3.0</jedis.version>
</properties>
<!-- 引入jedis客户端,需要把lettuce客户端移除 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>${spring-boot.version}</version>
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>${jedis.version}</version>
</dependency>
注:这里有一个比较坑的地方,导入的Jedis版本必须要和springboot版本兼容,需要点入spring-boot-starter-data-redis的pom文件查看spring-data-redis,然后继续点击spring-data-redis查看对应jedis版本
第一步:
第二步:
第三步:就可以查看到当前springboot对应哪一个jedis版本,然后在自己的pom中引入和这个redis对应的版本。
2. yaml配置
#yaml配置
spring:
redis:
database: 0
cluster:
nodes: 127.0.0.1:7001,127.0.0.1:7002,127.0.0.1:7003,127.0.0.1:7004,127.0.0.1:7005,127.0.0.1:7006 #集群节点
password: xxxx #密码
jedis:
pool:
max-active: 10 #连接池最大连接数
max-idle: 8 #连接池中最大空闲连接数
max-wait: -1 #连接池最大等待阻塞时间
min-idle: 0 #连接池中最小空闲数
timeout: 5000 #访问超时时间
3. 配置RedisTemplate
@Value("${spring.redis.cluster.nodes}")
private String host;
@Value("${spring.redis.password}")
private String password;
@Value("${spring.redis.timeout}")
private int connectionTimeout;
@Value("${spring.redis.jedis.pool.max-active}")
private int maxTotal;
@Value("${spring.redis.jedis.pool.min-idle}")
private int minIdle;
@Value("${spring.redis.jedis.pool.max-idle}")
private int maxIdle;
@Value("${spring.redis.jedis.pool.max-wait}")
private int maxWaitMillis;
@Bean
public RedisClusterConfiguration redisClusterConfiguration() {
RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration();
String[] hosts = host.split(",");
Set<RedisNode> nodeList = new HashSet<RedisNode>();
for (String hostAndPort : hosts) {
String[] hostOrPort = hostAndPort.split(":");
nodeList.add(new RedisNode(hostOrPort[0], Integer.parseInt(hostOrPort[1])));
}
redisClusterConfiguration.setClusterNodes(nodeList);
// redisClusterConfiguration.setMaxRedirects();
return redisClusterConfiguration;
}
@Bean
public JedisPoolConfig jedisPoolConfig() {
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxIdle(this.maxIdle);
poolConfig.setMinIdle(this.minIdle);
poolConfig.setTestOnCreate(true);
poolConfig.setTestOnBorrow(true);
poolConfig.setTestOnReturn(true);
poolConfig.setTestWhileIdle(true);
return poolConfig;
}
@Bean("myJedisConnectionFactory")
public JedisConnectionFactory jedisConnectionFactory(RedisClusterConfiguration redisClusterConfiguration,
JedisPoolConfig jedisPoolConfig) {
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(
redisClusterConfiguration, jedisPoolConfig);
jedisConnectionFactory.setPassword(password);
return jedisConnectionFactory;
}
@Bean
RedisTemplate<String, Serializable> redisTemplate(@Qualifier("myJedisConnectionFactory")JedisConnectionFactory jedisConnectionFactory) {
RedisTemplate<String, Serializable> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(jedisConnectionFactory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
// 设置值(value)的序列化采用Jackson2JsonRedisSerializer。
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
// 设置键(key)的序列化采用StringRedisSerializer。
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
@Bean
public CacheManager cacheManager(@Qualifier("myJedisConnectionFactory")JedisConnectionFactory jedisConnectionFactory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
RedisCacheConfiguration redisCacheConfiguration = config
.serializeKeysWith(
RedisSerializationContext.SerializationPair
.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(
RedisSerializationContext.SerializationPair
.fromSerializer(new GenericJackson2JsonRedisSerializer()));
return RedisCacheManager.builder(jeddisConnectionFactory)
.cacheDefaults(redisCacheConfiguration).build();
}
最后,项目中直接注入RedisTemplate就可以使用。