Redis内存回收机制

  Redis的内存回收机制主要是下面列举的两种:

   1.删除达到过期时间的键对象。

   2.内存使用达到maxmemory(redis所能够使用的最大内存)上限时出发内存溢出控制策略。

  

  先来说说删除过期键对象

  众所周知Redis所有的键都可以设置一个过期属性,内部保存在过期字典中。但由于进程内保存着大量的键,如果对每个键的过期删除的机制都进行维护,那不用想,肯定会消耗大量的CPU,单线程的Redis本来就讲究一个快,这么整肯定不行,与Redis的设计初衷不符,因此Redis采用了惰性删除机制定时任务删除机制实现过期键的内存回收。
  

  • 惰性删除
      
     通俗易懂的来说就是,Redis不会主动删除过期的键,等客户端读取的时候,在对这个键进行判断,如果超过了设置的过期时间,就删除并返回空,如果没超过就把值返回给客户端。使用这种策略可以不用精准的维护每个键的过期删除机制,大大节省了CPU成本,但是单独使用这种策略存在内存泄漏的问题,Redis是等客户端读取才对数据进行判断,那么问题来了,要是有一堆设置了过期时间的数据长时间没有被读取,那么这些数据肯定也不会被删除,内存也无法即时释放。所以,Redis还提供另一种定时任务删除机制作为惰性删除的补充。
      
  • 定时任务删除
      
     Redis内部维护了一个定时任务,默认是每秒运行十次(可以通过配置hz控制)。定时任务中删除过期键采用了自适应逻辑算法,可以根据键的过期比例和使用快慢两种速率回收键(默认慢模式)。

     流程说明:
  • a. 定时任务在每个数据库随机检查20个键,当发现其中有键过期时,立即删除。
  • b. 如果超过检查数25%的键过期(也就是平均每个库有5个或者5个以上的键过期),就循环执行回收逻辑直到不足25%或运行超时为止,默认的慢模式下超时时间为25毫秒。
  • c. 如果之前的回收键逻辑超时,则在Redis触发内部事件之前再次以快模式运行回收过期键任务,快模式超时时间为1毫秒且2秒内只能运行1次。
  • d. 快慢两种模式的内部逻辑是一样的,只是执行的超时时间不同。

  再来看看内存溢出控制策略

  当Redis所用内存达到maxmemory上限时会触发相应的溢出控制策略。具体策略受 maxmemory-policy 参数控制(不控制的话,当内存达到最大物理内存就会出现内存交换),最初Redis支持6种策略,在4.0版本后提供了两种新的策略,如下:

  1.noeviction:默认的策略,不删除任何数据,拒绝所有写入操作并返回错误信息给客户端,正常响应读操作。
  
  2.volatile-lru :根据LRU(最近最少使用算法)算法删除设置了超时属性(expire)的键,直到有了足够的空间为止。如果没有可删除的键,则还是按默认的noeviction策略执行。
  
  3.volatile-ttl :根据LRU(最近最少使用算法)算法删除键(无论设没设置超时属性),直到有了足够的空间为止。
  
  4.volatile-random:随机删除所有键,直到有了足够的空间为止。
  
  5.allkeys-lru :随机删除过期键,直到有了足够的空间为止。
  
  6.allkeys-random:根据键的TTL(查看过期设置)属性,删除即将要过期的键,如果没有,则还是按默认的noeviction策略执行。
  
  7.allkeys-random:根据LFU(最不经常使用算法)算法随机淘汰全部key。
  
  8.volatile-lfu:根据LFU(最不经常使用算法)算法随机淘汰过期key。
  
  
  内存溢出控制策略可以用config set maxmemory {策略名}来进行配置,可以根据需求使用不同的策略灵活定制。当Redis因为内存溢出而删除了键时,可以通过info stats命令查看evicted_keys指标得到Redis删除键的数量。
  
  其实如果需要收缩Redis的内存,直接把maxmemory参数的值调小就行了,如果当前Redis使用的是非默认策略,它会直接一次性回收到用户指定(maxmemory)的大小,以此实现快速回收的目的,但是这样会导致部分数据 丢失并且会有短暂的堵塞问题,多使用与将Redis当作缓存的场景下。
  

    先就写这么多了。

  以上内容主要来自《Redis开发与运维》。

  这本书同样很nice(不是广告),感兴趣的小伙伴可以去淘宝的新华书店购买。

  我发言完毕 bye~

猜你喜欢

转载自blog.csdn.net/imagineluopan/article/details/120786269