JedisCluster Client 操作集群 Too many Cluster redirections?

redis.clients.jedis.exceptions.JedisClusterMaxRedirectionsException: Too many Cluster redirections?

使用flink往redis集群写数据时暴露的问题,通过正常的JedisCluster类进行连接操作
private static JedisCluster jedisCluster;

jedisCluster = new JedisCluster(hostAndPortSet,connectionTimeout,soTimeout,maxAttempts,password,config);

异常堆栈信息如下:

在这里插入图片描述

flink集群和redis集群网络是不通的,我们是通过一台机器用nginx进行中转

在一台网络和redis集群通的机器上测试过,也是通过中转网络进行操作的,发现是没有问题,也通过redis shell客户端使用代理端口进行连接,也把代码copy出来放在服务器上测试,发现没啥问题的。当时不知道网络是通的,总以为是通过中转网络进行操作redis集群的,看报错,又不是那种**No reachable node in cluster**连接不上的问题,思路就往nginx方向想了,集群参数redis.maxAttempts用的默认值5,这个值也尝试调大过,在设置为0的时候会抛出No reachable node in cluster异常,于是想着是不是nginx多次转发的问题,于是在测试环境也构建一套nginx服务,并且进行二次转发。nginx配置如下。发现问题还是没有解决。
nginx-stream
#redis代理测试
stream {
     upstream redis1 {
          #redis真实访问地址
          server  machine1:6380 max_fails=3 fail_timeout=30s;
     }
     upstream redis2 {
          #redis真实访问地址
          server  machine1:6381 max_fails=3 fail_timeout=30s;
     }
     upstream redis3 {
          #redis真实访问地址
          server  machine2:6380 max_fails=3 fail_timeout=30s;
     }
     upstream redis4 {
          #redis真实访问地址
          server  machine2:6381 max_fails=3 fail_timeout=30s;
     }
     upstream redis5 {
          #redis真实访问地址
          server  machine3:6380 max_fails=3 fail_timeout=30s;
     }
     upstream redis6 {
          #redis真实访问地址
          server  machine3:6381 max_fails=3 fail_timeout=30s;
     }

     server {
          #外网监听地址
          listen 7001;
          #代理连接超时时间
          proxy_connect_timeout 5s;
          #代理超时时间
          proxy_timeout 300s;
          #代理名称
          proxy_pass redis1;
     }
     server {
          #外网监听地址
          listen 7002;
          #代理连接超时时间
          proxy_connect_timeout 5s;
          #代理超时时间
          proxy_timeout 300s;
          #代理名称
          proxy_pass redis2;
     }
     server {
          #外网监听地址
          listen 7003;
          #代理连接超时时间
          proxy_connect_timeout 5s;
          #代理超时时间
          proxy_timeout 300s;
          #代理名称
          proxy_pass redis3;
     }
     server {
          #外网监听地址
          listen 7004;
          #代理连接超时时间
          proxy_connect_timeout 5s;
          #代理超时时间
          proxy_timeout 300s;
          #代理名称
          proxy_pass redis4;
     }
     server {
          #外网监听地址
          listen 7005;
          #代理连接超时时间
          proxy_connect_timeout 5s;
          #代理超时时间
          proxy_timeout 300s;
          #代理名称
          proxy_pass redis5;
     }
     server {
          #外网监听地址
          listen 7006;
          #代理连接超时时间
          proxy_connect_timeout 5s;
          #代理超时时间
          proxy_timeout 300s;
          #代理名称
          proxy_pass redis6;
     }

     upstream redis7 {
          #redis真实访问地址
          server  machine1:7001 max_fails=3 fail_timeout=30s;
     }
     upstream redis8 {
          #redis真实访问地址
          server  machine1:7002 max_fails=3 fail_timeout=30s;
     }
     upstream redis9 {
          #redis真实访问地址
          server  machine2:7003 max_fails=3 fail_timeout=30s;
     }
     upstream redis10 {
          #redis真实访问地址
          server  machine2:7004 max_fails=3 fail_timeout=30s;
     }
     upstream redis11 {
          #redis真实访问地址
          server  machine3:7005 max_fails=3 fail_timeout=30s;
     }
     upstream redis12 {
          #redis真实访问地址
          server  machine3:7006 max_fails=3 fail_timeout=30s;
     }
     server {
          #外网监听地址
          listen 7007;
          #代理连接超时时间
          proxy_connect_timeout 5s;
          #代理超时时间
          proxy_timeout 300s;
          #代理名称
          proxy_pass redis7;
     }
     server {
          #外网监听地址
          listen 7008;
          #代理连接超时时间
          proxy_connect_timeout 5s;
          #代理超时时间
          proxy_timeout 300s;
          #代理名称
          proxy_pass redis8;
     }
     server {
          #外网监听地址
          listen 7009;
          #代理连接超时时间
          proxy_connect_timeout 5s;
          #代理超时时间
          proxy_timeout 300s;
          #代理名称
          proxy_pass redis9;
     }
     server {
          #外网监听地址
          listen 7010;
          #代理连接超时时间
          proxy_connect_timeout 5s;
          #代理超时时间
          proxy_timeout 300s;
          #代理名称
          proxy_pass redis10;
     }
     server {
          #外网监听地址
          listen 7011;
          #代理连接超时时间
          proxy_connect_timeout 5s;
          #代理超时时间
          proxy_timeout 300s;
          #代理名称
          proxy_pass redis11;
     }
     server {
          #外网监听地址
          listen 7012;
          #代理连接超时时间
          proxy_connect_timeout 5s;
          #代理超时时间
          proxy_timeout 300s;
          #代理名称
          proxy_pass redis12;
     }
}

整的头皮发麻

后面思路往JedisCluster Client方向思考,看了下JedisCluster的源码,分析如下

1.JedisCluster在初始化的时候用代理的ip和端口和ip进行初始化连接

2.初始化后会使用redis的**cluter nodes**命令将,集群的主从信息,包括solt信息进行缓存

3.在使用redis进行set命令的时候,会根据CRC16得到slot从pool中找到对应的某台机器ip和端进行连接,再写入数据,读的话会先匹配从机进行连接

4.核心就在这,实际上JedisCluster保存的是真实的redis集群地址,并不是代理的,在操作redis的时候发现网络不通,所以就抛出本文的这种的异常

具体缓存的集群信息可以打印出来看看

Map<String, JedisPool> clusterNodes = jedisCluster.getClusterNodes();
System.out.println(clusterNodes);
在测试的时候,我们有三台机器,默认防火墙是关掉的,所以不会抛这种问题,网络也是通的,没有复现生产上的问题。

在开启某一台机器的防火墙后,发现会问题和本文一样,初始化JedisCluster Client是没有问题的,在对redis进行操作的时候,就会抛出这种异常。如果在初始化JedisCluster Client后不去对集群进行操作,发现程序是不会报错的,也不会停止运行的。就算三台机器开启两台防火墙,只留一台不开,网络通,在初始化JedisCluster Client的时候也是不会抛出异常的。

参考1
参考2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值