Redis内存使用耗尽情况分析
目录
1、内存上限介绍
1.1、产生原因
1.2、Redis的maxmemory限额
1.3、影响的命令与场景
2. 内存用完后的策略
2.1、淘汰策略分类
2.2、淘汰策略介绍
2.3、不同策略对比
3、常见业务示例
3.1、影响
3.2、监控与自动告警
前言
在日常项目中,不知道你思考过没有redis的内存耗尽的情况?
如下所示:
具体行为:
当内存满时:
- 读操作(如GET):可以正常进行
- 写操作(如SET、LPUSH、SADD等):
- 如果能通过淘汰策略释放一点空间,则写入继续
- 如果根据策略无法再释放空间(比如noeviction),则直接返回错误:“OOM command not allowed when used memory > 'maxmemory'.”
风险:
- 如果是noeviction(默认),Redis直接拒绝写入!
- 如果淘汰策略被触发,你的“旧数据”就会被自动删除(可能有业务风险)。
- 内存页碎片、fork快照等也会加速内存耗尽。
- 极端情况下,如果宿主机内存被撑爆,系统可能直接kill掉Redis进程(OOM Killer)。
关于更多redis的介绍,可参考:对Redis组件的深入探讨_redis 磁盘 内存-CSDN博客文章浏览阅读1.3k次,点赞20次,收藏8次。前言在介绍redis的时候,先介绍下存储介质,磁盘和内存。通过对以下两种认识,对了解redis有着更深的理解。如下图所示:以上就是r。_redis 磁盘 内存https://blog.csdn.net/weixin_50055999/article/details/147757520?spm=1011.2415.3001.5331
1、内存上限介绍
Redis是内存数据库,所有数据(Key/Value)都存放在内存(RAM)中,不像MySQL等主要用磁盘。
Redis的数据结构不仅要存储你的 key/value 数据,还要存储:
1、Key/value 相关的元数据(如过期信息)
2、Append Only File (AOF)
3、缓冲区复制缓冲区、客户端连接缓冲区等
所以实际内存消耗 = 数据+各种维护数据+内存碎片。
1.1、产生原因
1、数据总量超过maxmemory配置:
这是最常见情况:写入、缓存、业务量上涨、没有删除机制,累计到了上限。
2、未设置maxmemory,Redis自动用光了系统全部内存:
系统会自动kill Redis进程(Linux OOM Killer)。
3、AOF或RDB备份引起内存瞬时暴涨:
快照/流复制/fork过程占用大量额外内存。
4、客户端缓冲区、复制缓冲区太大:
有些命令或者慢客户端导致缓冲区堆积。
5、内存碎片率很高:
内存并不是100%利用,碎片率过高也会导致出现“看似还有容量,实际已用尽”的问题。
1.2、Redis的maxmemory限额
Redis 是基于内存的数据库,其总内存上限可通过maxmemory参数配置。
比如在redis.conf中:
maxmemory 1gb
如果你没有设置,理论上 Redis 可以用光宿主机所有可用内存,直到被Linux OOM杀死进程。
1.3、影响的命令与场景
1、影响所有产生新内存分配的命令
包括:set/hash/set/zset/list的增量写入命令,bitmap、hyperloglog…
2、以下命令不会报错
读命令(GET/EXISTS/SCAN等)
删除命令(DEL/EXPIRE/UNLINK)
清空命令(FLUSHDB、FLUSHALL)
2. 内存用完后的策略
当 Redis 达到 maxmemory 限制(即内存“用完”),会按照配置的淘汰策略(maxmemory-policy参数)来处理新写入命令。
如下图所示:
写请求 -> 检查used_memory|是否超maxmemory?/ \否 是| |正常写 执行淘汰策略|能释放内存吗?/ \能 不能| |正常写 返回OOM错误,写失败
2.1、淘汰策略分类
- noeviction(默认):不淘汰,拒绝写入,只允许读;
- allkeys-lru:将所有key中最久未使用的key淘汰;
- volatile-lru:只对设置了过期时间的key做lru淘汰;
- allkeys-random:所有key随机淘汰;
- volatile-random:只对设置了过期的key随机淘汰;
- volatile-ttl:优先淘汰过期时间到期最早的key;
- volatile-lfu、allkeys-lfu:最不常用的(Least Frequently Used)key被淘汰。
2.2、淘汰策略介绍
1、noeviction(默认)
只读不写: 所有新增key、修改key、增加元素的命令(如SET、LPUSH、HSET等) 统统返回错误(error),只允许读(GET等)。
(error) OOM command not allowed when used memory > 'maxmemory'.
- 危险:
- 业务写入完全中断
- 可能造成数据库/队列/秒杀等核心数据业务丢失
- 生产极其危险,尤其是做缓存穿透时容易击穿下游数据库
2、allkeys-lru
自动淘汰:
优先淘汰“最久未使用”的key(Least Recently Used),腾出空间让新数据写成功。
风险:
部分“冷数据”被自动删掉,新数据继续写入,服务不中断,但有可能丢掉了有用的老数据。
3、volatile-lru
- 只判断有过期时间(expire)的key。
- 只淘汰带过期时间的key,不带过期属性的key永远不会被删
- 如果全是永久key,效果跟noeviction一样,容易写不进去
4、allkeys-random/volatile-random
- allkeys-random:任意key随机淘汰。
- volatile-random:也只淘汰带过期的key,随机选择。
5、volatile-ttl
只淘汰带过期时间里“快要到期”的key。
6、allkeys-lfu/volatile-lfu
淘汰最少被访问的key(Least Frequently Used),更智能。
2.3、不同策略对比
如下所示:
注意:
- 持久化(RDB/AOF)也有可能被影响,如果没法持久化新数据,有可能异常或数据丢失!
- 主从同步、集群等同步数据也受maxmemory影响。
3、常见业务示例
3.1、影响
1、缓存:
如果用作普通缓存,可以用allkeys-lru/allkeys-lfu让Redis自动“以空间换时间”。热点数据永远在,冷数据慢慢淘汰,更健康。
2、持久化队列/核心计数/实时业务:
如果Redis用作数据库功能(存放业务数据、消费队列),noeviction策略推荐。避免关键数据被误删。一旦写入超限应报警、扩容、限流,绝不随便丢“老数据”。
3、大key、热key、慢客户端
某个大key占住大量内存,会加速爆表,需依据业务定期分析优化。
更多bigkey文章介绍,参考:
Redis中的bigkey的介绍及影响_redis 大key-CSDN博客文章浏览阅读1.2k次,点赞31次,收藏12次。什么是BigKey?为什么它成为Redis的性能杀手?BigKey指在Redis中key对应的value占用内存或元素数量超出业务合理阈值的键值对。_redis 大keyhttps://blog.csdn.net/weixin_50055999/article/details/148856033?spm=1011.2415.3001.5331
4、内存暴涨瞬间写崩溃
新增了超大key(如bitmap、大string、大list),远超单条key的预期,会导致写入命令的突然异常或长时间阻塞(尤其fork的时候)。
3.2、监控与自动告警
建议配合运维/监控工具(如Prometheus、Grafana、redis_exporter、阿里云/腾讯云云监控等)。
重点关注:
1、used_memory (info memory)。
2、maxmemory。
3、内存碎片率。
4、淘汰计数器evicted_keys。
5、命令拒绝计数rejected_connections。
总结
Redis的内存满了,不同的淘汰策略决定要不要丢弃已有数据腾空间,否则直接拒绝写入并报错,只能读不能写,业务必须配合好监控、限流和数据结构优化。
参考文章:
1、内存耗尽后,Redis会发生什么?_redis中key没有达到过期时间,但是内存满了会怎么样?-CSDN博客文章浏览阅读84次。作为一台服务器来说,内存并不是无限的,所以总会存在内存耗尽的情况,那么当 Redis 服务器的内存耗尽后,如果继续执行请求命令,Redis 会如何处理呢?_redis中key没有达到过期时间,但是内存满了会怎么样?https://blog.csdn.net/qq_30987095/article/details/143257130?ops_request_misc=%257B%2522request%255Fid%2522%253A%252295fab89f19b3cb10a23ea7030593bb32%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=95fab89f19b3cb10a23ea7030593bb32&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-143257130-null-null.142^v102^control&utm_term=redis%E5%86%85%E5%AD%98%E8%80%97%E5%B0%BD&spm=1018.2226.3001.4187