SpringBoot中使用集群版Redis

发布于:2025-05-14 ⋅ 阅读:(18) ⋅ 点赞:(0)

1.单机版配置

我们先看默认SpringBoot中引入Redis时一般的流程.

在Spring Boot应用启动时,RedisAutoConfiguration类会在Spring容器初始化过程中被自动注入。具体过程如下:

  1. 启动应用:当应用程序启动时,Spring Boot会扫描类路径中的所有依赖,并通过反射加载带有@Configuration等注解的类。
  2. 处理自动配置@EnableAutoConfiguration注解是核心,它会让Spring Boot根据项目中存在的依赖和配置,推断出需要的自动配置类。Spring Boot会读取META-INF/spring.factories文件,该文件定义了多个自动装配依赖的配置类,其中就包括RedisAutoConfiguration
  3. 条件判断与加载RedisAutoConfiguration类上通常会有条件注解,如@ConditionalOnClass,该注解会判断当前配置类对应的类(如Redis客户端相关类)是否在项目中存在。如果存在,就会创建并加载RedisAutoConfiguration这个配置类。
  4. 创建相关Bean:加载完成后,RedisAutoConfiguration会根据环境配置创建相应的Bean,如RedisConnectionFactoryRedisTemplate等,并将这些Bean注入到Spring容器中。

2.集群版自定义配置

现在我们要使用集群版了,那肯定就得重新定制一些配置,用来满足我们的需求。

2.1 resources\META-INFO中的spring.factories中增加我们需要自定义的类,我们增加如下三个类来满足我们的需求。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.common.redis.configure.RedisConfig,\
  com.common.redis.configure.ClusterRedisConfig,\
  com.common.redis.service.RedisService

这三个类中, RedisConfig适配单机版的redis, ClusterRedisConfig适配集群版的redis,RedisService封装了RedisTemplate作为服务类可以引入到我们项目中直接使用. 其中单机版和集群版配置可以通过配置文件灵活配置.

2.2 ClusterRedisConfig类,用来设置集群配置。
/**
 * 集群版 Redis缓存配置类,如需启用请在配置文件中新增:spring.redis.model=cluster
 */
@Configuration
@ConditionalOnClass({JedisCluster.class})
@AutoConfigureBefore(RedisAutoConfiguration.class)
@ConditionalOnProperty(prefix = "spring.redis", name = "model", havingValue = "cluster")
public class ClusterRedisConfig {

    @Autowired
    private RedisProperties redisProperties;

    @Bean
    public RedisClusterConfiguration redisClusterConfiguration() {
        RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration(redisProperties.getCluster().getNodes());
        redisClusterConfiguration.setPassword(redisProperties.getPassword());
        return redisClusterConfiguration;
    }

    @Bean
    public RedisConnectionFactory redisConnectionFactory(RedisClusterConfiguration redisClusterConfiguration) {

        ClusterTopologyRefreshOptions clusterTopologyRefreshOptions = ClusterTopologyRefreshOptions.builder()
                .enablePeriodicRefresh()
                .enableAllAdaptiveRefreshTriggers()
                .refreshPeriod(Duration.ofSeconds(5))
                .build();
        ClusterClientOptions clusterClientOptions = ClusterClientOptions.builder()
                .topologyRefreshOptions(clusterTopologyRefreshOptions).build();
        LettuceClientConfiguration lettuceClientConfiguration = LettuceClientConfiguration.builder()
                .readFrom(ReadFrom.REPLICA_PREFERRED)
                .clientOptions(clusterClientOptions).build();
        return new LettuceConnectionFactory(redisClusterConfiguration, lettuceClientConfiguration);
    }

    /**
     * 设置数据存入redis 的序列化方式
     * </br>redisTemplate序列化默认使用的jdkSerializeable,存储二进制字节码,导致key会出现乱码,所以自定义
     * 序列化类
     *
     * @paramredisConnectionFactory
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);

        FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);

        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        serializer.setObjectMapper(mapper);

        // 使用StringRedisSerializer来序列化和反序列化redis的key值
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(serializer);

        // Hash的key也采用StringRedisSerializer的序列化方式
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(serializer);

        template.afterPropertiesSet();
        return template;
    }

}
2.3 FastJson2JsonRedisSerializer 类 ,使用StringRedisSerializer来序列化和反序列化redis的key值.
/**
 * Redis使用FastJson序列化
 *
 * @author dkmk
 */
public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T> {
    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

    static {
        ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
    }

    @SuppressWarnings("unused")
    private ObjectMapper objectMapper = new ObjectMapper();
    private Class<T> clazz;

    public FastJson2JsonRedisSerializer(Class<T> clazz) {
        super();
        this.clazz = clazz;
    }

    @Override
    public byte[] serialize(T t) throws SerializationException {
        if (t == null) {
            return new byte[0];
        }
        return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
    }

    @Override
    public T deserialize(byte[] bytes) throws SerializationException {
        if (bytes == null || by

网站公告

今日签到

点亮在社区的每一天
去签到