前言

笔者一个同事面试某大厂时问到的一个问题,这里拿来讲讲:Redis过期后key是怎么样清理的?

在Redis中,对于过期key的清理主要有惰性清除,定时清理,内存不够时清理三种方法,下面我们就来具体看看这三种清理方法。

惰性清除

在访问key时,如果发现key已经过期,那么会将key删除。

定时清理

Redis配置项hz定义了serverCron任务的执行周期,默认每次清理时间为25ms,每次清理会依次遍历所有DB,从db随机取出20个key,如果过期就删除,如果其中有5个key过期,那么就继续对这个db进行清理,否则开始清理下一个db。

内存不够时清理

当执行写入命令时,如果发现内存不够,那么就会按照配置的淘汰策略清理内存,淘汰策略一般有6种,Redis4.0版本后又增加了2种,主要由分为三类

  • 第一类 不处理,等报错(默认的配置)noeviction,发现内存不够时,不删除key,执行写入命令时直接返回错误信息。(Redis默认的配置就是noeviction)
  • 第二类 从所有结果集中的key中挑选,进行淘汰allkeys-random 就是从所有的key中随机挑选key,进行淘汰allkeys-lru 就是从所有的key中挑选最近使用时间距离现在最远的key,进行淘汰allkeys-lfu 就是从所有的key中挑选使用频率最低的key,进行淘汰。(这是Redis 4.0版本后新增的策略)
  • 第三类 从设置了过期时间的key中挑选,进行淘汰这种就是从设置了expires过期时间的结果集中选出一部分key淘汰,挑选的算法有:volatile-random 从设置了过期时间的结果集中随机挑选key删除。volatile-lru 从设置了过期时间的结果集中挑选上次使用时间距离现在最久的key开始删除volatile-ttl 从设置了过期时间的结果集中挑选可存活时间最短的key开始删除(也就是从哪些快要过期的key中先删除)volatile-lfu 从过期时间的结果集中选择使用频率最低的key开始删除(这是Redis 4.0版本后新增的策略)

LRU算法

LRU算法的设计原则是如果一个数据近期没有被访问到,那么之后一段时间都不会被访问到。所以当元素个数达到限制的值时,优先移除距离上次使用时间最久的元素。

可以使用双向链表Node+HashMap来实现,每次访问元素后,将元素移动到链表头部,当元素满了时,将链表尾部的元素移除,HashMap主要用于根据key获得Node以及添加时判断节点是否已存在和删除时快速找到节点。

PS:使用单向链表能不能实现呢,也可以,单向链表的节点虽然获取不到pre节点的信息,但是可以将下一个节点的key和value设置在当前节点上,然后把当前节点的next指针指向下下个节点,这样相当于把下一个节点删除了

//双向链表    public static class ListNode {        String key;//这里存储key便于元素满时,删除尾节点时可以快速从HashMap删除键值对        Integer value;        ListNode pre = null;        ListNode next = null;        ListNode(String key, Integer value) {            this.key = key;            this.value = value;        }    }    ListNode head;    ListNode last;    int limit=4;        HashMap hashMap = new HashMap();    public void add(String key, Integer val) {        ListNode existNode = hashMap.get(key);        if (existNode!=null) {            //从链表中删除这个元素            ListNode pre = existNode.pre;            ListNode next = existNode.next;            if (pre!=null) {               pre.next = next;            }            if (next!=null) {               next.pre = pre;            }            //更新尾节点            if (last==existNode) {                last = existNode.pre;            }            //移动到最前面            head.pre = existNode;            existNode.next = head;            head = existNode;            //更新值            existNode.value = val;        } else {            //达到限制,先删除尾节点            if (hashMap.size() == limit) {                ListNode deleteNode = last;                hashMap.remove(deleteNode.key);              //正是因为需要删除,所以才需要每个ListNode保存key                last = deleteNode.pre;                deleteNode.pre = null;                last.next = null;            }            ListNode node = new ListNode(key,val);            hashMap.put(key,node);            if (head==null) {                head = node;                last = node;            } else {                //插入头结点                node.next = head;                head.pre = node;                head = node;            }        }    }    public ListNode get(String key) {        return hashMap.get(key);    }    public void remove(String key) {        ListNode deleteNode = hashMap.get(key);        ListNode preNode = deleteNode.pre;        ListNode nextNode = deleteNode.next;        if (preNode!=null) {            preNode.next = nextNode;        }        if (nextNode!=null) {            nextNode.pre = preNode;        }        if (head==deleteNode) {            head = nextNode;        }        if (last == deleteNode) {            last = preNode;        }        hashMap.remove(key);    }

最后

LFU算法的设计原则时,如果一个数据在最近一段时间被访问的时次数越多,那么之后被访问的概率会越大,基本实现是每个数据都有一个引用计数,每次数据被访问后,引用计数加1,需要淘汰数据时,淘汰引用计数最小的数据。在Redis的实现中,每次key被访问后,引用计数是加一个介于0到1之间的数p,并且访问越频繁p值越大,而且在一定的时间间隔内,如果key没有被访问,引用计数会减少。

redis查看key的过期时间_面试官:Redis过期后key是怎么样清理的?相关推荐

  1. redis查看key的过期时间_面试官:你在Redis中设置过带过期时间的Key吗?

    点击上方小伟后端笔记关注公众号 每天阅读Java干货文章 熟悉Redis的同学应该知道,Redis的每个Key都可以设置一个过期时间,当达到过期时间的时候,这个key就会被自动删除. 在为key设置过 ...

  2. redis list设置过期时间_面试官:你在Redis中设置过带过期时间的Key吗?

    点击上方小伟后端笔记关注公众号 每天阅读Java干货文章 熟悉Redis的同学应该知道,Redis的每个Key都可以设置一个过期时间,当达到过期时间的时候,这个key就会被自动删除. 在为key设置过 ...

  3. redis做mysql缓存的优点_面试官:如何保障数据库和redis缓存的一致性

    随着互联网的高速发展,使用互联网产品的人也越来越多,团队不可避免得也会面对越来越复杂的高并发业务场景(如下图),比如热点视频/文章的观看(读场景),热点视频/文章的评论,点赞等(写场景). 众所周知, ...

  4. httpclient 设置超时时间_面试官:技术选型,HttpClient还是OkHttp?

    你知道的越多,不知道的就越多,业余的像一棵小草! 你来,我们一起精进!你不来,我和你的竞争对手一起精进! 编辑:业余草 来源:juejin.im/post/6844904040644476941 推荐 ...

  5. 设置过期时间_在Redis中设置了过期时间的Key,需要注意哪些问题?

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:千山qianshan juejin.im/post/5d6b ...

  6. redis setnx 过期时间_阿里面试官:你确定你用过 Redis 分布式锁吗?

    你有听说过 Redlock 吗? 别整些花里胡哨的,Redlock 全称 Redis Distributed Lock,即用 Redis 实现的分布式锁. Redis 热身知识 Redis 命令参考: ...

  7. redis 设置不过期_面试时 Redis 内存淘汰总被问,但是总答不好,怎么解决?

    什么是内存淘汰 内存淘汰,和平时我们设置redis key的过期时间,不是一回事:内存淘汰是说,假设我们限定redis只能使用8g内存,现在已经使用了这么多了(包括设置了过期时间的key和没设过期时间 ...

  8. c# redis 如何设置过期时间_Spring cache整合Redis,并给它一个过期时间!

    小Hub领读: 不知道你们有没给cache设置过过期时间,来试试? 上一篇文章中,我们使用springboot集成了redis,并使用RedisTemplate来操作缓存数据,可以灵活使用. 我才懂! ...

  9. java控制订单过期时间_订单自动过期实现方案

    需求分析:24小时内未支付的订单过期失效. 解决方案被动设置:在查询订单的时候检查是否过期并设置过期状态. 定时调度:定时器定时查询并过期需要过期的订单. 延时队列:将未支付的订单放入一个延时队列中, ...

最新文章

  1. 虚拟化---简单高效的IT管理模型
  2. Android应用--简、美音乐播放器获取专辑图片(自定义列表适配器)
  3. 郑州尚学堂:JAVA常用4种排序方法
  4. 由Thread.sleep引发的
  5. php显示服务器拒绝连接失败,php – SMTP ERROR:无法连接到服务器:连接被Office365拒绝(111)...
  6. mysql 暴力破解 root账号密码
  7. java agent_如何脚踏实地构建Java Agent
  8. element中select默认选中第一个_探索在网页中使用“标注”
  9. 【Animation】 使用handler和Runnable实现某一个控件的抖动效果
  10. 处理minist数据集,把网络和数据都放在gpu上面。
  11. 通信(1)---LTE 整体架构
  12. 创建ASPState数据库
  13. python菜鸟教程网-Python JSON
  14. 雷林鹏分享:MySQL DELETE 语句
  15. 树莓派小实验 | 制作一个带快门的照相机 录像机
  16. 桌面快捷方式计算机打不开,桌面快捷方式打不开,详细教您桌面快捷方式打不开怎么解决...
  17. [OpenCV实战]23 使用OpenCV获取高动态范围成像HDR
  18. 智能DNS之DNS原理与解析
  19. SDUT-3337 计算长方体、四棱锥的表面积和体积(JAVA*)
  20. 破解Windows7开机密码

热门文章

  1. 福师离线 微型计算机与外部,福师《计算机应用基础》离线作业答案
  2. android图片分辨率改变,android 通过修改图片像素实现CircleImageView
  3. python编程学习_使用EduBlocks轻松学习Python编程
  4. 敏捷团队为何失败,Bash技巧,Emacs vs. Vim,为Linux粉丝撰写的12部小说读物,以及其他热门歌曲
  5. devops 开发_DevOps如何消除开发瓶颈
  6. 互联网 性能 开源_开源的互联网25年及未来
  7. java string范围_字符串索引超出范围? (Java,子字符串循环...
  8. ROS笔记(26) Movelt!
  9. mysql benchmark 测试工具_BenchmarkSQL数据库基准测试工具
  10. pb调用键盘钩子的例子_搞不动Vue3.0的源码,先做个API调用师也行(新人踩坑初试)...