淘汰策略概述

redis作为缓存使用时,在添加新数据的同时自动清理旧的数据。这种行为在开发者社区众所周知,也是流行的memcached系统的默认行为。

redis中使用的LRU淘汰算法是一种近似LRU的算法。

淘汰策略

针对淘汰策略,redis有一下几种配置方案:

1、noeviction:当触发内存阈值时,redis只读不写;

2、allkeys-lru:针对所有的key,执行LRU(最近最少使用)策略;

3、allkeys-lfu:针对所有的key,执行LFU(最低频使用)策略;

4、volatile-lru:针对设置了过期时间的key,执行LRU(最近最少使用)策略;

5、volatile-lfu:针对设置了过期时间的key,执行LFU(最低频使用)策略;

6、allkeys-random:针对所有key,进行随机淘汰;

7、volatile-random:针对设置了过期时间的key,进行随机淘汰;

8、volatile-ttl:针对设置了过期时间的key,淘汰剩余过期时间最短的;

根据应用场景选择合适的淘汰策略是非常重要的,我们可以在程序运行时实时重置淘汰策略,并使用Redis INFO输出来监控缓存未命中和命中的数量,以优化设置。

根据以往使用惯例:

  • 当你希望某些元素的子集被访问的频率高于其他元素,或者当你不知道怎么选择淘汰策略时,allkeys-lru策略是一个很好的选择;
  • 当你在循环访问redis,且所有的key是被连续扫描时,或者你希望key过期时间均匀分布时,allkeys-random策略是一个很好的选择;
  • 如果你希望基于key不同的TTL时间筛选出哪些key可被淘汰,volatile-ttl策略是一个很好的选择;

还有一点是为key设置过期时间会占用内存,因此使用allkeys-lru这样的策略会更节省内存,因为在内存压力下不需要对key进行过期设置。

淘汰策略如何工作

淘汰过程如下:

  • 客户端执行一条指令,需要添加一批数据;
  • redis检测缓存阈值限制,如果超过阈值则执行淘汰策略;
  • 执行指令等等;

因此在redis的使用过程中,我们可能不断的超过内存阈值限制,然后执行淘汰策略再将内存恢复到阈值之下。

近似LRU算法

redis lru算法是一个近似lru算法,这意味着针对整个key集合,redis在执行lru策略时可能不会很精准的淘汰掉最应该被淘汰的key,相反的是,redis会通过抽样一小部分key,并淘汰采样key中最该被淘汰的。
自redis3.0以来,该算法得到了改善,能够抽样大批量的key进行淘汰,使其能够更接近真实LRU算法的行为。
redis lru算法的重要之处在于可以通过更改样本数量来调整算法的精度,此参数由以下配置指令控制:
maxmemory-samples 5

redis不使用真正的LRU实现的原因是它需要更多的内存。然而,对于使用Redis的应用程序,近似lru算法实际上是与精确lru算法差不多的。此图将redis使用的LRU近似值与真实LRU进行了比较。

用给定数量的key填充了Redis服务器(达到内存阈值)进行测试并生成了上面的图。从第一个到最后一个访问key。第一个key是使用LRU算法淘汰的最佳候选key。之后再添加50%以上的key,以强制淘汰一半的旧key。

你可以在图中看到三种点,形成了三个不同的区域:

  • 浅灰色区域是被淘汰的对象
  • 灰色区域是未被淘汰的对象
  • 绿色区域是新加的对象

在理论LRU实现中(theoretical LRU),我们预计旧key集合中的前一半将会被淘汰,与之相反,redis lru算法实现中,旧key集合中也只是会离散性的淘汰其中某些key。

正如您所看到的那样,与Redis 2.8相比,Redis 3.0在同样抽样数为5个时做得更好,但是大多数最新增加的key仍然被Redis 2.8保留。在Redis 3.0中使用10的样本大小,近似值非常接近Redis 3.0的理论性能。

在模拟中,我们发现使用幂律访问模式(类似20%的key承担了80%的访问),真实LRU和Redis近似LRU之间的差异极小或根本不存在。

使用CONFIG SET maxmemory samples<count>命令在生产中使用不同的样本大小值进行实验非常简单。

新的LFU模式

从redis4.0开始,可以在某些特定场景下使用低频淘汰策略。在选用LFU策略后,redis会跟踪key的访问频率,所以低频的key将被淘汰。这意味着经常访问的key有很大的机会一直留在内存中。

要配置LFU模式,可以使用以下策略:

  • volatile-lfu:针对设置了过期时间的key,使用近似lfu淘汰;
  • allkeys-lfu:针对所有key,使用近似lfu淘汰;

LFU近似于LRU:它使用一个称为Morris的概率计数器来估计key访问频率,计数器中每个key只占用几个bit,并且计数器功能附加衰减周期,这样计数器统计的key访问频率就会随着时间的推移而降低(如果一段时间内一个key访问频率低于计数器衰减速度,最终这个key会被淘汰)。直至某一刻,我们不再将一些key视为频繁访问的key,即使它们在过去是被频繁访问的,以便算法能够适应访问模式的变化。

该信息的采样方式与LRU(如本文档前一节所述)选择淘汰key的情况类似。

然而,与LRU不同的是,LFU具有某些可调参数:例如,如果一个频繁key不再被访问,那么它的访问频率级别应该降低多少?还可以调整Morris计数器范围,以更好地使算法适应特定的场景。

默认情况下,Redis配置为:

  • 在大约100万次请求时让计数器饱和;
  • 每一分钟使计数器衰减一次;

这些配置应该是合理的,并且经过了实验测试,但用户可能希望使用这些配置设置来选择最佳值。

有关如何调整这些参数的说明,可以在源发行版的示例redis.conf文件中找到。简而言之,它们是:

lfu-log-factor 10
lfu-decay-time 1

衰减时间是最明显的一个,它是计数器在采样时应该衰减的分钟数。特殊值0表示:永远不会衰减计数器。

计数器对数因子决定了使频率计数器达到饱和需要的key命中次数,频率计数器刚好在0-255范围内。系数越高,需要更多的访问才能达到最大值;系数越低,低频访问计数器的分辨率越好,如下表所示:

Redis之key的淘汰策略的更多相关文章

  1. 动手实现 LRU 算法,以及 Caffeine 和 Redis 中的缓存淘汰策略

    我是风筝,公众号「古时的风筝」. 文章会收录在 JavaNewBee 中,更有 Java 后端知识图谱,从小白到大牛要走的路都在里面. 那天我在 LeetCode 上刷到一道 LRU 缓存机制的问题, ...

  2. Redis数据过期和淘汰策略详解(转)

    原文地址:https://yq.aliyun.com/articles/257459# 背景 Redis作为一个高性能的内存NoSQL数据库,其容量受到最大内存限制的限制. 用户在使用Redis时,除 ...

  3. Redis(二十):Redis数据过期和淘汰策略详解(转)

    原文地址:https://yq.aliyun.com/articles/257459# 背景 Redis作为一个高性能的内存NoSQL数据库,其容量受到最大内存限制的限制. 用户在使用Redis时,除 ...

  4. Redis中的LRU淘汰策略分析

    Redis作为缓存使用时,一些场景下要考虑内存的空间消耗问题.Redis会删除过期键以释放空间,过期键的删除策略有两种: 惰性删除:每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除 ...

  5. Redis系列之-—内存淘汰策略(笔记)

    一.Redis ---获取设置的Redis能使用的最大内存大小 []> config get maxmemory ) "maxmemory" ) " --获取当前内 ...

  6. Redis++:Redis 内存爆满 之 淘汰策略

    前言: 我们的redis使用的是内存空间来存储数据的,但是内存空间毕竟有限,随着我们存储数据的不断增长,当超过了我们的内存大小时,即在redis中设置的缓存大小(maxmeory 4GB),redis ...

  7. redis过期key的清理策略

    一,有三种不同的删除策略(1),立即清理.在设置键的过期时间时,创建一个回调事件,当过期时间达到时,由时间处理器自动执行键的删除操作. (2),惰性清理.键过期了就过期了,不管.当读/写一个已经过期的 ...

  8. Redis的key过期处理策略

    Redis中有三种处理策略:定时删除.惰性删除和定期删除. 定时删除:在设置键的过期时间的时候创建一个定时器,当过期时间到的时候立马执行删除操作.不过这种处理方式是即时的,不管这个时间内有多少过期键, ...

  9. redis键的过期和内存淘汰策略

    键的过期时间 设置过期时间 Redis可以为存储在数据库中的值设置过期时间,作为一个缓存数据库,这个特性是很有帮助的.我们项目中的token或其他登录信息,尤其是短信验证码都是有时间限制的. 按照传统 ...

  10. redis六种内存淘汰策略学习

    当客户端会发起需要更多内存的申请,Redis检查内存使用情况,如果实际使用内存已经超出maxmemory,Redis就会根据用户配置的淘汰策略选出无用的key; 当前Redis3.0版本支持的淘汰策略 ...

随机推荐

  1. NLP之基于Seq2Seq和注意力机制的句子翻译

    Seq2Seq(Attention) @ 目录 Seq2Seq(Attention) 1.理论 1.1 机器翻译 1.1.1 模型输出结果处理 1.1.2 BLEU得分 1.2 注意力模型 1.2.1 ...

  2. OCI runtime create failed: container_linux.go:349: starting container process caused "exec: "bash": executable file not found in $PATH": unknown

    docker save docker save centos:self -o centos.tar 导出镜像到文件 用于持久化镜像,导出的tar包需要用 docker load -i imagedat ...

  3. vs自定义工程宏

    [视图] ---->[其他窗口]----> [属性管理器 ]右键工程---->[添加新项目属性表]打开配置debug/release打开propertysheet找到用户宏即可添加

  4. Pyside2 开发框架

    apps文件夹 tools文件夹 Main.py .ui .json Global.py Main.py 通用 函数及子线程 函数内容

  5. 部署redis

    1. 下载redis 下载地址:https://redis.io/download/ 下载版本:6.2.7 应用包:redis-6.2.7.tar.gz 2. 上传服务器并解压 将redis安装包上传 ...

  6. 幂次方表达:p1010

    1 题目ID: P1010 [NOIP1998 普及组] 幂次方 2 题目描述: 任何一个正整数都可以用 22 的幂次方表示.例如 137=2^7+2^3+2^0137=27+23+20. 同时约定方 ...

  7. CentOS 8 离线安装 podman 解决方法

    CentOS 8 系统中如果没有安装Podman的话,想要离线安装会比较麻烦,因为podman依赖的包比较多,从网上一个一个下载会很繁琐,也容易出错. 这里介绍一种曲线救国的方式来离线安装. 首先分享 ...

  8. 操作系统课程设计pintos project1实验摘记

    第一部分 项目概述 一.Pintos简介 Pintos是一个基于80x86架构的简单操作系统框架,它支持内核级线程.能够加载和运行用户程序,也拥有文件系统,不过,这些功能均以一种简单的形式实现. 二. ...

  9. uwsgi 启动配置文件

    # uwsig使用配置文件启动 [uwsgi] # 项目目录 chdir=/myfiles/xxx/xxx/my_project # 指定项目的application module=my_projec ...

  10. services资源+pod详解

    services资源+pod详解 一.Service 虽然每个Pod都会分配一个单独的Pod IP,然而却存在如下两问题: Pod IP 会随着Pod的重建产生变化 Pod IP 仅仅是集群内可见的虚 ...