集成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");
    }
}

Springboot整合redis集群 springboot redis集群 lettuce_连接池

使用默认配置的话,到此就结束了。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整合redis集群 springboot redis集群 lettuce_Springboot整合redis集群_02


第二步:

Springboot整合redis集群 springboot redis集群 lettuce_spring_03

第三步:就可以查看到当前springboot对应哪一个jedis版本,然后在自己的pom中引入和这个redis对应的版本。

Springboot整合redis集群 springboot redis集群 lettuce_redis_04

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就可以使用。