记一次redis使用问题

本文涉及的产品
云原生内存数据库 Tair,内存型 2GB
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Redis 版,经济版 1GB 1个月
简介: 记一次redis使用问题

现象

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 很大的内存。模型图如下图所示:

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

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

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


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


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


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


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

在 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来完成;

添加command-rename配置,将一些危险的命令(flushall, monitor, keys * , flushdb)做rename;

对 redis 使用中遇到的问题分享、学习分享很重要。

参考博文:


https://www.iteye.com/blog/carlosfu-2254154

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
1月前
|
存储 NoSQL Go
Redis 双端链表
Redis 双端链表
31 0
|
9月前
|
存储 NoSQL Redis
|
9月前
|
存储 NoSQL 算法
|
9月前
|
消息中间件 缓存 NoSQL
### 1.2 使用Redis能做什么
### 1.2 使用Redis能做什么
31 0
|
9月前
|
监控 NoSQL Java
|
9月前
|
NoSQL Redis
|
存储 缓存 NoSQL
Redis为什么那么快
Redis为什么那么快
96 1
Redis为什么那么快
|
10月前
|
存储 缓存 NoSQL
|
存储 消息中间件 缓存
Redis总结(二)
redis 和 memcached 什么区别?为什么高并发下有时单线程的 redis 比多线程的memcached 效率要高?区别:1.mc 可缓存图片和视频。rd 支持除 k/v 更多的数据结构;2.rd 可以使用虚拟内存,rd 可持久化和 aof 灾难恢复,rd 通过主从支持数据备份;3.rd 可以做消息队列。原因:mc 多线程模型引入了缓存一致性和锁,加锁带来了性能损耗。redis 主从复制如何实现的?redis 的集群模式如何实现?redis 的 key 是如何寻址的?
93 0
|
NoSQL Redis