jedis客戶端報Too many Cluster redirections異常?很困擾?不知道是什麼問題?請看如下文章,爲你一一解答。java
請求間歇性穿透緩存。redis
redis.clients.jedis.exceptions.JedisClusterMaxRedirectionsException: Too many Cluster redirections? at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:34) at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:85) at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:68) at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:85) at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:68) at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:85) at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:68) at redis.clients.jedis.JedisClusterCommand.run(JedisClusterCommand.java:29) at redis.clients.jedis.JedisCluster.set(JedisCluster.java:75)
經過分析如下代碼得知錯誤緣由:緩存
private T runWithRetries(byte[] key, int redirections, boolean tryRandomNode, boolean asking) { if (redirections <= 0) { throw new JedisClusterMaxRedirectionsException("Too many Cluster redirections?"); } Jedis connection = null; try { if (asking) { // TODO: Pipeline asking with the original command to make it // faster.... connection = askConnection.get(); connection.asking(); // if asking success, reset asking flag asking = false; } else { if (tryRandomNode) { connection = connectionHandler.getConnection(); } else { connection = connectionHandler.getConnectionFromSlot(JedisClusterCRC16.getSlot(key)); } } return execute(connection); } catch (JedisConnectionException jce) { if (tryRandomNode) { // maybe all connection is down throw jce; } // release current connection before recursion releaseConnection(connection); connection = null; // retry with random connection return runWithRetries(key, redirections - 1, true, asking); } catch (JedisRedirectionException jre) { // if MOVED redirection occurred, if (jre instanceof JedisMovedDataException) { // it rebuilds cluster's slot cache // recommended by Redis cluster specification this.connectionHandler.renewSlotCache(connection); } // release current connection before recursion or renewing releaseConnection(connection); connection = null; if (jre instanceof JedisAskDataException) { asking = true; askConnection.set(this.connectionHandler.getConnectionFromNode(jre.getTargetNode())); } else if (jre instanceof JedisMovedDataException) { } else { throw new JedisClusterException(jre); } return runWithRetries(key, redirections - 1, false, asking); } finally { releaseConnection(connection); } }
當發生JedisConnectionException或者JedisRedirectionException時,會從新調用當前方法。網絡
與該錯誤關係不大。dom
由於該錯誤是:鏈接Redis錯誤,若是鏈接第一個節點失敗,嘗試第二個節點也失敗,會直接推斷成所有節點down掉拋出錯誤,中斷處理。ui
和該錯誤關係很大。this
對該錯誤處理時,並處理了如下兩個異常:
JedisMovedDataException:節點重置/遷移後,會拋出該異常
JedisAskDataException: 數據遷移,發生asking問題, 獲取asking的Jediscode
今後推斷,發生該問題的緣由爲:ip
所以,致使該錯誤的緣由可爲:ci