redis 内存淘汰策略和内存大小限制

记录一次生产环境问题排查过程:
生产环境部署方式:nginx + uwsgi + flask
问题描述:
发现生产环境中之前正常运行的服务突然不可用了,查看程序日志发现部分接口访问时报I/O写错误,nginx acess.log显示504,error.log显示 upstream time out,同时 netstat -apn | grep 6379 | wc -l 检查发现redis存在大量连接,进一步检查发现其中大多为 SYN_SENT 包,连接大多归属于uwsgi 进程。
 

因为程序中有很多接口被调用是会访问redis, 以为是redis连接池导致,对程序中的redis连接池进行优化后重启服务,刚启动时一切正常,http 200, 但几分钟后服务再次挂掉,http 504.

检查系统资源使用情况,发现 kswapd0 进程CPU占用很高,这个进程是当物理内存不足时,会将一部分硬盘当做虚拟内存来使用, 使用swap分区与内存换页操作交换数据,导致CPU占用过高, 再细看发现redis-server内存占用已超过100%:
在这里插入图片描述

  • 进入redis中查看info memory和各存储数据的key下数据量,果然存在大量未处理完毕的数据。

    到此问题终于是找到了。

  • 设置redis最大占用内存

# 编辑redis配置文件,加入最大内存使用限制,我根据服务器的情况设置为3G
maxmemory 3221225472

 在redis配置文件中设置过期策略为:
maxmemory-policy allkeys-lru
一开始是设置为volatile-lru的,但是该策略只是清除设置过期时间的key值,因为很多key并没有设置过期时间。因此修改为maxmemory-policy allkeys-lru,指明非活跃近期很少用的key值清除.
  在使用maxmemory-policy allkeys-lru策略时,内存超限后将不再存储数据,但数据的读取删除操作不会受影响,超限时显示错误 OOM command not allowed when used memory > 'maxmemory'

  • 重启程序,至此服务终于正常运行。

总结:本次的问题归根结底是redis中存储入了大量脏数据,但数据处理并没有及时的清理掉这部分数据,最终导致服务停滞,allkeys-lru策略有可能会将长期未用但实际有用的数据清理掉,所以还是应优化数据处理为主。

 

缓存淘汰策略


当 Redis 内存超出物理内存限制时,内存的数据会开始和磁盘产生频繁的交换 (swap)。交换会让 Redis 的性能急剧下降,对于访问量比较频繁的 Redis 来说,这样龟速的存取效率基本上等于不可用。

在生产环境中我们是不允许 Redis 出现交换行为的,为了限制最大使用内存,Redis 提供了配置参数 maxmemory 来限制内存超出期望大小。

当实际内存超出 maxmemory 时,Redis 提供了几种可选策略 (maxmemory-policy) 来让用户自己决定该如何腾出新的空间以继续提供读写服务。

 

noeviction 不会继续服务写请求 (DEL 请求可以继续服务),读请求可以继续进行。这样可以保证不会丢失数据,但是会让线上的业务不能持续进行。这是默认的淘汰策略。

volatile-lru 尝试淘汰设置了过期时间的 key,最少使用的 key 优先被淘汰。没有设置过期时间的 key 不会被淘汰,这样可以保证需要持久化的数据不会突然丢失。淘汰最近最少使用的key

volatile-ttl 跟上面一样,除了淘汰的策略不是 LRU,而是 key 的剩余寿命 ttl 的值,ttl 越小越优先被淘汰。

volatile-random 跟上面一样,不过淘汰的 key 是过期 key 集合中随机的 key。淘汰随机的key数据

allkeys-lru 区别于 volatile-lru,这个策略要淘汰的 key 对象是全体的 key 集合,而不只是过期的 key 集合。这意味着没有设置过期时间的 key 也会被淘汰

allkeys-random 跟上面一样,不过淘汰的策略是随机的 key。

volatile-xxx 策略只会针对带过期时间的 key 进行淘汰,allkeys-xxx 策略会对所有的 key 进行淘汰。如果你只是拿 Redis 做缓存,那应该使用 allkeys-xxx,客户端写缓存时不必携带过期时间。如果你还想同时使用 Redis 的持久化功能,那就使用 volatile-xxx 策略,这样可以保留没有设置过期时间的 key,它们是永久的 key 不会被 LRU 算法淘汰。

 

设置缓存的最大内存+ 淘汰策略:

127.0.0.1:6379> CONFIG SET maxmemory 1G
OK
127.0.0.1:6379> CONFIG GET maxmemory
1) "maxmemory"
2) "1000000000"
127.0.0.1:6379> config rewrite
OK

127.0.0.1:6379> CONFIG SET maxmemory-policy noeviction
OK
127.0.0.1:6379> config rewrite
OK


 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值