视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
redis的一个诡异问题排查
2020-11-09 13:10:33 责编:小采
文档


前段时间,由于线上redis服务器的内存使用率达到了机器总内存的50%以上,导致内存数据的dump持久化一直失败。扩展到多台redis后,应用系统访问redis时, 在业务量较少时,时不时会出现以下异常,当业务量较大,redis访问频率很高时,却不会发生这个异常 ,一

前段时间,由于线上redis服务器的内存使用率达到了机器总内存的50%以上,导致内存数据的dump持久化一直失败。扩展到多台redis后,应用系统访问redis时,在业务量较少时,时不时会出现以下异常,当业务量较大,redis访问频率很高时,却不会发生这个异常,一时觉得很诡异。

redis.clients.jedis.exceptions.JedisConnectionException:?It?seems?like?server?has?closed?the?connection.
at?redis.clients.util.RedisInputStream.readLine(RedisInputStream.java:90)?~[jedis-2.1.0.jar:na]
at?redis.clients.jedis.Protocol.processInteger(Protocol.java:110)?~[jedis-2.1.0.jar:na]
at?redis.clients.jedis.Protocol.process(Protocol.java:70)?~[jedis-2.1.0.jar:na]
at?redis.clients.jedis.Protocol.read(Protocol.java:131)?~[jedis-2.1.0.jar:na]
at?redis.clients.jedis.Connection.getIntegerReply(Connection.java:188)?~[jedis-2.1.0.jar:na]
at?redis.clients.jedis.Jedis.sismember(Jedis.java:1266)?~[jedis-2.1.0.jar:na]

看提示,应该是服务端主动关闭了连接。查看了新上线的redis服务器的配置,有这么一项:

# Close the connection after a client is idle for N seconds (0 to disable)
timeout 120

这项配置指的是客户端连接空闲超过多少秒后,服务端主动关闭连接,默认值0表示服务端永远不主动关闭。而op人员把服务器端的超时时间设置为了120秒。这就解释了发生这个异常的原因。客户端使用了一个连接池管理访问redis的所有连接,这些连接是长连接,当业务量较小时,客户端部分连接使用率较低,当两次使用之间的间隔超过120秒时,redis服务端就主动关闭了这个连接,而等客户端下次再使用这个连接对象时,发现服务端已经关闭了连接,进而报错。

解决方案有两种:

1. 在redis-cli下直接修改redis 的配置,把timeout改回为0,无需重启redis即可直接生效。

2. 修改应用系统代码,设置连接的最大空闲时长(超出此时长将断开空闲连接)小于120秒。

出于改动成本考虑,采用了第一种方案,修改后,报错不再出现。

这里有一个问题,为何服务器端主动关闭空闲连接后,客户端没有报错呢,系统依赖的是jedis-2.1.0,这块需要细看下jedis连接池那块的实现,jedis连接池主要是基于commons-pool写的,下来再研究研究,写一篇文章总结一下。

(本文已被阅读18次)

前段时间,由于线上redis服务器的内存使用率达到了机器总内存的50%以上,导致内存数据的dump持久化一直失败。扩展到多台redis后,应用系统访问redis时,在业务量较少时,时不时会出现以下异常,当业务量较大,redis访问频率很高时,却不会发生这个异常,一时觉得很诡异。 redis.clients.jedis.exceptions.JedisConnectionException:?It?seems?like?server?has?closed?the?connection. at?redis.clients.util.RedisInputStream.readLine(RedisInputStream.java:90)?~[jedis-2.1.0.jar:na] at?redis.clients.jedis.Protocol.processInteger(Protocol.java:110)?~[jedis-2.1.0.jar:na] at?redis.clients.jedis.Protocol.process(Protocol.java:70)?~[jedis-2.1.0.jar:na] at?redis.clients.jedis.Protocol.read(Protocol.java:131)?~[jedis-2.1.0.jar:na] at?redis.clients.jedis.Connection.getIntegerReply(Connection.java:188)?~[jedis-2.1.0.jar:na] at?redis.clients.jedis.Jedis.sismember(Jedis.java:1266)?~[jedis-2.1.0.jar:na] 看提示,应该是服务端主动关闭了连接。查看了新上线的redis服务器的配置,有这么一项: # Close the connection after a client is idle for N seconds (0 to disable) timeout 120 这项配置指的是客户端连接空闲超过多少秒后,服务端主动关闭连接,默认值0表示服务端永远不主动关闭。而op人员把服务器端的超时时间设置为了120秒。这就解释了发生这个异常的原因。客户端使用了一个连接池管理访问redis的所有连接,这些连接是长连接,当业务量较小时,客户端部分连接使用率较低,当两次使用之间的间隔超过120秒时,redis服务端就主动关闭了这个连接,而等客户端下次再使用这个连接对象时,发现服务端已经关闭了连接,进而报错。 解决方案有两种: 1. 在redis-cli下直接修改redis 的配置,把timeout改回为0,无需重启redis即可直接生效。 2. 修改应用系统代码,设置连接的最大空闲时长(超出此时长将断开空闲连接)小于120秒。 出于改动成本考虑,采用了第一种方案,修改后,报错不再出现。 这里有一个问题,为何服务器端主动关闭空闲连接后,客户端没有报错呢,系统依赖的是jedis-2.1.0,这块需要细看下jedis连接池那块的实现,jedis连接池主要是基于commons-pool写的,下来再研究研究,写一篇文章总结一下。 (本文已被阅读18次)

下载本文
显示全文
专题