Redis缓存满了,如何存放数据?缓存淘汰策略
我们的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 按以下方式递增:
- 提取 0 和 1 之间的随机数 R。
- counter - 初始值(默认为 5),得到一个基础差值,如果这个差值小于 0,则直接取 0,为了方便计算,把这个差值记为 baseval。
- 概率 P 计算公式为:1/(baseval * lfu_log_factor + 1)。
- 如果 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缓存满了,如何存放数据?缓存淘汰策略的更多相关文章
- Dcloud课程5 php如何实现文件缓存技术(静态数据缓存)
Dcloud课程5 php如何实现文件缓存技术(静态数据缓存) 一.总结 一句话总结:保存在磁盘上的静态文件,用PHP生成数据到静态文件中.其实cookie和session使用的就是这样的技术,所以c ...
- Redis在windows实现将数据缓存起来定时更新读取
实现接口的读取存放在内存中,实现了Web网站直接读取内存数据,大大的减少了访问接口带来的等待时间,这个功能是比较实用的 需要下载一下‘类库’及‘Redis-x64-3.2.100程序包’ 百度云材料下 ...
- ecshop二次开发系统缓存优化之扩展数据缓存的必要性与方法
1.扩展数据缓存的必要性 大家都知道ecshop系统使用的是静态模板缓存,在后台可以设置静态模板的缓存时间,只要缓存不过期,用户访问页面就相当于访问静态页面,速度可想而知,看似非常完美,但是ecsho ...
- Redis达到最大占用内存后的淘汰策略
1. 查询Redis最大占用内存 # 查询最大占用内存 config get maxmemory # 为0时在64操作系统中不限制内存,在32位操作系统中最大为3GB 2. Redis设置最大占用内存 ...
- .net 缓存之应用程序数据缓存
CaCheHelp类中代码如下: #region 根据键从缓存中读取保持的数据 /// <summary> /// 根据键从缓存中读取保持的数据 /// </summary> ...
- Redis中如何保证数据库和缓存双写时的数据的一致性?
简单的场景: 直接使用 1. 使用Cache Aside pattern 读取的时候,先读取缓存中是否有数据,缓存中没有数据,再去数据库中进行查询,查询出来以后,然后再存入到缓存中 更新的时候,先删除 ...
- jQuery 2.0.3 源码分析 数据缓存
历史背景: jQuery从1.2.3版本引入数据缓存系统,主要的原因就是早期的事件系统 Dean Edwards 的 ddEvent.js代码 带来的问题: 没有一个系统的缓存机制,它把事件的回调都放 ...
- jQuery源代码学习之六——jQuery数据缓存Data
一.jQuery数据缓存基本原理 jQuery数据缓存就两个全局Data对象,data_user以及data_priv; 这两个对象分别用于缓存用户自定义数据和内部数据: 以data_user为例,所 ...
- jQuery数据缓存data(name, value)详解及实现
一. jQuery数据缓存的作用 jQuery数据缓存的作用在中文API中是这样描述的:“用于在一个元素上存取数据而避免了循环引用的风险”.如何理解这句话呢,看看我下面的举例,不知道合不合适,如果你有 ...
- jQuery 源码分析(十) 数据缓存模块 data详解
jQuery的数据缓存模块以一种安全的方式为DOM元素附加任意类型的数据,避免了在JavaScript对象和DOM元素之间出现循环引用,以及由此而导致的内存泄漏. 数据缓存模块为DOM元素和JavaS ...
随机推荐
- 【原创】不同RTOS POSIX接口的实现差异
目录 前言 POSIX简介 RTOS对POSIX的实现情况 Zephyr FreeRTOS RTOS提供的POSIX接口实时吗? nanosleep Timer-不同linux版本和xenomai的实 ...
- linux文本三剑客之sed命令详解
linux文本三剑客之sed命令详解 目录 linux文本三剑客之sed命令详解 1.sed命令详解 1.1 地址定界和编辑命令 1.2 搜索替换 1.3 sed高级用法 1.sed命令详解 sed称 ...
- python教程6.4-json序列化
序列化:dumps,编码,将python类型转成json对象 反序列化:loads,解码,将json对象转成python对象 pickle 模块提供了四个功能:dumps.loads.dump.loa ...
- UE4/5 应用角色根运动的问题
总的来说UE还是有点绕,网上提到的也不是很清晰,记录下. 具体可以下载UE官方示例ContentExample并进入Animation Level进行查看. 在Level中能看到根运动的必要步骤: 1 ...
- JDK源码阅读-------自学笔记(八)(数组演示冒泡排序和二分查找)
冒泡排序 算法 比较相邻的元素.如果第一个比第二个大,就交换他们两个 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对.在这一点,最后的元素应该会是最大的数 针对所有的元素重复以上的步骤,除 ...
- .NET 9 预览版:打造云原生及人工智能 AI 平台
前言 微软发布了 .NET 9 首个预览版,分享.NET团队对 .NET 9 的初步愿景,该愿景将于今年年底在 .NET Conf 2024 上发布. 重点关注针对云原生和人工智能领域的应用程序开发以 ...
- SCSS随笔-mixin与@extend
变量 定义变量 $color-white: white; 使用变量 body { background-color: $color-white; } @mixin 与 @include 定义mixin ...
- 【ESP32】制作 Wi-fi 音箱(HTTP + I2S 协议)
用 Wifi 来传输音频数据,会比蓝牙更好.使用蓝牙方式,不管你用什么协议,都会对数据重新编码,说人话就是有损音质,虽然不至于全损.而使用 Wifi 就可以将 PCM 数据直接传输,无需再编码和压缩. ...
- 【Azure App Service】.NET代码实验App Service应用中获取TLS/SSL 证书 (App Service Windows)
在使用App Service服务部署业务应用,因为有些第三方的接口需要调用者携带TLS/SSL证书(X509 Certificate),在官方文档中介绍了两种方式在代码中使用证书: 1) 直接使用证书 ...
- CSP-S2021 游记
那天是惊蛰 满天花瓣 就像现在 我看清了无池里的那个人 前言 终于是开了 游记 的坑(期盼已久!) 虽然参加过 CSP-J2019 ,CSP-S2020 以及 NOIP2020 ,但是都没有写过游记( ...