前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >redis的过期策略以及内存淘汰机制

redis的过期策略以及内存淘汰机制

作者头像
名字是乱打的
发布2021-12-22 14:56:48
2880
发布2021-12-22 14:56:48
举报
文章被收录于专栏:软件工程软件工程

注:本文主要参考自《Redis设计与实现》 https://www.cnblogs.com/xuliangxing/p/7151812.html https://www.cnblogs.com/sunsing123/p/11093038.html http://www.imooc.com/article/257065?block_id=tuijian_wz

1、设置过期时间

所谓过期,就是我们插入数据的时候设置了过期时间,一班情况下有下面两种设置g

  • expire key time(以秒为单位)--这是最常用的方式
  • setex(String key, int seconds, String value)--字符串独有的方式

具体的使用方式:查看"java企业项目开发实践"的第九章 企业项目开发--分布式缓存Redis(1)第十章 企业项目开发--分布式缓存Redis(2)

注意

  • 除了字符串自己独有设置过期时间的方法外,其他方法都需要依靠expire方法来设置时间
  • 如果没有设置时间,那缓存就是永不过期
  • 如果设置了过期时间,之后又想让缓存永不过期,使用persist key

2、两种常用的过期策略

对于上面咱们设置了过期时间的数据,那数据到期了咱们怎么删除呢?

  • 惰性删除
    • 含义:key过期的时候不删除,每次从数据库获取key的时候去检查是否过期,若过期,则删除,返回null。
    • 优点:删除操作只发生在从数据库取出key的时候发生,而且只删除当前key,所以对CPU时间的占用是比较少的,而且此时的删除是已经到了非做不可的地步(如果此时还不删除的话,我们就会获取到了已经过期的key了)
    • 缺点:若大量的key在超出超时时间后,很久一段时间内,都没有被获取过,那么可能发生内存泄露(无用的垃圾占用了大量的内存)
  • 定期删除
    • 含义:每隔一段时间执行一次删除过期key操作
    • 优点: 通过限制删除操作的时长和频率,来减少删除操作对CPU时间的占用--处理"定时删 定期删除过期key--处理"惰性删除"的缺点
    • 缺点 在内存友好方面,不如"定时删除" 在CPU时间友好方面,不如"惰性删除"
    • 难点 合理设置删除操作的执行时长(每次删除执行多长时间)和执行频率(每隔多长时间做一次删除)(这个要根据服务器运行情况来定了)

注意

  • 对于主从redis结构的从结点slave的过期key处理 slave的key不会过期,只会等待master的key过期。如果master的key过期,或者通过LRU淘汰了key,那么会发送一条模拟的del命令给slave
  • 上边所说的数据库指的是内存数据库,默认情况下每一台redis服务器有16个数据库(关于数据库的设置,看下边代码),默认使用0号数据库,所有的操作都是对0号数据库的操作,关于redis数据库的存储结构,查看 第八章 Redis数据库结构与读写原理
  • memcached只是用了惰性删除,而redis同时使用了惰性删除与定期删除,这也是二者的一个不同点(可以看做是redis优于memcached的一点)
  • 对于惰性删除而言,并不是只有获取key的时候才会检查key是否过期,在某些设置key的方法上也会检查(eg.setnx key2 value2:该方法类似于memcached的add方法,如果设置的key2已经存在,那么该方法返回false,什么都不做;如果设置的key2不存在,那么该方法设置缓存key2-value2。假设调用此方法的时候,发现redis中已经存在了key2,但是该key2已经过期了,如果此时不执行删除操作的话,setnx方法将会直接返回false,也就是说此时并没有重新设置key2-value2成功,所以对于一定要在setnx执行之前,对key2进行过期检查

3、Redis采用的过期策略

惰性删除+定期删除
  • 惰性删除流程 在进行get或setnx等操作时,先检查key是否过期, 若过期,删除key,然后执行相应操作; 若没过期,直接执行相应操作
  • 定期删除流程(简单而言,对指定个数个库的每一个库随机删除小于等于指定个数个过期key) 遍历每个数据库(就是redis.conf中配置的"database"数量,默认为16) 默认Reds每秒10次做的事情: 1.测试随机的20个keys进行相关过期检测 2.删除所有已经过期的keys。 3.如果有多于25%的keys过期,重复步奏1 这是一个平凡的概率算法,基本上的假设是,我们的样本是这个密钥控件,并且我们不断重复过期检测,直到过期的keys的百分百低于25%这意味着,在任何给定的时刻,最多会清除14的过期keys.

如果当前库中没有一个key设置了过期时间,直接执行下一个库的遍历 随机获取一个设置了过期时间的key,检查该key是否过期,如果过期,删除key 判断定期删除操作是否已经达到指定时长,若已经达到,直接退出定期删除。

注意:

对于定期删除,在程序中有一个全局变量current_db来记录下一个将要遍历的库,假设有16个库,我们这一次定期删除遍历了10个,那此时的current_db就是11,下一次定期删除就从第11个库开始遍历,假设current_db等于15了,那么之后遍历就再从0号库开始(此时current_db==0) 由于在实际中并没有操作过定期删除的时长和频率,所以这两个值的设置方式作为疑问?

4、RDB对过期key的处理

过期key对RDB没有任何影响

从内存数据库持久化数据到RDB文件 持久化key之前,会检查是否过期,过期的key不进入RDB文件 从RDB文件恢复数据到内存数据库 数据载入数据库之前,会对key先进行过期检查,如果过期,不导入数据库(主库情况)

5、AOF对过期key的处理

过期key对AOF没有任何影响

从内存数据库持久化数据到AOF文件: 当key过期后,还没有被删除,此时进行执行持久化操作(该key是不会进入aof文件的,因为没有发生修改命令) 当key过期后,在发生删除操作时,程序会向aof文件追加一条del命令(在将来的以aof文件恢复数据的时候该过期的键就会被删掉) AOF重写 重写时,会先判断key是否过期,已过期的key不会重写到aof文件

5. redis内存淘汰机制

内存淘汰机制 Redis 的内存占用会越来越高。Redis 为了限制最大使用内存,提供了 redis.conf 中的配置参数 maxmemory。

当内存超出 maxmemory,Redis 提供了几种内存淘汰机制让用户选择,配置 maxmemory-policy:

  • noeviction:当内存超出 maxmemory,写入请求会报错,但是删除和读请求可以继续。(不推荐,使用这个策略,疯了吧)
  • allkeys-lru:当内存超出 maxmemory,所有的 key 中,移除最少使用的key。只把 Redis 既当缓存是使用这种策略。(推荐)。
  • allkeys-random:当内存超出 maxmemory,所有的 key中,随机移除某个 key。(应该没人用吧)
  • volatile-lru:当内存超出 maxmemory,设置了过期时间 key的字典中,移除最少使用的 key。把 Redis 既当缓存,又做持久化的时候使用这种策略。
  • volatile-random:当内存超出 maxmemory,在设置了过期时间 key的字典中,随机移除某个key。
  • volatile-ttl:当内存超出 maxmemory,在设置了过期时间 key 的字典中,优先移除 ttl 小的,也就是移除马上就要过期的key。

redis 中的默认的过期策略是volatile-lru 。设置方式 可以通过命令直接设置 config set maxmemory-policy xxxx(eg:volatile-lru)

6.LRU 算法

实现 LRU 算法除了需要 key/value 字典外,还需要附加一个链表,链表中的元素按照一定的顺序进行排列。当空间满的时候,会踢掉链表尾部的元素。当字典的某个元素被访问时,它在链表中的位置会被移动到表头。所以链表的元素排列顺序就是元素最近被访问的时间顺序。

这里基于linkhashmap实现一个lru算法,可设置最大容量,淘汰最老的数据

代码语言:javascript
复制
class LRUCache<K, V> extends LinkedHashMap<K, V> {
    private final int CACHE_SIZE;

    public LRUCache(int size) {
        //true代表顺序存放,最新的放头部,最老的放尾部
        super((int) Math.ceil(size / 0.75) + 1, 0.75f, true);
        CACHE_SIZE = size;
    }

    /**
     * 定义移除最老的数据的规则
     *
     * @author zyh
     * @date 2021/8/4
     **/
    @Override
    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
        return size() > CACHE_SIZE;
    }


}
```t
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/9/5 下午,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、设置过期时间
  • 2、两种常用的过期策略
    • 注意:
      • 4、RDB对过期key的处理
      • 5、AOF对过期key的处理
      • 5. redis内存淘汰机制
      • 6.LRU 算法
  • 3、Redis采用的过期策略
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档