当前位置:首页 > 内存 > 正文

redis内存满了怎么处理

  • 内存
  • 2024-09-05 01:36:05
  • 3955

一、Redis数据丢失问题之前有朋友问我,为什么我们生产环境的redis经常会丢失一些数据呢?一旦写入,一段时间后它可能会消失。
天哪,如果你问这个问题,那就说明你对redis毫无用处。Redis是一个缓存,你把它当成存储吧?
什么是缓存?使用内存作为缓存。内存是无限的吗?相反,内存是宝贵且有限的,而磁盘是廉价且充足的。一台机器可能有几十GB的内存,但它可能有几TB的硬盘空间。Redis严重依赖内存来执行高性能、高并发的读写操作。
由于内存有限,比如redis只能使用10G,如果往里面写20G的数据怎么办?当然,10G的数据会被销毁,然后10G的数据会被保存。那么哪些数据应该被删除呢?存储什么数据?当然,我们需要去掉不常用的数据,保存常用的数据。
所以这是数据存储最基本的概念,要么它自己超时,要么redis自己杀死它。
例如:setkeyvalue超时(1小时)
设置的key将在1小时后被删除并失效
(1)设置timeout
我们在设置key的时候,可以给一个timeout,就是超时时间。例如,指定该密钥只能存活1小时。10分钟?这个非常有用,我们可以指定缓存过期后就过期。
如果假设一组key只能存活1小时,那么redis如何在下一小时后删除这组key呢?
答案是:定期删除+惰性删除
所谓定期删除,是指默认情况下,redis每隔100ms随机选择一些指定过期时间的key,检查是否过期,如果过期,则将其删除。
假设redis中有10万个key,并且设置了超时时间,如果每隔几百毫秒检查10万个key,那么redis基本上就会死掉,CPU负载会很高,就会通过检查过期密钥来消耗。
请注意,这并不是每100毫秒超时一次循环遍历所有键,这将是性能灾难。事实上,redis每隔100ms随机选择一些key来检查并删除它们。
但问题在于,定期删除会导致很多过期的key到了时间却没有被删除。那么我们应该做什么呢?于是就懒得删了。延迟删除是指当你拿到一个key的时候,redis会检查这个key是否已经过期了,如果有设定的过期时间呢?如果过期,此时它将被删除,并且不会向您返还任何内容。
所以并不是key超时就被删除,而是当你请求key的时候,redis会懒惰的检查它。
通过以上两种方法,保证过期的key会被删除。
很简单,这意味着您的过期密钥不会通过redis的常规删除来删除。
但其实这还是一个问题,如果正则删除漏掉了很多过期的key,然后你没有及时检查,那么你不使用懒惰删除,会出现什么情况。发生在这个时候?如果内存中堆积了大量过期key,导致redis内存块耗尽,该怎么办?
答案是:采用内存消除机制。
(2)内存消除
如果redis获取的内存过多,此时就会进行内存消除。有以下几种策略:
1)noeviction:当内存不足以容纳新写入的数据时,新的写入操作会报错一般没人用这个,真是恶心
2)allkeys-lru:当内存不足以容纳新写入的数据时,在keyspace中,移除最近最少使用的key(这是最常使用的)
3)allkeys-random:当内存不足以容纳新写入的数据时,从键空间中随机删除某个key/>
4)易失性-lru:当内存不足以容纳新写入的数据时容纳新写入的数据,在有一定过期时间的key空间中,删除最近最少使用的key(这个一般是不合适的)
5)易失性-随机:当内存不够的时候容纳新写入的数据,随机移除key空间中指定过期时间的一个key
6)volatile-ttl:当内存不足以容纳新写入的数据时插入数据时,在有一定过期时间的键空间中,过期时间最早的键会先被删除
例如:redis中有10个键,现在内存已满,那么这些设置的键就会被删除。策略是allkeys-lru,redis需要删除一些key来保证可以继续写入。这10个键中,1个键最近1分钟被查询100次,1个键最近10分钟被查询50次,1个键最近1小时被查询1次。显然最近最少使用的已经被杀掉了。
为什么redis中存储的数据会丢失?
很简单,你写入的数据太多,内存已满,或者触发了某些条件,比如redisallkeys-lru缓存清除策略,自动清除一些很少使用的数据。你最近。


二、别再问我Redis内存满了该怎么办了当频繁请求Redis内存满问题时,其实可以通过配置来解决。Redis的maxmemory参数允许我们设置内存限制,这是在文件中配置的,一般设置为3GB左右就可以满足当前的需要。如果存储的数据超过配置,Redis会采用淘汰策略来清理空间,比如LRU、allkeys-lru、随机等具体策略取决于数据的访问方式。
LRU算法基于最近最少使用的逻辑,而Redis则使用近似LRU通过随机选择来淘汰最长时间未使用的key。然而,这可能会导致热点数据的错误识别。为了解决这个问题,Redis4.0引入了LFU算法,根据访问频率而不是上次访问时间来淘汰key,以更准确地识别热点数据。
淘汰策略的执行时间可以根据业务需求,采用定时、惰性或定期删除过期key的方式来平衡内存和CPU资源。在持久化方面,RDB和AOF模式也提供了相应的策略,例如RDB快照只存储活动数据,AOF模式通过Overwrite优化避免写入过期的key。
总的来说,面对Redis内存满的挑战,关键是要理解并灵活运用配置、淘汰策略和持久化机制,以保证系统的稳定运行。
三、Redis内存满了会怎么样?

1.通过配置文件进行配置

通过在Redis安装目录下的配置文件中添加以下配置来设置内存大小

可能是redis配置文件无法使用的是安装目录下的。redis服务启动时,可以传递一个参数来指定redis配置文件

Redis支持命令操作动态修改内存大小

因为最大内存大小为Redis可以设置,创建的内存将会被使用。那么当我们内存不足的时候,我们继续向Redis添加数据,是不是就有内存可用了呢?

其实,Redis定义了几种策略来处理这种情况:

当使用三种策略volatile-lru,volatile-random,和volatile-ttl时,如果没有,如果key可以被删除,会返回和noevection一样的错误。

获取当前内存清除策略:

通过配置文件设置清除策略(修改le):

通过命令修改移除策略:

近似LRU算法

Redis使用近似LRU算法,与传统的LRU算法不同。近似LRU算法通过随机采样来去除数据,每次随机选择5个(虚拟)键,并去除最近最少使用的键。

可以通过maxmemory-samples参数修改样本数量:

示例:maxmemory-samples10

maxmemory样本配置越大,越接近去除结果是严格LRU算法

为了实现粗略LRU算法,Redis为每个key添加了一个额外的24位字段来存储该key最后一次被访问的时间。

Redis3.0中近似LRU的改进

Redis3.0对近似LRU算法做了一些改进。新算法将维护一个过滤器池(大小为16)。池中的数据会按照访问时间进行排序。仅当访问时间小于在池中分配的最短时间时,第一个随机选择的密钥才会被放入池中,直到候选池已满。当它已满时,如果有新的密钥要放置,则访问时间最长的密钥将在集合中最后(最后访问)被删除。

当需要删除时,只需从集合中选择最近访问时间最小的key(最长未被访问过的key)并将其删除即可。