SpringBoot项目如何接入Redis集群

配置参数

因为这篇文章不介绍 Redis 集群的搭建,这里我们假设已经有了一个 Redis 的集群环境,我们项目中需要调整以下几个部分

  • 修改配置参数,集群的节点和密码配置;

  • 确保引入的 Jedis 版本支持设置密码,spring-data-redis 1.8 以上,SpringBoot 1.5 以上才支持设置密码;

  • SpringBoot项目如何接入Redis集群:7个步骤一网打尽

    注入 RedisTemplate;

  • 编写工具类;

  • 修改配置参数############### Redis 集群配置 #########################
    spring.custome.redis.cluster.nodes=172.20.0.1:7001,172.20.0.2:7002,172.20.0.3:7003
    spring.custome.redis.cluster.max-redirects=3
    spring.custome.redis.cluster.max-active=500
    spring.custome.redis.cluster.max-wait=-1
    spring.custome.redis.cluster.max-idle=500
    spring.custome.redis.cluster.min-idle=20
    spring.custome.redis.cluster.timeout=3000
    spring.custome.redis.cluster.password=redis.cluster.password 引入依赖(如果需要)

    确保 SpringBoot 的版本大于 1.4.x 如果不是的话,采用如下配置,先排除 SpringBoot 中旧版本 Jedis 和 spring-data-redis,再依赖高版本的 Jedis 和 spring-data-redis。


    org.springframework.boot
    spring-boot-starter-data-redis






    redis.clients
    jedis




    org.springframework.data
    spring-data-redis










    redis.clients
    jedis
    2.9.0




    org.springframework.data
    spring-data-redis
    1.8.0.RELEASE 注入 RedisTemplate

    注入 RedisTemplate 我们需要三个组件,分别是JedisConnectionFactory 、RedisClusterConfiguration、JedisPoolConfig,下面是注入RedisTempalte 的代码。先根据配置创建 JedisConnectFactory 同时需要配置 RedisClusterConfiguration、JedisPoolConfig,最后将JedisConnectionFactory 返回用于创建RedisTemplate

    import com.fasterxml.jackson.annotation.JsonAutoDetect;

    import com.fasterxml.jackson.annotation.PropertyAccessor;

    import com.fasterxml.jackson.databind.ObjectMapper;

    import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

    import org.springframework.beans.factory.annotation.Value;

    import org.springframework.context.annotation.Bean;

    import org.springframework.context.annotation.Primary;

    import org.springframework.data.redis.connection.RedisClusterConfiguration;

    import org.springframework.data.redis.connection.RedisNode;

    import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;

    import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;

    import org.springframework.data.redis.core.RedisTemplate;

    import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;

    import org.springframework.data.redis.serializer.StringRedisSerializer;



    import java.time.Duration;

    import java.util.ArrayList;

    import java.util.List;



    public class RedisClusterConfig {


    @Bean(name = "
    redisTemplate"
    )
    @Primary
    public RedisTemplate redisClusterTemplate(@Value("
    ${spring.custome.redis.cluster.nodes}"
    ) String host,
    @Value("
    ${spring.custome.redis.cluster.password}"
    ) String password,
    @Value("
    ${spring.custome.redis.cluster.timeout}"
    ) long timeout,
    @Value("
    ${spring.custome.redis.cluster.max-redirects}"
    ) int maxRedirect,
    @Value("
    ${spring.custome.redis.cluster.max-active}"
    ) int maxActive,
    @Value("
    ${spring.custome.redis.cluster.max-wait}"
    ) int maxWait,
    @Value("
    ${spring.custome.redis.cluster.max-idle}"
    ) int maxIdle,
    @Value("
    ${spring.custome.redis.cluster.min-idle}"
    ) int minIdle) {


    JedisConnectionFactory connectionFactory = jedisClusterConnectionFactory(host, password,
    timeout, maxRedirect, maxActive, maxWait, maxIdle, minIdle);

    return createRedisClusterTemplate(connectionFactory);

    }


    private JedisConnectionFactory jedisClusterConnectionFactory(String host, String password,
    long timeout, int maxRedirect, int maxActive, int maxWait, int maxIdle, int minIdle) {
    RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration();

    List nodeList = new ArrayList();

    String[] cNodes = host.split("
    ,"
    );

    //分割出集群节点
    for (String node : cNodes) {
    String[] hp = node.split("
    :"
    );

    nodeList.add(new RedisNode(hp[0], Integer.parseInt(hp[1])));

    }
    redisClusterConfiguration.setClusterNodes(nodeList);

    redisClusterConfiguration.setPassword(password);

    redisClusterConfiguration.setMaxRedirects(maxRedirect);



    // 连接池通用配置
    GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();

    genericObjectPoolConfig.setMaxIdle(maxIdle);

    genericObjectPoolConfig.setMaxTotal(maxActive);

    genericObjectPoolConfig.setMinIdle(minIdle);

    genericObjectPoolConfig.setMaxWaitMillis(maxWait);

    genericObjectPoolConfig.setTestWhileIdle(true);

    genericObjectPoolConfig.setTimeBetweenEvictionRunsMillis(300000);



    JedisClientConfiguration.DefaultJedisClientConfigurationBuilder builder = (JedisClientConfiguration.DefaultJedisClientConfigurationBuilder) JedisClientConfiguration
    .builder();

    builder.connectTimeout(Duration.ofSeconds(timeout));

    builder.usePooling();

    builder.poolConfig(genericObjectPoolConfig);

    JedisConnectionFactory connectionFactory = new JedisConnectionFactory(redisClusterConfiguration, builder.build());

    // 连接池初始化
    connectionFactory.afterPropertiesSet();



    return connectionFactory;

    }


    private RedisTemplate createRedisClusterTemplate(JedisConnectionFactory redisConnectionFactory) {
    RedisTemplate redisTemplate = new RedisTemplate();

    redisTemplate.setConnectionFactory(redisConnectionFactory);



    Jackson2JsonRedisSerializer<
    Object>
    jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);

    ObjectMapper om = new ObjectMapper();

    om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);

    om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

    jackson2JsonRedisSerializer.setObjectMapper(om);



    StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

    // key采用String的序列化方式
    redisTemplate.setKeySerializer(stringRedisSerializer);

    // hash的key也采用String的序列化方式
    redisTemplate.setHashKeySerializer(stringRedisSerializer);

    // value序列化方式采用jackson
    redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);

    // hash的value序列化方式采用jackson
    redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);

    redisTemplate.afterPropertiesSet();



    return redisTemplate;

    }
    } 编写工具类

    其实到这里基本上已经完成了,我们可以看到 SpringBoot 项目接入 Redis 集群还是比较简单的,而且如果之前单机环境就是采用RedisTemplate 的话,现在也就不需要编写工具类,之前的操作依旧有效。

    /**
    * 删除KEY
    * @param key
    * @return
    */
    public boolean delete(String key) {
    try {
    return getTemplate().delete(key);

    } catch (Exception e) {
    log.error("
    redis hasKey() is error"
    );

    return false;

    }
    }


    /**
    * 普通缓存获取
    *
    * @param key 键
    * @return 值
    */
    public Object get(String key) {


    return key == null ? null : getTemplate().opsForValue().get(key);

    }


    /**
    * 普通缓存放入
    *
    * @param key 键
    * @param value 值
    * @return true成功 false失败
    */
    public boolean set(String key, Object value) {


    try {
    getTemplate().opsForValue().set(key, value);

    return true;

    } catch (Exception e) {
    log.error("
    redis set() is error"
    );

    return false;

    }


    }


    /**
    * 普通缓存放入并设置时间
    *
    * @param key 键
    * @param value 值
    * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
    * @return true成功 false 失败
    */
    public boolean set(String key, Object value, long time) {
    try {
    if (time >
    0) {
    getTemplate().opsForValue().set(key, value, time, TimeUnit.SECONDS);

    } else {
    set(key, value);

    }
    return true;

    } catch (Exception e) {
    log.error("
    redis set() is error"
    );

    return false;

    }
    }


    /**
    * 计数器
    *
    * @param key 键
    * @return 值
    */
    public Long incr(String key) {


    return getTemplate().opsForValue().increment(key);

    }


    public Long incrBy(String key, long step) {


    return getTemplate().opsForValue().increment(key, step);

    }


    /**
    * HashGet
    *
    * @param key 键 不能为null
    * @param item 项 不能为null
    * @return 值
    */
    public Object hget(String key, String item) {


    return getTemplate().opsForHash().get(key, item);

    }


    /**
    * 获取hashKey对应的所有键值
    *
    * @param key 键
    * @return 对应的多个键值
    */
    public Map hmget(String key) {


    return getTemplate().opsForHash().entries(key);

    }


    /**
    * 获取hashKey对应的批量键值
    * @param key
    * @param values
    * @return
    */
    public List<
    Object>
    hmget(String key, List values) {


    return getTemplate().opsForHash().multiGet(key, values);

    }

    随着互联网的不断发展,大数据和云计算已经成为了时代新的变革。于此同时,Redis作为速度最快的内存数据库之一,已经在Web开发中逐渐获得了支持和认可。本文将介绍如何使用SpringBoot项目快速接入Redis集群,在构建高性能Web应用的同时,为读取和传输数据提供更快的响应速度。
    1. 安装Redis集群
    首先,将Redis集群下载到本地并解压缩,选定一个目录存储到本地。打开终端并进入到目录中,开始启动Redis。
    2. 配置Redis集群
    在Redis配置文件中,首先确定Redis的端口号。设置master的数量和slave的数量,请确保他们有适当的主从关系。考虑到集群的可扩展性,您可以通过增加主机数和Redis服务器数量来实现水平扩展。
    3. 连接Redis集群
    首先,我们需要使用Spring的RedisTemplate来完成Redis的连接。在这里,我们不需要关心连接是由Java代码还是由Spring Datasource实现,这取决于您的实际需求。
    4. 编写RedisService实现类
    RedisService实现类是操作Redis时用到的实现类。我们首先需要定义一个实例的空值,并在实现类中添加必要的注释。使用Spring的RedisTemplate时,我们需要为不同的数据类型添加对应的序列化器。
    5. 编写RedisKeyUtils类
    RedisKeyUtils类是SpringBoot项目中用到的重要辅助类,它用于设置以前缀和后缀为组合的键名,以便于在整个集群中进行快速访问。其功能类似于Spring的DatasourceUtils,但与之不同的是RedisKeyUtils仅用于创建和操作Redis中的键名。
    6. 编写RedisThreadPool类
    在SpringBoot项目中,Redis连接池也是一个重要的组件,它可以避免频繁地打开和关闭Redis连接。在RedisThreadPool类中,我们可以设置线程池的大小,并通过設置线程池中的生存时间来实现预防内存泄漏。
    7. 测试Redis集群
    在调用Redis集群时,我们需要进行单元测试。为了确保Redis集群的配置和方法调用正确,我们可以在RedisServiceImplTest中编写单元测试示例。在测试红包抢购应用程序中,创建了10个线程并发地访问向Redis写入和读取元素的方法,通过这种方式测试和检验将机器的性能发挥到极致。
    通过上述7个步骤,SpringBoot项目和Redis集群的相关配置和接入已完成。这项任务可以使你的Web应用程序更加快速、可靠和具有竞争力,从而为您的业务增强了核心竞争力。在未来的应用程序开发中,相信你会发现它的无价之处。