Redis-内存淘汰策略

策略分类

内存写满了怎么办?Redis提供了以下几种内存淘汰的策略:

Redis-内存淘汰策略

No eviction 不淘汰数据

即,内存写满后,再有写请求时,Redis直接返回错误,不会提供服务。这也是Redis3.0之后的默认淘汰策略。

淘汰数据

设置过期时间的数据中淘汰

💜 volatile-ttl :根据过期时间的先后进行删除,越早过期越早淘汰
💜 volatile-random : 在设置了过期时间的key中,随机删除
💜 volatile-lru : 在设置了过期时间的key中,使用LRU算法淘汰
💜 volatile-lfu : 在设置了过期时间的key中,使用LFU算法淘汰

全键中淘汰

💙 allkeys-random : 在所有key中,随机删除
💙 allkeys-lru : 使用LRU算法淘汰
💙 allkeys-lfu : 使用LFU算法淘汰

大名鼎鼎的LRU

LRU 即 Least Recently Used, 越是最近被访问的越会被保留,越早以前访问的,会被淘汰。其实在MySQL Innodb内存管理部分,就已经讲过LRU了:🚪传送门

算法实现

LRU在算法实际实现时,需要用链表来管理所有缓存数据,会有额外的 空间开销以及大量数据被访问时,移动数据在链表位置的 性能消耗,会降低Redis的性能。所以Redis做了简化的LRU,键值数据对结构的RedisObject中Lru字段记录了最近一次访问的时间戳,当需要做淘汰数据时,第一次淘汰,Redis会随机选出一个数据集合,集合大小可由参数 maxmemory-samples配置,在这个集合中比较他们lru字段的大小,然后把最小的淘汰。后面淘汰,会挑选lru字段小于之前集合最小值的数据进入集合,达到集合配置大小时,进行淘汰最小的lru字段值的数据。

大名鼎鼎的LFU

在MySQL Innodb内存管理章提到,如果有全表扫描等操作,那么LRU机制会使得大部分热点数据失效,所以引入了分区(young,old)的LRU来避免。Redis避免这个问题的做法,在4.0之后增加了LFU的淘汰策略。LRU是访问一次就把该数据提到前面,而LFU是访问一次就用计数器给次数加一,然后根据次数大小比较,淘汰次数小的。自己写一个LFU的leetcode 🚪传送门

算法实现

Redis实现LFU策略时,把原来24bit大小的lru字段拆成了两部分:

  • ldt 前16bit表示时间戳
  • counter 后8bit表示数据访问次数
    由于8bit只能记录最大次数255,所以redis做了一个优化的计数规则,想想是你你会怎么做这个(一个放缩)?Redis缩放的代码实现:
double r = (double)rand()/RAND_MAX;
...

double p = 1.0/(baseval*server.lfu_log_factor+1);
if (r < p) counter++;

baseval即为计数器当前值,配置项 lfu_log_factor一般取10就行了。

同时,也会存在一部分数据在某个时间段内访问次数非常多,之后就不再访问的情况。所以Redis设计了一个counter值的衰减机制,通过 lfu_decay_time来配置。

参考资料:redis 官网

Original: https://www.cnblogs.com/rachel-aoao/p/redis_data_eviction.html
Author: rachel_aoao
Title: Redis-内存淘汰策略

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/601472/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • MySQL实战45讲 4,5

    04 | 深入浅出索引(上) 索引的出现实际上是为了提高数据查询的效率,就像一本书的目录一样。 [En] The emergence of the index is actuall…

    数据库 2023年5月24日
    0100
  • 3 访问修饰符public,private,protected以及不写(默认)时的区别

    private 私有的,只对本类公开。 default 类的成员不写访问修饰符时默认为default,默认对于同一个包中的其它类相当于公开(public),对于不是同一个包中的其它…

    数据库 2023年6月6日
    092
  • IDEA 快捷键

    普通快捷键 分类 说明 快捷键 代码提示 代码提示或自动补全 Alt + / 代码提示 Ctrl + Alt + Space 提示方法参数类型 Ctrl + P 提示注释文档 Ct…

    数据库 2023年6月6日
    080
  • 万恶的Jackson

    一、吐槽 已经是凌晨12点了我还是睡不着我所有的实体类时间用的j8的LocalDateTime这就导致一个问题:jackson不能序列化时间,因为它不支持j8的Api,让我添加 j…

    数据库 2023年6月6日
    078
  • logstash在windows系统下的安装与使用

    前言:Logstash 是开源的服务器端数据处理管道,能够同时从多个来源采集数据,转换数据,然后将数据发送到 Elasticsearch。 ES官网:https://www.ela…

    数据库 2023年6月14日
    0104
  • 第十二章 自定义类型转换器

    1.类型转换器 作用:Spring通过类型转换器把配置文件中字符串类型的数据,转换成对象中成员变量对应类型的数据,从而完成注入 2.自定义类型转换器 当Spring内部没有提供特定…

    数据库 2023年6月14日
    080
  • MySQL在Linux环境下的安装、初始化、配置

    CentOS操作系统,可选择: MySQL Community Server 8.0.28 Red Hat Enterprise Linux / Oracle Linux Red …

    数据库 2023年5月24日
    092
  • 利用rabbitmq异步实现来提升程序处理性能

    近期交易系统出款交易量猛增,从skywalking监控平台查看服务的调用链路(Trace),发现在调用外部三方http接口会耗时将近一半。鉴于出款交易在业务上是异步处理的,所以,商…

    数据库 2023年6月9日
    084
  • MySQL专题2: 事务和锁

    这属于数据库事务的基础概念了, 就是ACID Atomicity, 原子性, 事务包含的所有操作要么全部成功, 要么全部失败回滚. Consistency, 一致性, 事务执行前后…

    数据库 2023年5月24日
    0149
  • MySQL实战45讲 9

    09 | 普通索引和唯一索引,应该怎么选择? 每个人都有一个唯一的身份证号,而且业务代码已经保证了不会写入两个重复的身份证号。如果市民系统需要按照身份证号查姓名,就会执行类似这样的…

    数据库 2023年6月16日
    0109
  • 如何重置postgresql用户密码

    如何重置postgresql用户密码 场景: 打算新建一个postgresql的数据库 FooDB 并把所有者权限赋给用户 foo 正常操作应该是:先创建用户foo,再用foo身份…

    数据库 2023年6月9日
    0106
  • MySQL8.0解决“MySQL 服务无法启动。 服务没有报告任何错误。”

    TL;NRs 初始化服务时最好使用 mysqld –initialized –console命令; MySQL8.0的配置变量与MySQL5.7不同, [mysqld]下面设置…

    数据库 2023年5月24日
    0138
  • OA系统模块设计方案

    `1.模型管理 :web在线流程设&#x…

    数据库 2023年6月6日
    079
  • The user specified as a definer(‘mysql.infochema’@”localhost’) does not exist

    最近将之前用的 mysql5.5 升级到了 mysql8.0,第一天还能正常使用,几天没用后,登录发现报错:The user specified as a definer (&#8…

    数据库 2023年6月6日
    082
  • 我是个怎样的人

    我是一个怎样的人 我是一个怎样的人, 我是一个虚伪的人. 我麻木的观察着这个世界, 对好坏, 真假, 我都去同样看待, 不去区分. 我是一个怎样的人, 我是一个善良的人. 我温柔的…

    数据库 2023年6月9日
    083
  • 红黑树

    2-3-4树 JAVA技术交流群:737698533 定义 所有的叶子节点都拥有相同的深度 节点只能是2-节点,3-节点,或者4-节点 2节点 包含一个元素的节点,有两个子节点 3…

    数据库 2023年6月16日
    067
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球