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

Redis 当中提供了不同的淘汰策略来处理这种场景。

首先 Redis 提供了一个参数 maxmemory 来配置 Redis 最大使用内存:

maxmemory <bytes>

或者也可以通过命令 config set maxmemory 1GB 来动态修改。

如果没有设置该参数,那么在 32 位的操作系统中 Redis 最多使用 3GB 内存,而在 64 位的操作系统中则不作限制。

Redis 中提供了 8 种淘汰策略,可以通过参数 maxmemory-policy 进行配置:

根据是否进行数据淘汰可以分为:不淘汰的数据策略和7种淘汰数据策略。

PS:淘汰策略也可以直接使用命令 config set maxmemory-policy <策略> 来进行动态配置。


LRU 算法

LRU 全称为:Least Recently Used。即:最近最少使用原则来进行数据的淘汰算法。这个主要针对的是使用时间。

Redis 改进后的 LRU 算法

在 Redis 当中,并没有采用传统的 LRU 算法,因为传统的 LRU 算法存在 2 个问题:

  • 需要额外的空间进行存储。
  • 可能存在某些 key 值使用很频繁,但是最近没被使用,从而被 LRU 算法删除。

为了避免以上 2 个问题,Redis 当中对传统的 LRU 算法进行了改造,通过抽样的方式进行删除。

配置文件中提供了一个属性 maxmemory_samples 5,默认值就是 5,表示随机抽取 5 个 key 值,然后对这 5 个 key 值按照 LRU 算法进行删除,所以很明显,key 值越大,删除的准确度越高。

LRU 算法原理:

将数据放入到一个链表中,当链表中的某个元素被访问时,这个元素就被会提到链表的前面,其他元素,默认向后移动;

当这个时候我们想缓存中新增一个元素时,也会被增加到链表的头部,那么尾部的最后一个元素就被淘汰了。


LFU 算法

LFU 全称为:Least Frequently Used。即:最近使用最少的数据将被淘汰。这个主要针对的是使用频率。

当我们采用 LFU 回收策略时,lru 属性的高 16 位用来记录访问时间(last decrement time:ldt,单位为分钟),低 8 位用来记录访问频率(logistic counter:logc),简称 counter。

LFU 算法步骤

根据数据的访问次数进行筛选,淘汰访问次数少的数据,如果访问次数相同,在根据访问时间进行比较,淘汰访问时间久远的数据。

redis中的实现方式:

就是在RedisObject的字段lru上,拆分为两个部分

访问频次递增

LFU 计数器每个键只有 8 位,它能表示的最大值是 255,所以 Redis 使用的是一种基于概率的对数器来实现 counter 的递增。

给定一个旧的访问频次,当一个键被访问时,counter 按以下方式递增:

  1. 提取 0 和 1 之间的随机数 R。
  2. counter - 初始值(默认为 5),得到一个基础差值,如果这个差值小于 0,则直接取 0,为了方便计算,把这个差值记为 baseval。
  3. 概率 P 计算公式为:1/(baseval * lfu_log_factor + 1)。
  4. 如果 R < P 时,频次进行递增(counter++)。

公式中的 lfu_log_factor 称之为对数因子,默认是 10 ,可以通过参数来进行控制:

lfu_log_factor 10

访问频次递减

如果访问频次 counter 只是一直在递增,那么迟早会全部都到 255,也就是说 counter 一直递增不能完全反应一个 key 的热度的,所以当某一个 key 一段时间不被访问之后,counter 也需要对应减少。

counter 的减少速度由参数 lfu-decay-time 进行控制,默认是 1,单位是分钟。默认值 1 表示:N 分钟内没有访问,counter 就要减 N。

lfu-decay-time 1
计算公式:

取出当前的时间戳和对象中的 lru 属性进行对比,计算出当前多久没有被访问到,比如计算得到的结果是 100 分钟没有被访问,然后再去除配置参数 lfu_decay_time,如果这个配置默认为 1也即是 100/1=100,代表 100 分钟没访问,所以 counter 就减少 100。


redis的淘汰策略怎么选?

每种淘汰策略都会有自己的使用场景,我们在设置redis的淘汰策略的时候,就需要结合自己的业务场景去定制化的配置。

  • 可以优先将淘汰策略设置为allkeys-lru,这样可以充分利用lru算法的特性,把最近访问的数据都留在缓存中,长时间没有访问的数据给淘汰掉。

  • 如果业务中的访问数据,没有冷热数据之分,数据的访问时间相差不大,可以采用allkeys-lru策略。

  • 如果在业务中,有需要置顶数据,可以不给置顶数据设置过期时间,然后采用volatile-lru策略来实现。

  • 如果在业务中,有一些定时任务的数据,过了这个时间段后,基本就不会访问的数据,可以采用allkeys-lfu算法。

Redis缓存满了,如何存放数据?缓存淘汰策略的更多相关文章

  1. Dcloud课程5 php如何实现文件缓存技术(静态数据缓存)

    Dcloud课程5 php如何实现文件缓存技术(静态数据缓存) 一.总结 一句话总结:保存在磁盘上的静态文件,用PHP生成数据到静态文件中.其实cookie和session使用的就是这样的技术,所以c ...

  2. Redis在windows实现将数据缓存起来定时更新读取

    实现接口的读取存放在内存中,实现了Web网站直接读取内存数据,大大的减少了访问接口带来的等待时间,这个功能是比较实用的 需要下载一下‘类库’及‘Redis-x64-3.2.100程序包’ 百度云材料下 ...

  3. ecshop二次开发系统缓存优化之扩展数据缓存的必要性与方法

    1.扩展数据缓存的必要性 大家都知道ecshop系统使用的是静态模板缓存,在后台可以设置静态模板的缓存时间,只要缓存不过期,用户访问页面就相当于访问静态页面,速度可想而知,看似非常完美,但是ecsho ...

  4. Redis达到最大占用内存后的淘汰策略

    1. 查询Redis最大占用内存 # 查询最大占用内存 config get maxmemory # 为0时在64操作系统中不限制内存,在32位操作系统中最大为3GB 2. Redis设置最大占用内存 ...

  5. .net 缓存之应用程序数据缓存

    CaCheHelp类中代码如下: #region 根据键从缓存中读取保持的数据 /// <summary> /// 根据键从缓存中读取保持的数据 /// </summary> ...

  6. Redis中如何保证数据库和缓存双写时的数据的一致性?

    简单的场景: 直接使用 1. 使用Cache Aside pattern 读取的时候,先读取缓存中是否有数据,缓存中没有数据,再去数据库中进行查询,查询出来以后,然后再存入到缓存中 更新的时候,先删除 ...

  7. jQuery 2.0.3 源码分析 数据缓存

    历史背景: jQuery从1.2.3版本引入数据缓存系统,主要的原因就是早期的事件系统 Dean Edwards 的 ddEvent.js代码 带来的问题: 没有一个系统的缓存机制,它把事件的回调都放 ...

  8. jQuery源代码学习之六——jQuery数据缓存Data

    一.jQuery数据缓存基本原理 jQuery数据缓存就两个全局Data对象,data_user以及data_priv; 这两个对象分别用于缓存用户自定义数据和内部数据: 以data_user为例,所 ...

  9. jQuery数据缓存data(name, value)详解及实现

    一. jQuery数据缓存的作用 jQuery数据缓存的作用在中文API中是这样描述的:“用于在一个元素上存取数据而避免了循环引用的风险”.如何理解这句话呢,看看我下面的举例,不知道合不合适,如果你有 ...

  10. jQuery 源码分析(十) 数据缓存模块 data详解

    jQuery的数据缓存模块以一种安全的方式为DOM元素附加任意类型的数据,避免了在JavaScript对象和DOM元素之间出现循环引用,以及由此而导致的内存泄漏. 数据缓存模块为DOM元素和JavaS ...

随机推荐

  1. python教程3.1:数据类型:字符串+列表list

    一.字符串 字符串是⼀个有序的字符的集合,⽤于在计算机⾥存储和表示⽂本信息  常用方法--str.fun() 全局函数 二.列表list []内以逗号分隔,按照索引,存放各种数据类型,每个位置代表⼀个 ...

  2. java学习之旅(day.19)

    多线程 线程简介 多任务:同时做多件事 进程(Process):在操作系统中运行的程序就是进程,如QQ,播放器,游戏. 线程(Thread):一个进程可以有多个线程,如视频中同时听声音,看弹幕,看图像 ...

  3. AIRIOT可视化组态引擎如何应用于物联业务场景中

    在物联网的业务应用场景中,可视化组态是一个必不可少的功能需求.不同的行业场景,都需要将物联设备采集的数据和业务场景状态进行直观的可视化展示,供使用者进行分析或决策.如工艺流程用能监测.3D场景构建.能 ...

  4. 彻底搞懂JavaScript原型和原型链

    基于原型编程 在面向对象的编程语言中,类和对象的关系是铸模和铸件的关系,对象总是从类创建而来,比如Java中,必须先创建类再基于类实例化对象. 而在基于原型编程的思想中,类并不是必须的,对象都是通过克 ...

  5. winform cefsharp chart.js 再winform上使用chart.js 绘制动态曲线

    CefSharp 是一款开源的使用.net平台基于谷歌的 封装浏览器组件,可用于winform wpf . chart.js 也是一款开源的图表展示组件. 我所作的就是使用这两个组件再winform上 ...

  6. 你不知道的PageContext

    你不知道的PageContext 最近在文艺复兴,学习JSP和Servlet,此文为笔者学习记录. 本文分为以下几个部分: 前言 环境搭建 正文 总结 前言 在我们使用的项目中,存储数据最常用的非 S ...

  7. 23ai中的True Cache到底能做啥?

    最近,Oracle的产品管理总监在Oracle数据库内幕中介绍了True Cache. 原文链接如下: https://blogs.oracle.com/database/post/introduci ...

  8. C#.Net筑基-深入解密小数内部存储的秘密

    为什么0.1 + 0.2 不等于 0.3?为什么16777216f 等于 16777217f?为什么金钱计算都推荐用decimal?本文主要学习了解一下数字背后不为人知的存储秘密. 01.数值类型 C ...

  9. c# IdHelper生成唯一的雪花Id

    为什么使用雪花ID 在以前的项目中,最常见的两种主键类型是自增Id和UUID,在比较这两种ID之前首先要搞明白一个问题,就是为什么主键有序比无序查询效率要快,因为自增Id和UUID之间最大的不同点就在 ...

  10. 基于Vue的二进制时钟组件 -- fx67llBinaryClock

    fx67llClock Easy & Good Clock ! npm 组件说明 一个基于Vue的二进制时钟组件,没什么卵用,做着好玩,可以方便您装饰个人主页 使用步骤 npm install ...