序:文由
- 因今日排查问题,发现微服务因 ERR max number of clients reached (已达到客户端的最大数量) redis异常,而导致服务在健康检测时未通过,进而导致高频宕机。
概述:Redis 连接与会话管理
Redis 连接会话的原理
- redis通过监听一个TCP端口或socket的方式接收来自客户端的连接,当与客户端建立连接后,redis内部会进行如下操作:
(1)客户端socket会被设置为非阻塞模式,因为redis在网络时间处理上采用的是非阻塞多路复用模型;
(2)为这个socket设置TCP_NODELAY属性,禁用Nagle算法;
(3)创建一个可读的文件事件用于监听这个客户端socket的数据发送。
常用功能与指令
连接操作类
查看连接总数 : info clients
- > info clients
- # Clients
- connected_clients:95
- client_recent_max_input_buffer:2
- client_recent_max_output_buffer:0
- blocked_clients:0
- rx_controlled_clients:0
- total_real_rx_controlled:0
- total_tx_controlled:0
- total_rx_controlled:824214
- proxy_header_error:0
复制代码 查看连接详情列表 : client list
- client list : 命令用于返回所有连接到服务器的客户端信息和统计数据。
http://www.redis.cn/commands/client-list.html
bulk-string-reply: 一个独特的字符串。具体格式:
每个已连接客户端对应一行(以 LF 分割)
每行字符串由一系列 属性=值(property=value) 形式的域组成,每个域之间以空格分开。
各字段的含义::
- id: 唯一的64位的客户端ID(Redis 2.8.12加入)。
- addr: 客户端的地址和端口
- fd: 套接字所使用的文件描述符
- age: 以秒计算的已连接时长
- idle: 以秒计算的空闲时长
- flags: 客户端 flag
- db: 该客户端正在使用的数据库 ID
- sub: 已订阅频道的数量
- psub: 已订阅模式的数量
- multi: 在事务中被执行的命令数量
- qbuf: 查询缓冲区的长度(字节为单位, 0 表示没有分配查询缓冲区)
- qbuf-free: 查询缓冲区剩余空间的长度(字节为单位, 0 表示没有剩余空间)
- obl: 输出缓冲区的长度(字节为单位, 0 表示没有分配输出缓冲区)
- oll: 输出列表包含的对象数量(当输出缓冲区没有剩余空间时,命令回复会以字符串对象的形式被入队到这个队列里)
- omem: 输出缓冲区和输出列表占用的内存总量
- events: 文件描述符事件
- cmd: 最近一次执行的命令
复制代码 设置当前连接点redis的名称 : CLIENT SETNAME
查看当前连接的名称 : CLIENT GETNAME
杀死指定连接 : CLIENT KILL {ip}:{port}
连接配置类
查看/设置连接的默认超时自动断连时间(空闲超时时间) : config [get|set] timeout [{second}]
默认值 = 0
单位:秒钟
查询/设置允许的最大连接数 : config get maxclients
方法1:在2.6之后版本,可以修改最大连接数配置,默认10000,可以在redis.conf配置文件中修改
方法2: config set maxclients num 可以设置redis允许的最大连接数
- 127.0.0.1:6379> CONFIG set maxclients 10
- OK
- 127.0.0.1:6379>
复制代码方法3:启动redis.service服务时加参数--maxclients 100000来设置最大连接数限制
- redis-server --maxclients 100000 -f /etc/redis.conf
复制代码 FAQ for Redis 连接与会话管理
Q: 连接过多,乃至报ERR max number of clients reached(Redis客户端连接数已达到最大限制)?
redis maxclients 是redis server的重要配置,它决定了客户端的最大连接数量、最大客户端连接数量。
由于redis不区分连接是客户端连接、还是内部打开文件、或者和slave连接等。所以,maxclients最小存在32个连接数,如果超过了设置的maxclients,redis会给新的连接发送"max number of clients reached",并关闭连接。
在Redis 2.4中,可以同时处理的最大客户端数量存在硬编码限制。
在Redis 2.6中,此限制是动态的:默认情况下,它设置为10000个客户端,除非Redis.conf中的maxclients指令另有说明。
绝大部分原因:由于客户端很多空闲连接都没有被及时释放掉,从而导致connected_clients非常高
其他可能:maxclients设置的太少了
还有可能:软硬件存在限制
- JedisPoolConfig jedisPoolConfig = initPoolConfig();
- jedisPool = new JedisPool(jedisPoolConfig, "*.*.*.*", 6379);
- =========> 修改为:
- JedisPoolConfig jedisPoolConfig = initPoolConfig();
- jedisPool = new JedisPool(jedisPoolConfig, "*.*.*.*", 6379, 2*1000); //timeout = 2*1000 = connectionTimeout = soTimeout
复制代码public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, final int connectionTimeout, final int soTimeout, final String password, final int database, final String clientName)
- Jedis jedis = JedisUtils.getJedis();
- try {
- //Todo
- } catch (Exception e){
- throw new RuntimeException(e.getMessage(), e);
- JedisUtils.returnBrokenResource(jedis); //释放连接
- } finally {
- JedisUtils.returnResource(jedis); //释放连接
- }
- ----
- /**
- * 回收Jedis对象资源
- *
- * @param jedis
- */
- public synchronized void returnResource(Jedis jedis) {
- if (jedis != null) {
- jedisPool.returnResource(jedis);
- }
- }
-
- /**
- * Jedis对象出异常的时候,回收Jedis对象资源
- *
- * @param jedis
- */
- public synchronized void returnBrokenResource(Jedis jedis) {
- if (jedis != null) {
- jedisPool.returnBrokenResource(jedis);
- }
-
- }
复制代码在 Jedis 2.6.2 以后,由于重写了jedis.close(),实现自动关闭,2.6.3以后正式使用,详见Deprecates JedisPool returnResource and returnBrokenResource ,这样可以代码使用JDK7中新增的try-with-resource语法糖,这样代码会简洁很多如下:
- try (Jedis jedis = JedisUtils.getJedis()) {
- //Todo
- } catch (Exception e) {
- throw new RuntimeException(e.getMessage(), e);
- }
复制代码
- 3 通过ip排查对应的service服务,查看是否还可以进行优化。
- 4 查看空闲超时时间: config get timeout
0 : 默认不开启
- 5 设置空闲超时时间 : config set timeout {second}
建议为0,尤其是有用分布式锁的情况下、具体看业务场景
如:配置默认空闲超时时间为60s : config set timeout 60
可在 redis.conf 配置文件中添加重启生效。
X 参考文献
- redis 连接工具_redis之timeout(默认建议为0) , maxclients(重要) - 博客园
- 解决Redis 连接池报错:ERR max number of clients reached - CSDN 【推荐】
- 生产-已解决-Redis连接数占满 报错 (error) ERR max number of clients reached - CSDN 【推荐】
(error) ERR max number of clients reached
"我仔细审查了一下前同事写的Redis工具类,发现连接用完,全都没有归还连接"
- public <T> T get(String key, String modulePrefix, Class<T> t) {
- checkJedisPool();
- key = generateKey(key, modulePrefix);
- try (Jedis jedis = jedisPool.getResource()) {
- String valueStr = jedis.get(key);
- return parse(valueStr, t);
- }
- }
复制代码 本文作者: 千千寰宇
本文链接: https://www.cnblogs.com/johnnyzen
关于博文:评论和私信会在第一时间回复,或直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
日常交流:大数据与软件开发-QQ交流群: 774386015 【入群二维码】参见左下角。您的支持、鼓励是博主技术写作的重要动力!
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |