redis内存溢出排查

1、背景
早上收到“系统登录接口异常”、“redis服务器内存利用率过高” ,结合来看怀疑redis导致登录功能异常

2、排查过程
tail -f /var/log/redis/redis-server.log
发现内存溢出报错

29258:M 08 Aug 2024 12:35:00.123 # Warning: memory over the limit
29258:M 08 Aug 2024 12:35:00.123 # Error: memory limit exceeded, write operation denied

redis-cli info memory

used_memory_human:7.7G
maxmemory_human:7.8G

那现在已经是实锤redis溢出了,看下是啥占用了那么多,查看占内存比较高的键

redis-cli --bigkeys

-------- summary -------

Sampled 12000000 keys in the keyspace!

redis-cli --bigkeys输出会显示最大占用内存的字符串key、set key、及hash key是啥,分别占了多少字节跟其他信息。但是最大那个key也不过几十M,不可能是某个key造成的,有可能是某种情况引发了百万级别的key创建塞满了redis内存

redis-cli keys “*” > /data/redis-key.log

把所有键名都导出来,发现大部分都是这种“f30a0485-b59f-4939-a41d-3955786b37e0”格式的键名,我恍然大悟,这是创建的会话id啊。

开发反馈会话id过期时间设置了两天,难道会话过期时间设置没生效,导致会话记录一直积在redis里面导致溢出?为了验证我的想法,我得去看下那些现有会话的存活时长有没有超过两天

1、把key的过期时间导出
cat /data/redis-key-100000.log | xargs -I key redis-cli ttl key > /data/key_ttl.log
2、过滤过期时间超过2天的key
cat /data/key_ttl.log | awk '{if($0 > 172800) print $0}'

结果一条都没过滤到,证明过期时间设置没有问题

既然过期时间设置没问题,就看创建出了什么问题,我随便拿了一个会话id的key,打印出它的值

redis-cli get 'f30a0485-b59f-4939-a41d-3955786b37e0'

具体结构就不展示了,但我得到了一个重要信息,这会话里面没有存有会话信息跟业务信息,只存了几个可有可无的值;我纳闷了,会话里不应该存登录信息用户信息啥的吗,为啥用户信息都是空的,这也能创建一个会话啊?证明没有登录就可以创建会话?为了验证我的想法,我去实验了一下:

打开我测试环境的项目,事先清了redis相关记录,我打开页面,没有登录,我立马回去看redis信息,它果真给我创建了一个会话。。。。。我这算是彻底知道咋回事了,肯定有人刷我们的网站,导致会话不断给创建。

后知后觉的我打开的nginx 的访问日志,发现有大量的IP在访问我们的网站

awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr

3、解决方案
1) bug修改
经过盘查,发现会话是egg的一个插件egg-seesion-redis自动创建的,只要请求来的没带我们规定的会话key键,而且有数据要写入(不管写入内容是啥,即便为空),就会立马给你创建一个会话。具体原理如下:
在这里插入图片描述

但是这不是我想要的结果,我想要的是登录后再创建会话。
让开发通过设置 autoCommit: false,可以避免未必要的会话创建

2)nginx IP封禁、限制ip每秒访问频率

<think>好的,我现在需要处理用户关于Redis内存溢出的问题。首先,我得回忆一下用户之前提到的内容相关引用。用户现在想查找Redis内存溢出解决方案,异常处理的方法。根据提供的引用内容,我需要综合这些信息来给出合理的解答。 首先,用户提供的引用中有几个关键点。引用[1]提到使用`redis-cli config get activerehashing`来查看内存分配策略,合理配置可以减少内存碎片。引用[3]中的序列图展示了排查步骤,包括检查内存使用情况、内存限制配置、回收策略、内存碎片率等。引用[4]讨论了Redis的内存管理,包括申释放、缓存预留、淘汰策略碎片整理。引用[5]提到了缓存并发的问题,但可能内存溢出关系不大,暂时不考虑。 用户的问题是关于内存溢出解决方案,所以需要从根本原因入手。内存溢出通常是由于数据量超过Redis配置的最大内存限制,或者内存碎片过多导致无法有效利用。可能的解决方案包括调整内存限制、优化数据结构、使用淘汰策略、处理内存碎片等。 接下来,我需要按照系统级指令的要求,结构清晰,分步骤回答。同时要生成相关问题,并正确引用来源。注意数学表达式要用$...$,但这个问题可能涉及较少数学内容,但如果有的话,比如内存计算公式,需要正确使用格式。 首先,应该引导用户检查当前的内存使用情况,如使用`INFO memory`命令,查看已用内存最大内存配置。然后检查是否设置了maxmemory以及淘汰策略,如引用[3]提到的。如果内存达到上限,可能需要增加服务器内存(引用[1]),或者优化数据,比如删除不必要的键,使用高效的数据结构。 另外,内存碎片的问题可以通过启用activedefragactiverehashing来整理碎片(引用[4])。而内存分配策略如jemalloc也可以影响碎片情况,需要检查配置(引用[3])。 数据持久化配置也可能影响内存,比如RDBAOF的配置是否合理。如果AOF文件过大,重写时可能占用额外内存,需要关注。 总结解决方案的步骤应该是:检查内存使用、调整配置、优化数据、处理碎片、监控分析。每一步都要结合引用中的信息,并正确标注引用来源。 最后生成相关问题,比如如何设置淘汰策略,如何处理内存碎片,内存分析工具等。确保问题与主题相关,帮助用户进一步了解。 现在需要确保回答符合格式要求,使用中文,结构清晰,正确引用,并且没有使用任何markdown。同时,检查是否有遗漏的关键点,比如是否提到集群分片,或者具体的配置命令,比如`CONFIG SET maxmemory-policy`等。</think>### Redis内存溢出解决方案分步说明 #### 一、检查内存使用情况 1. **查看实时内存状态** 执行命令 `redis-cli info memory` 获取详细内存指标: - `used_memory`:当前已用内存 - `maxmemory`:配置的最大内存限制 - `mem_fragmentation_ratio`:内存碎片率(若$ratio > 1.5$说明碎片严重)[^3][^4] 2. **确认内存限制配置** - `redis-cli config get maxmemory`:检查是否设置了内存上限 - 若返回`0`表示未限制,需通过`CONFIG SET maxmemory <bytes>`设置合理阈值[^3] #### 二、优化内存配置 1. **调整内存淘汰策略** Redis提供8种淘汰策略(如`volatile-lru`、`allkeys-lfu`),通过命令设置: ```bash CONFIG SET maxmemory-policy allkeys-lru ``` 根据数据类型选择策略:对含过期时间的键用`volatile-*`,否则用`allkeys-*`[^4] 2. **启用内存碎片整理** - 修改配置文件: ```conf activedefrag yes active-defrag-ignore-bytes 100mb # 碎片超过100MB时触发 active-defrag-threshold-lower 10 # 碎片率>10%开始整理 ``` - 动态生效:`CONFIG SET activerehashing yes`[^3][^4] #### 三、数据层优化 1. **缩短Key与Value长度** - 使用缩写(如`usr:123`代替`user_id:123`) - 对大Value拆分存储或使用压缩算法(如Snappy) 2. **选择高效数据结构** - 用Hash替代多个String存储对象 - 使用ZSet代替List+Timestamp实现排序场景[^4] 3. **清理无效数据** - 执行`SCAN`命令遍历并删除过期键 - 批量删除匹配Key: ```bash redis-cli --scan --pattern "temp:*" | xargs redis-cli del ``` #### 四、架构级扩展 1. **集群分片** 通过Redis Cluster或代理(如Twemproxy)将数据分布到多个节点,公式: $$ 分片数 = \frac{总数据量}{单节点最大内存 \times 0.8} $$ 保留20%冗余应对突发流量[^1] 2. **冷热分离** 将低频数据迁移至磁盘数据库(如LevelDB),仅保留热数据在Redis中 #### 五、监控与分析工具 1. **内置工具** - `redis-cli --bigkeys`:分析大Key分布 - `redis-cli memory stats`:输出内存碎片率及分配详情[^3] 2. **外部监控** 集成Prometheus + Grafana监控以下指标: - 内存使用率曲线 - 淘汰策略触发频率 - 碎片整理耗时
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值