• Redis 缓存过期删除/淘汰策略分析


    Redis 缓存过期删除/淘汰策略分析

    Redis 缓存删除

    1. Redis 键过期删除,定期删除(主动)和惰性删除(被动)
    2. Redis 内存不足时,缓存淘汰策略

    key 键过期删除

    我们用 redis 作为缓存数据库,设置 k-v 数据的时候,可以给这条数据设置一个过期时间。比如,set 命令设置过期时间:

    set testkey redisvalue EX 60
    

    EX: 表示秒, EX 60 表示这个键值60秒后过期。

    那好,现在就有一个问题了,redis 怎么检查数据缓存时间到期了?然后删除它。

    想一想,检测到期数据一般有两种方法,

    第一:主动检测

    第二:被动检测

    什么是主动?

    第一种,就是每设置一个 kv 值时,给这个 kv 值设置一个定时器,给它计时,到期就删除。但是这样会给 cpu 造成很多压力。

    另外一种,定期扫描 kv 值,检查到期值在删除。

    什么是被动?

    被动就是对这个数据有操作时候才检查它缓存时间是否到期,如果有到期,就删除。

    删除步骤:

    redis 会将每个设置了过期时间的 key 放到一个独立的字典集合中,以后会定时遍历这个字典来删除到期的 key。

    定时遍历删除,默认情况每秒检查 10 次键的字典集合,每次从这个集合中随机检查 20 个键查看是否过期,过期就直接删除。删除后还有超过 25% 的集合中键过期,继续随机抽取 20 个键检测删除。

    还有惰性删除,就是在客户端访问这个 key 时,redis 会对 key 的过期时间进行检查,过期了就删除。

    Redis 内存不足时缓存淘汰策略

    redis 的 8 种缓存淘汰策略

    image-20220104181531440

    redis.conf 配置文件中,就可以看到 redis 缓存过期淘汰的设置项。

    当 Redis 内存快要满的时候,redis 会执行缓存淘汰策略。

    https://github.com/redis/redis/blob/6.2/redis.conf#L994

    # MAXMEMORY POLICY: how Redis will select what to remove when maxmemory
    # is reached. You can select one from the following behaviors:
    #
    # volatile-lru -> Evict using approximated LRU, only keys with an expire set.
    # allkeys-lru -> Evict any key using approximated LRU.
    # volatile-lfu -> Evict using approximated LFU, only keys with an expire set.
    # allkeys-lfu -> Evict any key using approximated LFU.
    # volatile-random -> Remove a random key having an expire set.
    # allkeys-random -> Remove a random key, any key.
    # volatile-ttl -> Remove the key with the nearest expire time (minor TTL)
    # noeviction -> Don't evict anything, just return an error on write operations.
    #
    #
    # The default is:
    #
    # maxmemory-policy noeviction
    

    redis v6.2 版本配置。

    maxmemory , redis 提供了一个配置参数来设置 maxmemory(redis 最大可使用内存),这个参数来限制最大内存使用,实际内存超出了这个参数设置时,redis 就根据 maxmemory-policy 的设置策略删除键值,释放内存空间。

    maxmemory-policy 设置,也就是内存淘汰策略,从 redis4.0 开始有8种缓存淘汰策略:

    noeviction:默认设置。如果设置的空间满了,不会删除任何值,写操作请求时服务器直接返回错误。读、删除请求可以继续服务。

    volatile-lru:淘汰设置了过期时间的 key,使用 lru 算法,最近最少使用的 key 先淘汰。注意,没有设置过期时间的 key 就不淘汰。why?我们是不是还有一些持久化 key 的需求。

    allkeys-lru:上面 volatile-lru 是部分淘汰 key(设置了过期时间的 key)。而这个是淘汰所有的 key,不管有没有设置过期时间,都会淘汰。也是使用 lru 最近最少使用算法。

    volatile-lfu:淘汰设置了过期时间的 key,使用 lfu 算法,使用频率最少的 key 先淘汰。

    allkeys-lfu:淘汰所有的 key,根据 lfu 算法。

    volatile-random:淘汰设置了过期时间的 key,随机算法。

    allkeys-random:淘汰所有的 key,不管是否设置过期时间,随机算法。

    volatile-ttl:淘汰设置了过期时间的 key,根据 key 的 ttl 剩余时间,也就是说 ttl 越小越先被淘汰。

    说明:使用 lfu 淘汰算法的都是 redis4.0 以上版本。

    缓存淘汰算法

    • lru:Least Recently Used,最近最少使用。
    • lfu:Least Frequently Used,使用频率最少的,最不经常使用。
    • random:随机算法。
    • ttl:根据 key 设置的 ttl 剩余时间。

    random 和 ttl 这 2 种缓存淘汰算法容易理解。

    但是 lru 和 lfu 不容易理解,他们的区别是什么呢?

    LRU :

    Least Recently Used,最近最少使用,与使用的最后一次时间有关,淘汰最近使用、时间离现在最久的。

    算法思想:

    如果一个数据最近一段时间没有被访问到,那么以后它被访问到的可能性也比较小。

    LFU :

    Least Frequently Used,最近一段时间使用频率最少,与使用的次数有关,淘汰使用次数最少的。

    LFU 是 redis4.0 以后才出现的,4.0 以前都是 LRU。那 LFU 解决的是什么问题呢?

    看下面的图,来自 antirez 博客文章 Random notes on improving the Redis LRU algorithm:

    ~~~~~A~~~~~A~~~~~A~~~~A~~~~~A~~~~~A~~|
    ~~B~~B~~B~~B~~B~~B~~B~~B~~B~~B~~B~~B~|
    ~~~~~~~~~~C~~~~~~~~~C~~~~~~~~~C~~~~~~|
    ~~~~~D~~~~~~~~~~D~~~~~~~~~D~~~~~~~~~D|
    

    每个波浪代表 1 秒,key A 每 5 秒访问一次,key B 每 2 秒访问一次,key C 和 key D 每 10 秒访问一次。"|" 表示访问结束。

    看图,从结束 "|" 位置看(实际是以时间为标准看),D 是最近一次访问。但是,从上图整体来看, B 是使用次数最多,也就是访问频率最多。如果需要淘汰的话,应该淘汰 D 才合理,LFU 才是比较合理的策略。

    如果是在一段时间内,数据使用频率更高的场景中,那么 LFU 算法比 LRU 算法命中率更高。

    参考

    == just do it ==
  • 相关阅读:
    (OK) 编译cBPM-android—CentOS 7—NDK8—androideabi-4.7— API14
    (OK) 编译xerces-c-3.1.2(动态库)—CentOS 7— android-ndk
    (OK) 编译libiconv-1.14(静态库)—CentOS 7— android-ndk
    (OK) 编译xerces-c-3.1.2(静态库)—CentOS 7— android-ndk
    (OK) 在Android系统上运行C/C++程序
    (OK—C++程序) CodeBlocks — CentOS 7 + android-ndk
    (OK) CentOS7 安装 Codeblocks
    (OK—C++程序) Eclipse C/C++ — CentOS 7 + android-ndk + eclipse-cpp-mars-R
    (OK) CentOS 7 + android-ndk-r10d-linux-x86_64 + Android (ARM)—ndk-build
    (OK—C程序) Eclipse C/C++ — CentOS 7 + android-ndk + eclipse-cpp-mars-R
  • 原文地址:https://www.cnblogs.com/jiujuan/p/15765214.html
Copyright © 2020-2023  润新知