redis 持续时间_记一次redis线上问题

本文详细描述了一次Redis集群中某分片内存异常飙升的排查过程。问题表现为某个分片内存显著高于其他分片并持续增长,且主从节点内存使用不一致。经过分析发现,原因是由于`monitor`命令导致的大量数据输出,占用了大量输出缓存区内存。紧急处理办法是关闭`monitor`进程,内存随即下降。为预防此类问题,建议限制或禁用危险命令,如`monitor`,并调整客户端输出缓存区的配置。
摘要由CSDN通过智能技术生成

阅读大概需要4分钟

一个生产中的问题,建议阅读四颗星

  • 现象

  • 分析可能原因

  • 调查原因

  • 概念详细介绍

  • 紧急处理办法

  • 预防办法

现象

redis-cluster某个分片内存飙升,明显比其他分片高很多,而且持续增长。并且主从的内存使用量并不一致。(个别可能导致服务无法启动)

分析可能原因

对于 redis 出现这种现象,一般都会从这个这几个方面考虑

  1. redis-cluster的bug (这个应该不存在)
  2. 客户端的hash(key)有问题,造成分配不均。(redis使用的是crc16, 不会出现这么不均的情况)
  3. 存在个别大的key-value: 例如一个包含了几百万数据set数据结构(这个有可能)
  4. 主从复制出现了问题。
  5. 其他原因

调查原因

  1. 经查询,上述1-4都不存在
  2. 观察info信息,有一点引起了怀疑:client_longes_output_list有些异常。
  3. 于是理解想到服务端和客户端交互时,分别为每个客户端设置了输入缓冲区和输出缓冲区,这部分如果很大的话也会占用Redis服务器的内存。

从上面的 client_longest_output_list 看,应该是输出缓冲区占用内存较大,也就是有大量的数据从Redis服务器向某些客户端输出。

于是,使用 client list 命令(类似于 mysql processlist)redis-cli -h host -p port client list | grep -v "omem=0",来查询输出缓冲区不为0的客户端连接,于是查询到祸首 monitor,于是豁然开朗。

monitor 的模型是这样的,它会将所有在 Redis 服务器执行的命令进行输出,通常来讲 Redis 服务器的 QPS 是很高的,也就是如果执行了 monitor 命令,Redis服务器在 Monitor 这个客户端的输出缓冲区又会有大量“存货”,也就占用了大量 Redis 内存。

概念详细介绍

这是 redis 的配置介绍,对于客户端内存限制

        redis 客户端在于 redis 服务端相互交互时,服务端会为每个客户端分别设置输入缓存区和输出缓存区,我们知道 redis 是基于内存的非关系型数据库,所以这两部分缓存区的数据依然是保存在内存中,如果这两部分很大的话会占用 redis 很大的内存。模型图如下图所示:

bfc2888253d7e35917e14d349579f1fb.png
客户端连接

使用 info 命令查看当前redis客户端连接数及当前缓存区的使用量

086a98e01d279089ba839c61af0e4272.png
在这里插入图片描述

那么什么是输入缓存区和输出缓存区呢?

输入缓存区:用于保存客户端发送的请求,输入缓存区的大小会根据请求数据的大小动态变化,1GB 是输入缓存区最大的容量,如果超出最大容量该客户端便会被关闭。

输出缓存区:用于保存执行请求后的返回结果,每个客户端有两个缓存区,一个是固定客户端缓存区(用于保存那些长度比较小的返回值,如一些比较短的字符串或整数值);一个是可变客户端缓存区(用于保存那些长度比较大的返回值,如长度比较大的字符串、大集合等)。

服务器采用软性限制和硬性限制两种方式限制输出缓存区的大小。

软性限制:如果软性限制所设置的大小小于输出缓冲区的大小,且输出缓冲区的大小不大于硬性限制所设置的大小,那么服务器会使用客户端状态结构的 obuf_soft_limit_reached_time 属性来记录客户端达到软性限制的起始时间。之后服务器会继续监视客户端,如果这个缓冲区的大小一直超出软性限制,并且持续时间超过服务器设定的时长,那么服务器将会关闭这个客户端。相反地,如果输出缓冲区的大小在指定时间范围之内没有超过软性限制,那么这个客户端不会被关闭,并且 obuf_soft_limit_reached_time 属性的值也会被设置为 0。

如果输出缓存区的大小大于硬性限制,那么客户端会立即关闭。

在 redis 配置文件中,可以对软性限制和硬性限制进行设置:

ec73c1ffb952aed046fcfbf2b9f1d91f.png
redis 配置

第一行代码表示:对于 普通 客户端来说,限制为 0,也就是不限制。因为普通客户端通常采用阻塞式的消息应答模式,通常情况下不会导致 redis 输出缓存区数据堆积膨胀。

第二行代码表示:对于 slave 客户端来说,硬性限制是 256M,软性限制是当客户端缓冲区大小持续 60秒 超过 64M,则关闭客户端连接。

第三行代码表示:对于 Pub/Sub 客户端(也就是发布/订阅模式),硬性限制是 32M,当输出缓冲区超过 32M 时,会关闭连接。软性限制是当客户端缓冲区大小持续 60秒 超过 8M,则关闭客户端连接;

紧急处理办法

进行主从切换(主从内存使用量不一致),也就是 redis-cluster 的 fail-over 操作,继续观察新的 Master 是否有异常,通过观察未出现异常。

查找到真正的原因后,也就是 monitor,关闭掉 monitor 命令的进程后,内存很快就降下来了。

预防办法

  1. 修改客户端源代码,禁止掉一些危险的命令(shutdown, flushall, monitor, keys *),当然还是可以通过redis-cli来完成;
  2. 添加command-rename配置,将一些危险的命令(flushall, monitor, keys * , flushdb)做rename;
  3. 对 redis 使用中遇到的问题分享、学习分享很重要。
占用内存过高的命令谨慎使用,保证系统稳定性

参考博文:https://www.iteye.com/blog/carlosfu-2254154

87c1ec01d6801986394561a054c7bbba.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值