redis NoRouteToHostException: 没有到主机的路由

最近项目中使用redis遇到了一个异常(redis版本3.2.3),分享出来供大家参考:

异常如下:

Caused by: redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
    at redis.clients.util.Pool.getResource(Pool.java:53)
    at redis.clients.jedis.JedisPool.getResource(JedisPool.java:226)
    at redis.clients.jedis.JedisSlotBasedConnectionHandler.getConnectionFromSlot(JedisSlotBasedConnectionHandler.java:66)
    at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:116)
    at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:141)
    at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:141)
    at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:141)
    at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:141)
    at redis.clients.jedis.JedisClusterCommand.runBinary(JedisClusterCommand.java:60)
    at redis.clients.jedis.BinaryJedisCluster.hkeys(BinaryJedisCluster.java:448)
    at org.springframework.data.redis.connection.jedis.JedisClusterConnection.hKeys(JedisClusterConnection.java:2388)
    ... 14 more
Caused by: redis.clients.jedis.exceptions.JedisConnectionException: java.net.NoRouteToHostException: 没有到主机的路由
    at redis.clients.jedis.Connection.connect(Connection.java:207)
    at redis.clients.jedis.BinaryClient.connect(BinaryClient.java:93)
    at redis.clients.jedis.BinaryJedis.connect(BinaryJedis.java:1767)
    at redis.clients.jedis.JedisFactory.makeObject(JedisFactory.java:106)
    at org.apache.commons.pool2.impl.GenericObjectPool.create(GenericObjectPool.java:836)
    at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:457)
    at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:361)
    at redis.clients.util.Pool.getResource(Pool.java:49)
    ... 24 more
Caused by: java.net.NoRouteToHostException: 没有到主机的路由
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
    at java.net.Socket.connect(Socket.java:589)
    at redis.clients.jedis.Connection.connect(Connection.java:184)
    ... 31 more

看到异常第一反应是网络不通或者redis没有启动

查看后,发现redis启动的,但是配置了防火墙,然后加上了白名单

但是还是不能访问。

继续研究发现redis HA 是通过haproxy+redis实现的。访问接口提供了haproxy的接口。haproxy中映射了多个redis。

redis实例所在的主机也配置了防火墙,是不是应用直接访问了redis实例,而没有通过haproxy间接访问redis。

通过查看代码确实如此。

应用通过spring配置了集群模式访问redis。

应用启动的时候通过haproxy访问redis,并执行CLUSTER SLOTS命令,这个命令是redis3.0出现的,用来获取redis集群的所有节点信息。代码如下:

然后将节点信息放到连接池中,这样以后使用redis的时候,直接连接节点,而不再通过haproxy,当然也可以在配置中直接连接一个redis节点,不用连接haproxy,但是haproxy在第一次连接的时候可以在多个redis节点中找到一个有效的节点并返回,所以haproxy还是有用的。

使用redis时,从pool中取出一个,而且pool中多个redis还要shuffle一下,确保取出的节点是随机的一个,然后测试节点是否有效,如果无效,继续取下一个,直到取完。代码如下:

spring redis集群配置

这个配置中只配置了一个节点,实际这应该至少配置两个节点,这样应用的可用性会更高一些,haproxy也可以不用了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值