在这里插入图片描述

一. 问题背景

研究完基于Docker搭建Redis集群,开始用SpringBoot整合Redis集群,没有想象中的那么难,和SpringBoot整合Redis(Lettuce客户端)差不多

参考自:

二. 搭建好Redis集群

我采用Redis-Cluster(最新版的Redis集群架构)去搭建集群,详情可参考基于Docker搭建Redis集群

三. SpringBoot整合Redis集群

3.1 引入依赖

SpringBoot2.x默认使用Lettuce客户端了,因此我们也直接使用默认的Lettuce客户端,肯定有它的优点:

<!-- SpringBoot整合Redis的依赖 -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- lettuce pool 缓存连接池-->
<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-pool2</artifactId>
  <version>2.9.0</version>
</dependency>

3.2 配置Redis集群信息

去yml配置Redis集群的相关信息,如下:

spring:
  redis:
    cluster:
      timeout: 1000
      max-redirects: 3
      nodes: 192.168.199.130:6379,192.168.199.130:6380,192.168.199.130:6381,192.168.199.130:6382,192.168.199.130:6383,192.168.199.130:6384
    lettuce:
      pool:
        max-idle: 10 # 连接池中的最大空闲连接
        max-wait: 500 # 连接池最大阻塞等待时间(使用负值表示没有限制)
        max-active: 8 # 连接池最大连接数(使用负值表示没有限制)
        min-idle: 0 # 连接池中的最小空闲连接

注意:spring.redis.cluster.nodes的值要修改成你自己的Redis节点所在的ip地址以及端口号

3.3 自定义Redis相关的组件

Redis默认存入的value是用jdk的序列化方式,这会导致中文乱码,我们自定义一个序列化器:

@Configuration
@Slf4j
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        log.info("RedisConnectionFactory class: {}", redisConnectionFactory.getClass());
        RedisSerializer<Object> serializer = redisSerializer();
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(serializer);
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(serializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    @Bean
    public RedisSerializer<Object> redisSerializer() {
        // 创建JSON序列化器
        Jackson2JsonRedisSerializer<Object> serializer =
                new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 必须设置,否则无法将json转化为对象,会转化为Map类型
        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,
                ObjectMapper.DefaultTyping.NON_FINAL);
        serializer.setObjectMapper(objectMapper);
        return serializer;
    }
}

3.4 封装Redis操作的类

/**
 * redis操作Service,
 * 对象和数组都以json形式进行存储
 */
public interface RedisService {

    /**
     * 存储数据
     * @param key
     * @param value
     */
    void set(String key, String value);

    /**
     * 获取数据
     * @param key
     * @return
     */
    Object get(String key);

    /**
     * 设置超时时间
     * @param key
     * @param expire
     * @return
     */
    boolean expire(String key, long time);

    /**
     * 删除数据
     * @param key
     */
    void remove(String key);

    /**
     * 自增操作
     * @param key
     * @param delta
     * @return
     */
    Long increment(String key, long delta);

}

3.5 封装Redis操作的实现类

/**
 * redis操作Service的实现类
 */
@Service
public class RedisServiceImpl implements RedisService {

    @Autowired
    private RedisTemplate<String, Object> stringRedisTemplate;

    @Override
    public void set(String key, String value) {
        stringRedisTemplate.opsForValue().set(key, value);
    }

    @Override
    public Object get(String key) {
        return stringRedisTemplate.opsForValue().get(key);
    }

    @Override
    public boolean expire(String key, long time) {
        return stringRedisTemplate.expire(key, time, TimeUnit.SECONDS);
    }

    @Override
    public void remove(String key) {
        stringRedisTemplate.delete(key);
    }

    @Override
    public Long increment(String key, long delta) {
        return stringRedisTemplate.opsForValue().increment(key, delta);
    }
}

3.6 测试

创建一些类用于测试效果

3.6.1 创建一个业务逻辑类

/**
 * @Author Androidla
 * @Date 2021/2/14 13:30
 * @Description
 **/
@Service
@Slf4j
public class TestServiceImpl {

    @Autowired
    private RedisService redisService;

    @Value("${redis.key.authCode}")
    private String REDIS_KEY_AUTH_CODE;

    @Value("${redis.expire.authCode}")
    private Long REDIS_EXPIRE_AUTH_CODE;


    public void testRedis() {
        log.info("test start ...");
        String key = REDIS_KEY_AUTH_CODE + "10010";
        redisService.set(key, "管理员权限");
        redisService.expire(key, REDIS_EXPIRE_AUTH_CODE);
        String value = (String) redisService.get(key);
        log.info("value is : {}", value);
    }
}

3.6.2 创建一个controller

/**
 * 测试redis是否整合成功
 */
@RestController
@RequestMapping("/test")
public class TestController {

    @Autowired
    private TestServiceImpl testService;

    @GetMapping("/redis")
    public String testRedis() {
        testService.testRedis();
        return "success";
    }

}

3.7 测试

用postman发送请求进行测试。并登录Redis Desktop Manager查看是否有效果

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐