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

目录

一、过期策略

1.1、定时删除

1.1.1、过期

  • Redis 所有的数据结构都可以设置过期时间,时间一到,就会自动删除。但是会不会因为同一时间太多的key 过期,以至于忙不过来。同时因为Redis 是单线程的,删除的时间也会占用线程的处理时间,如果删除的大过于繁忙,会不会导致线上读写指令出现卡顿。

1.1.2、过期的 key 集合

  • redis 会将每个设置了过期时间的key 放入到一个独立的字典中 ,以后会定时遍历 这个字典 来删除到期的 key。除了定时遍历之外,它还会使用惰性策略来删除过期的 key,所谓惰性策略就是在客户端访问这个 key 的时候,redis 对 key 的过期时间进行检查,如果过期了就立即删除。定时删除是集中处理,惰性删除是零散处理。

1.1.3、定时扫描策略

  • Redis 默认会每秒进行十次过期扫描 ,过期扫描不会遍历过期字典中所有的 key,而是采用了一种简单的贪心策略。
    (1)、从过期字典中随机 20 个 key;
    (2)、删除这 20 个 key 中已经过期的 key;
    (3)、 如果过期的 key 比率超过 1/4,那就重复步骤(1);

1.1.4、 Redis 中所有的 key 在同一时间过期了,会出现怎样的结果

  • Redis 会持续扫描过期字典(循环多次),直到过期字典中过期的key 变得稀疏,才会停止(循环次数明显下降)。这就会导致线上读写请求出现明显的卡顿现象。导致这种卡顿的另外一种原因是内存管理器需要频繁回收内存页,这也会产生一定的 CPU 消耗
  • 所以业务开发人员一定要注意过期时间,如果有大批量的 key 过期,要给过期时间设置一个随机范围,而不能全部在同一时间过期。

1.1.5、从库的过期策略

  • 从库不会进行过期扫描 ,从库对过期的处理是被动的。主库在 key 到期时,会在 AOF 文件里增加一条 del 指令,同步到所有的从库,从库通过执行这条 del 指今来删除过期的 key
  • 因为指令同步是异步进行的,所以主库过期的key 的 del 指令没有及时同步到从库的话,会出现主从数据的不一致,主库没有的数据在从库里还存在,比如上-节的集群环境分布式锁的算法漏洞就是因为这个同步延迟产生的。

1.2、惰性删除

  • 所谓惰性策略就是在客户端访问这个kev的时候,redis对key的过期时间进行检查,如果过期了就立即删除,不会给你返回任何东西
  • 定期删除可能会导致很多过期kev到了时间并没有被删除。所以就有了惰性删除。假如你的过期 key,靠定期删除没有被删除掉,还停留在内存里,除非你的系统去查一下那个 key,才会被redis给删除掉。这就是所谓的惰性删除,即当你主动去查过期的key时,如果发现key过期了,就立即进行删除,不返回任何东西

1.3、定时删除和惰性删除的总结

  • 定期删除是集中处理,惰性删除是零散处理。

二、缓存淘汰算法

2.1、缓存淘汰算法概述

2.1.1、概述

  • 当 Redis 内存超出物理内存限制时,内存的数据会开始和磁盘产生频繁的交换(swap)。交换会让 Redis 的性能急剧下降,对于访问量比较频繁的 Redis 来说,这样龟速的存取效率基本上等于不可用。

2.1.2、maxmemory

  • 在生产环境中我们是不允许 Redis 出现交换行为的,为了限制最大使用内存,Redis 提供了配置参数maxmemory 来限制内存超出期望大小。
  • 当实际内存超出 maxmemory 时,Redis 提供了几种可选策略(maxmemory-policy) 来让用户自己决定该如何腾出新的空间以继续提供读写服务。

2.2、缓存淘汰算法机制

2.2.1、Noeviction

  • noeviction 不会继续服务写请求,(DEL 请求可以继续服务),读请求可以继续进行。这样可以保证不会丢失数据,但是会让线上的业务不能持续进行。这是默认的淘汰策略.

2.2.2、volatile-Iru

  • volatile-lru 尝试淘汰设置了过期时间的key,最少使用的 key 优先被淘汰。没有设置过期时间的 key 不会被淘汰,这样可以保证需要持久化的数据不会突然丢失。

2.2.3、volatile-ttl

  • voatie-ttl 跟上面一样,除了淘汰的策略不是 LRU,而是key 的剩余寿命ttl的值,ttl 越小越优先被淘汰

2.2.4、volatile-random

  • volatile-random 跟上面一样,不过淘汰的 key 是过期 key 集合中随机的 key。

2.2.5、allkeys-lru

  • allkeys-lru 区别于volatile-lru,这个策略要淘汰的 key 对象是全体的 key 集合,而不只是过期的 key 集合。这意味着没有设置过期时间的 key 也会被淘汰。

2.2.6、allkeys-random

  • allkeys-random跟上面一样,不过淘汰的策略是随机的 key。

2.3、缓存淘汰算法总结

  • volatile-xxx 策略只会针对带过期时间的key 进行淘汰。
  • allkeys-xxx 策略会对所有的 key 进行淘汰。
  • 如果你只是拿 Redis 做缓存,那应该使用 allkeys-xxx,客户端写缓存时不必携带过期时间。
  • 如果你还想同时使用 Redis 的持久化功能,那就使用 volatile-xxx 策略,这样可以保留没有设置过期时间的 key,它们是永久的 key 不会被LRU 算法淘汰。

2.4、LRU 算法概述

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

2.5、近似 LRU 算法概述

  • Redis 使用的是一种近似 LRU 算法,它跟 LRU 算法还不太一样。之所以不使用 LRU 算法,是因为需要消耗大量的额外的内存,需要对现有的数据结构进行较大的改造。
  • 近似LRU 算法则很简单,在现有数据结构的基础上使用随机采样法来淘汰元素,能达到和 LRU 算法非常近似的效果。Redis 为实现近似LRU 算法,它给每个 key 增加了一个额外的小字段,这个字段的长度是 24 个 bit,也就是最后一次被访问的时间戳。
  • 当 Redis 执行写操作时,发现内存超出maxmemory,就会执行一次 LRU 淘汰算法。这个算法也很简单,就是随机采样出 5可以配置maxmemory-samples) 个 key,然后淘汰掉最旧的 key,如果淘汰后内存还是超出maxmemory,那就继续随机采样淘汰,直到内存低于 maxmemory 为止。
相关推荐
我真的是大笨蛋8 小时前
Redis的String详解
java·数据库·spring boot·redis·spring·缓存
zhengzizhe10 小时前
Redssion出现attempt to unlock lock, not locked by current thread by node id
redis
兜兜风d'14 小时前
redis字符串命令
数据库·redis·缓存
西瓜er15 小时前
Docker 一键部署指南:GitLab、Nacos、Redis、MySQL 与 MinIO 全解析
redis·docker·gitlab
道可到16 小时前
别再瞎拼技术栈!Postgres 已经能干 Redis 的活了
redis·后端·postgresql
野犬寒鸦16 小时前
从零起步学习Redis || 第十二章:Redis Cluster集群如何解决Redis单机模式的性能瓶颈及高可用分布式部署方案详解
java·数据库·redis·后端·缓存
悟能不能悟1 天前
redis的红锁
数据库·redis·缓存
qq_5470261791 天前
SpringBoot+Redis实现电商秒杀方案
spring boot·redis·后端
野犬寒鸦1 天前
从零起步学习Redis || 第十一章:主从切换时的哨兵机制如何实现及项目实战
java·服务器·数据库·redis·后端·缓存
problc1 天前
PostgreSQL + Redis + Elasticsearch 实时同步方案实践:从触发器到高性能搜索
redis·elasticsearch·postgresql