配置redis cluster,springboot远程连接linux上的redis cluster

远程连接代码

使用jedis,将默认的lettuce客户端除外
pom.xml

<!--redis-->
        <!--属性配置支持-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

        <!--默认继承lettuce,切换成jedis需要排除依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>io.lettuce</groupId>
                    <artifactId>lettuce-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>

读取节点的代码:

/**
 * redis 集群配置属性
 */
@Component
@Validated
@Data
@ConfigurationProperties(value = "spring.redis.cluster")
@PropertySource(value = "classpath:application.yml")
public class RedisClusterProperty {

    /**
     * 集群节点的主机名
     * spring.redis.cluster.nodes[0] =
     * spring.redis.cluster.nodes[1] =
     * spring.redis.cluster.nodes[1] =
     */
    private List<String> nodes;

}

将节点注入到连接工厂:

/**
 *
 * (1)将配置文件注入到RedisConnectionFactory
 * (2)redis集群必须redis 3.0以上版本的支持
 */
@Configuration
@Component
public class JedisClusterConfig {


    private static final Logger LOGGER = LoggerFactory.getLogger(JedisClusterConfig.class);

    @Autowired
    private RedisClusterProperty redisClusterProperty;



    /**
     * Spring Data Redis 1.7 支持redis集群
     * jedis集群配置
     *
     * @return
     */
    @Bean
    @Primary
    public RedisConnectionFactory connectionFactory() {

        RedisConnectionFactory redisConnectionFactory = new JedisConnectionFactory(
                new RedisClusterConfiguration(redisClusterProperty.getNodes()));

        return redisConnectionFactory;
    }

}

application.yml

##########################################################################
# redis
##########################################################################
spring:
  redis:
    cluster:
      # 只需要添加三个master节点
      nodes: 192.168.48.142:8000,192.168.48.142:8001,192.168.48.142:8002
      # 节点之间最大转发次数
      max-redirects: 2

工具类:redis无法序列化Object,可以用Jackson工具序列化即可。


/**
 * redis对object对象的封装
 */
@Configuration
@EnableCaching
public class RedisObjectUtils extends CachingConfigurerSupport {
    /**
     * 选择redis作为默认缓存工具
     * (2.x版本和1.5x版本传参数不一样,创建rediscach也不一样)
     *
     * @param redisConnectionFactory
     * @return
     */
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        return RedisCacheManager.create(redisConnectionFactory);
    }

    /**
     * 设置序列化和反序列化对象
     *
     * @param factory
     * @return
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        //设置序列化
        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);
        // 配置redisTemplate
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(factory);
        RedisSerializer<String> stringSerializer = new StringRedisSerializer();
        // key序列化
        redisTemplate.setKeySerializer(stringSerializer);
        // value序列化
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        // Hash key序列化
        redisTemplate.setHashKeySerializer(stringSerializer);
        // Hash value序列化
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    /**
     * 对hash类型的数据操作
     *
     * @param redisTemplate
     * @return
     */
    @Bean
    public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForHash();
    }

    /**
     * 对redis字符串类型数据操作
     *
     * @param redisTemplate
     * @return
     */
    @Bean
    public ValueOperations<String, Object> valueOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForValue();
    }

    /**
     * 对链表类型的数据操作
     *
     * @param redisTemplate
     * @return
     */
    @Bean
    public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForList();
    }

    /**
     * 对无序集合类型的数据操作
     *
     * @param redisTemplate
     * @return
     */
    @Bean
    public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForSet();
    }

    /**
     * 对有序集合类型的数据操作
     *
     * @param redisTemplate
     * @return
     */
    @Bean
    public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForZSet();
    }
}

工具类:操作string

/**
 * redis对string的操作的封装
 */
@Component
public class RedisStringUtils {

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    /**
     * 默认过期时长 1天,单位:秒
     */
    public static final long DEFAULT_EXPIRE = 60 * 60 * 24;

    /**
     * 不设置过期时长
     */
    public static final long NOT_EXPIRE = -1;

    /**
     * 判断key是否存在
     *
     * @param key
     * @return
     */
    public boolean existsKey(String key) {
        return redisTemplate.hasKey(key);
    }

    /**
     * 重名名key,如果newKey已经存在,则newKey的原值被覆盖
     *
     * @param oldKey
     * @param newKey
     */
    public void renameKey(String oldKey, String newKey) {
        redisTemplate.rename(oldKey, newKey);
    }

    /**
     * newKey不存在时才重命名
     *
     * @param oldKey
     * @param newKey
     * @return 修改成功返回true
     */
    public boolean renameKeyNotExist(String oldKey, String newKey) {
        return redisTemplate.renameIfAbsent(oldKey, newKey);
    }

    /**
     * 删除key
     *
     * @param key
     */
    public void deleteKey(String key) {
        redisTemplate.delete(key);
    }

    /**
     * 删除多个key
     *
     * @param keys
     */
    public void deleteKey(String... keys) {
        Set<String> kSet = Stream.of(keys).collect(Collectors.toSet());
        redisTemplate.delete(kSet);
    }

    /**
     * 删除Key的集合
     *
     * @param keys
     */
    public void deleteKey(Collection<String> keys) {
        Set<String> kSet = keys.stream().collect(Collectors.toSet());
        redisTemplate.delete(kSet);
    }

    /**
     * 设置key的生命周期
     *
     * @param key
     * @param time
     * @param timeUnit
     */
    public void expireKey(String key, long time, TimeUnit timeUnit) {
        redisTemplate.expire(key, time, timeUnit);
    }

    /**
     * 指定key在指定的日期过期
     *
     * @param key
     * @param date
     */
    public void expireKeyAt(String key, Date date) {
        redisTemplate.expireAt(key, date);
    }

    /**
     * 查询key的有效期
     *
     * @param key
     * @param timeUnit
     * @return
     */
    public long getKeyExpire(String key, TimeUnit timeUnit) {
        return redisTemplate.getExpire(key, timeUnit);
    }

    /**
     * 将key设置为永久有效
     *
     * @param key
     */
    public void persistKey(String key) {
        redisTemplate.persist(key);
    }

    /**
     * 设置值
     * @param key
     * @param value
     */
    public void opsForValueSet(String key, String value) {
        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * 获取值
     * @param key
     */
    public String opsForValueGet(String key) {
        return redisTemplate.opsForValue().get(key);
    }
}

程序报错:

org.springframework.data.redis.TooManyClusterRedirectionsException: No more cluster attempts left.; nested exception is redis.clients.jedis.exceptions.JedisClusterMaxAttemptsException: No more cluster attempts left.

	at org.springframework.data.redis.connection.jedis.JedisExceptionConverter.convert(JedisExceptionConverter.java:55)
	at org.springframework.data.redis.connection.jedis.JedisExceptionConverter.convert(JedisExceptionConverter.java:42)
	at org.springframework.data.redis.PassThroughExceptionTranslationStrategy.translate(PassThroughExceptionTranslationStrategy.java:44)

百度出了以下解决方案:
1、redis.conf里面的”bind IP地址“是限制访问IP的,需要注释掉

2、使用ruby命令开启集群,要使用公网IP,如下:

#注意一定不要用127.0.0.1这种本地的局域ip,要用公网ip
ruby redis-trib.rb  create --replicas 1 公网IP:7000 公网IP:7001 公网IP:7002 公网IP:7003 公网IP:7004 公网IP:7005

上面的:–replicas 1 公网IP:7000 公网IP:7001 … … 都要使用非本地的其他设备在局域网内能访问到的ip,不要使用127.0.0.1。(我的就是这里弄错了,调整这里之后解决了)

3、如果执行2步骤一直在“Waiting for the cluster to join…”,那肯定是你端口没有开启,不要质疑,这里的端口不是7000-7005,而是17000-17005,因为redis设置集群的端口号是”redis端口+10000“,这个非常重要。

开始尝试1------修改redis端口

因为配置文件原本就没有binding 127.0.0.1,排除这种可能。
在这里插入图片描述
异常如下:

org.springframework.data.redis.RedisConnectionFailureException: No reachable node in cluster; nested exception is redis.clients.jedis.exceptions.JedisNoReachableClusterNodeException: No reachable node in cluster

	at org.springframework.data.redis.connection.jedis.JedisExceptionConverter.convert(JedisExceptionConverter.java:65)
	at org.springframework.data.redis.connection.jedis.JedisExceptionConverter.convert(JedisExceptionConverter.java:42)
	at org.springframework.data.redis.PassThroughExceptionTranslationStrategy.translate(PassThroughExceptionTranslationStrategy.java:44)
	at org.springframework.data.redis.FallbackExceptionTranslationStrategy.translate(FallbackExceptionTranslationStrategy.java:42)

开始尝试2---- 重新搭建redis cluster

参考教程:
https://blog.csdn.net/u010649766/article/details/79629526
https://blog.51cto.com/13544424/2058280

中途因为原来的配置导致节点之间互相已经建立了联系,可以删除他们的rbd和config文件即可。

最终问题解决了。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值