问题】使用jediscluster连接redis集群,使用jedis执行redis命令,一些时候报Could not get a resource from the pool ,底层是连接超时异常,另一些时候则正常。
复现】时好时坏,有时失败后马上第二次请求相同命令即成功,进一步测试发现竟然与请求的key有关,极难定位问题原因。
1、考虑为客户端连接参数问题,结合网上各种经验调整JedisPoolConfig与JedisCluster构造方法参数,均无效。这里时间浪费最多,网上信息庞杂而大部分无用。
2、考虑为服务端单个redis节点配置问题,bind不到外网ip,这点很疑惑。
3、考虑为服务端密码问题,从slot槽的设计入手,假设在目前的客户端中,如果请求的key需要转发到其他节点,则因为没有验证密码而被其他节点拒绝。(实际上这是对部署脚本或者jedis集群客户端不信任)服务端取消密码构建集群后问题依旧,但已经接近问题答案。
原因排查依据:
(1)命令执行时好时坏,同一命令请求不同key,一些一直成功,其他一直不成功。
(2)查询所有节点的keys命令从未成功。
(3)debug之下发现不成功的命令请求的节点是内网ip,成功的命令是另一节点的外网ip。
原来,为了测试方便,我使用了外网ip构建集群。但是,官方提供的redis-trib.rb脚本带有极大的迷惑性,在构建时返回屏幕的信息正确,而自动生成的每个节点的nodes.conf中,表述自身的一行与预期均有出入,如下所示: