redis 集群主从复制+哨兵,当主服务器宕机时,可以自动将从服务器切换为主服务器。提高系统的稳定性。

1.配置基本参数

需要的依赖:

<!-- springBoot 整合 redis 依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.9.0</version>
</dependency>
  • 在 yml 文件中配置基本参数
myjedis:
  redis:
    config:
      #哨兵集群节点
      nodes: 172.21.1.111:26379,172.21.2.111:26379
      masterName: mymaster
      password: 123456
      database: 8
      #总数
      maxTotal: 100
      #最大空闲数
      maxIdle: 50
      #最小空闲数
      minIdle: 10
      timeout: 60000
      maxWaitMillis: 5000
  • 创建配置类,使用 @ConfigurationProperties(prefix = "myjedis.redis.config") 注解读取yml 中配置,参数名称和路径要与yml文件中配置的对应。
@ConfigurationProperties(prefix = "myjedis.redis.config")
@Component
@Data
public class RedisConfigProperties {

    private String nodes;

    private String masterName;

    private String password;

    private int database;

    private String maxTotal;

    private String maxIdle;

    private String minIdle;

    private String timeout;

    private String maxWaitMillis;

    //以下单机redis配置信息
    private String mode;

    private String host;

    private String port;

    private String pass;
}

2.配置redis哨兵模式

@Configuration
public class RedisPoolConfig {

    /** 配置类信息 */
    @Autowired
    RedisConfigProperties redisConfigProperties;

    /** 初始化 jedis 连接池的配置 */
    @Bean
    public JedisPoolConfig getJedisPoolConfig(){
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxTotal(Integer.parseInt(redisConfigProperties.getMaxTotal()));
        jedisPoolConfig.setMaxIdle(Integer.parseInt(redisConfigProperties.getMaxIdle()));
        jedisPoolConfig.setMinIdle(Integer.parseInt(redisConfigProperties.getMinIdle()));
        jedisPoolConfig.setMaxWaitMillis(Integer.parseInt(redisConfigProperties.getMaxWaitMillis()));
        jedisPoolConfig.setTestOnReturn(true);
        jedisPoolConfig.setTestOnBorrow(true);
        return jedisPoolConfig;
    }

    /** 根据 jedis 连接池配置创建连接池 */
    @Bean
    public Pool<Jedis> getJedisPool(JedisPoolConfig jedisPoolConfig){
        
        //集群部署
        Set<String> nodeSet = new HashSet<>();
        String[] nodeStr = redisConfigProperties.getNodes().split(",");
        for(String node:nodeStr){
            nodeSet.add(node);
        }
        return new JedisSentinelPool(redisConfigProperties.getMasterName(), nodeSet, jedisPoolConfig, 2000,
                 2000, redisConfigProperties.getPassword(), redisConfigProperties.getDatabase());
    }

    /** 通过连接池获取 jedis 实例 */
    @Bean
    public Jedis getJedis(Pool<Jedis> jedisPool){
        return jedisPool.getResource();
    }
}

3.配置 ApplicationContextAware 实现类,获取spring容器中的实例 Bean。

@Component
public class ApplicationContextProvider implements ApplicationContextAware {

    /**
     * 上下文对象实例
     */
    public static  ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException {
        ApplicationContextProvider.applicationContext = context;
    }


    /**
     * 获取applicationContext
     * @return
     */
    public static  ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    /**
     * 通过class获取Bean.
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T getBean(Class<T> clazz){
        return getApplicationContext().getBean(clazz);
    }

    /**
     * 通过name获取 Bean.
     * @param name
     * @return
     */
    public static Object getBean(String name){
        return getApplicationContext().getBean(name);
    }
}

4.创建 JedisUtil 工具类,使用哨兵模式连接池。

public class JedisUtil {

    private static Pool<Jedis> jedisSentinelPool = ApplicationContextProvider.getBean(JedisSentinelPool.class);

    public static Pool<Jedis> getJedisSentinelPool() {
        if (jedisSentinelPool == null) {
            jedisSentinelPool = ApplicationContextProvider.getBean(JedisSentinelPool.class);
        }
        return jedisSentinelPool;
    }

    public static String get(String key) {
        String value = null;
        Jedis jedis = getJedisSentinelPool().getResource();
        if (jedis.exists(key)) {
            value = jedis.get(key);
            value = StringUtils.isNotBlank(value) && !"nil".equalsIgnoreCase(value) ? value : null;
        }
        jedis.close();
        return value;
    }

    public static long del(String key) {
        long result = 0;
        Jedis jedis = getJedisSentinelPool().getResource();
        if (jedis.exists(key)){
            result = jedis.del(key);
            log.debug("del {}", key);
        }else{
            log.debug("del {} not exists", key);
        }
        jedis.close();
        return result;
    }

    /**
     * 设置缓存
     * @param key 键
     * @param value 值
     * @return
     */
    public static String set(String key, String value) {
        return setex(key, value, 0);
    }

    /**
     * 设置缓存
     * @param key 键
     * @param value 值
     * @param cacheSeconds 超时时间,0为不超时
     * @return
     */
    public static String setex(String key, String value, int cacheSeconds) {
        Jedis jedis = getJedisSentinelPool().getResource();
        String result = null;
        if (cacheSeconds != 0) {
            jedis.setex(key, cacheSeconds, value);
        }else{
            result = jedis.set(key, value);
        }
        log.debug("set {} = {}", key, value);
        jedis.close();
        return result;
    }

    /**
     * 以秒为单位返回 key 的剩余过期时间
     * @param key 键
     * @return
     */
    public static long ttl(String key) {
        Jedis jedis = getJedisSentinelPool().getResource();
        long time = jedis.ttl(key);
        jedis.close();
        return time/1000;
    }
}
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐