• redis过期删除及内存淘汰策略



    redis的内存管理机制。

    最大内存限制

    redis的内存消耗划分。
    在这里插入图片描述
    redis使用maxmemory限制最大使用内存,
    默认无限使用服务器内存,为防止极端情况内存耗尽,所以尽量为redis进程配置maxmemory,
    maxmemory限制的是used_memory,由于有内存碎片的存在,
    所以redis进程实际使用内存可能会比设置的maxmemory大,实际应用中要注意这部分的溢出。

    redis是基于内存的数据库,内存是相对珍贵的资源,
    服务器的内存是比较有限的,如果我们一直往redis中存放数据,
    总会有占满的时候,这个问题是如何解决的?

    过期策略

    redis采用定期过期+惰性过期策略。

    定期过期

    每隔一段时间,随机抽取一部分的key,查看是否超过过期时间,
    如果过期了,就删除,
    默认100ms,在配置文件redis.conf中有一个hz属性,可以设置,
    默认为10,表示1s执行10次,即100ms执行一次。

    在这里插入图片描述
    之所以不是全部,是因为如果有大量key设置了过期时间,检测一遍会给CPU造成较大负担。

    为什么不一过期就直接删除,要实现这种操作,需要对每个设置了过期时间的key,
    创建一个定时器,一旦过期就立即删除,这样会给CPU带来比较大的负载,
    进而影响系统的响应时间和吞吐量。

    惰性过期

    当超过了过期时间,先不去管它,等到key被访问的时候,我们再删除它。

    光靠过期策略是不能完全解决问题的。

    内存淘汰策略

    缓存写满是无可避免的,那内存不足时如何淘汰旧数据?

    redis.conf中定义了八种内存淘汰策略来处理这种场景。

    # volatile-lru -> remove the key with an expire set using an LRU algorithm
    	内存不足以写入新数据时,在设置了过期时间的key中,删除最近最少使用的key;
    # allkeys-lru -> remove any key according to the LRU algorithm
    	内存不足以写入新数据时,在所有的key中,删除最近最少使用的key;
    # volatile-lfu -> remove the key with an expire set using an LFU algorithm
    	内存不足以写入新数据时,在设置了过期时间的key中,删除最不经常使用的key;
    # allkeys-lfu -> remove any key according to the LFU algorithm
    	内存不足以写入新数据时,在所有的key中,删除最不经常使用的key;
    # volatile-random -> remove a random key with an expire set
    	内存不足以写入新数据时,在设置了过期时间的key中,随机删除某个key;
    # allkeys-random -> remove a random key, any key
    	内存不足以写入新数据时,在所有的key中,随机删除某个key;
    # volatile-ttl -> remove the key with the nearest expire time (minor TTL)
    	内存不足以写入新数据时,在设置了过期时间的key中,删除过期时间最早的key;
    # noeviction -> don't expire at all, just return an error on write operations
    	内存不足以写入新数据时,直接返回错误,不删除任何key(默认策略)。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    redis4.0以前是6中,4.0之后又加了两种。

    在这里插入图片描述

    根据是否会淘汰数据、淘汰数据的范围把他们分类,

    在这里插入图片描述

    这其中涉及到了LRU、LFU两种淘汰算法。

    内存淘汰算法

    LFU(least frequently used)

    LFU算法的思想是:
    如果一个数据,很少被访问到,那么可以认为它在将来被访问的可能性也很小,因此先淘汰。

    LRU(least recently used)

    LRU算法的思想是:
    如果一个数据在一段时间内,很少被访问到,那么可以认为它在将来被访问的可能性也很小,因此先淘汰。

    LRU会在LFU的基础上,同时考虑数据访问的时效性。

    LRU算法会把所有key组织成一个链表,链表的头部是MRU(maximum recently used)端,最近最常使用端,
    尾部是LRU最近最不常用端。

    下面是它的演化过程,

    在这里插入图片描述

    LRU算法在实际使用中,需要用链表管理所有的key,当有数据被访问时,需要在链表上把对应数据移动到MRU端,
    这会带来额外的空间开销,如果大量数据被访问,还会频繁地操作链表,进而降低性能。

    在redis中,LRU算法被做了简化:
    redis会记录key最后一次被访问的时间戳,在redisObject中的lru字段;
    关于redis核心对象redisObject,可以看上一篇:redis五种数据类型对应的底层数据结构
    在决定淘汰数据时,首先会随机选出n条key,把它们作为一个候选集合;
    然后比较这n条key的lru,把lru最小,即最早的数据删除。

    redis配置中有一个参数:maxmemory-samples,这就是随机选择的条数。
    在这里插入图片描述

    refs:
    程序员历小冰:详解Redis内存管理机制和实现
    程序员历小冰:一文了解Redis内存监控和内存消耗
    FrankYou:Redis内存淘汰策略
    qq_547026179:Redis过期策略以及内存淘汰机制

  • 相关阅读:
    慢SQL治理经验总结
    洛谷U53878 树上背包,指针分配内存
    MIT 6.828 Lab1(从引导扇区开始)
    Node.js学习19~37(模块化)
    PC端 Rockchip RKNN-Toolkit 连接 Rockchip NPU 设备
    Spring注解驱动之BeanFactory的初始化
    linux- socket编程-直接获取网卡-packet- sokcket
    Rethinking Image Aesthetics Assessment:Models,Datasets and Benchmarks
    TiniXml C++ 开源代码中的几个概念
    计算机视觉岗实习面经
  • 原文地址:https://blog.csdn.net/qq_35549286/article/details/126663822