[TOC]
## 缓存的常见过期策略有哪些?
### 常见的删除策略有3种
#### 1. 定时删除
在设置键的过期时间的同时,创建一个定时器,让定时器在键的过期时间来临时,立即执行对键的删除操作。
定时删除策略通过使用定时器,定时删除策略可以保证过期键尽可能快地被删除,并释放过期键占用的内存。
因此,定时删除策略的优缺点如下所示:
1. 优点:对内存非常友好
2. 缺点:对CPU时间非常不友好
举个例子,如果有大量的命令请求等待服务器处理,并且服务器当前不缺少内存,如果服务器将大量的CPU时间用来删除过期键,那么服务器的响应时间和吞吐量就会受到影响。
也就是说,如果服务器创建大量的定时器,服务器处理命令请求的性能就会降低,
因此Redis目前并没有使用定时删除策略。
#### 2. 惰性删除
放任过期键不管,每次从键空间中获取键时,检查该键是否过期,如果过期,就删除该键,如果没有过期,就返回该键。
惰性删除策略只会在获取键时才对键进行过期检查,不会在删除其它无关的过期键花费过多的CPU时间。
因此,惰性删除策略的优缺点如下所示:
1. 优点:对CPU时间非常友好
2. 缺点:对内存非常不友好
举个例子,如果数据库有很多的过期键,而这些过期键又恰好一直没有被访问到,那这些过期键就会一直占用着宝贵的内存资源,造成资源浪费。
#### 3. 定期删除
每隔一段时间,程序对数据库进行一次检查,删除里面的过期键,至于要删除哪些数据库的哪些过期键,则由算法决定。
定期删除策略是定时删除策略和惰性删除策略的一种整合折中方案。
定期删除策略每隔一段时间执行一次删除过期键操作,并通过限制删除操作执行的时长和频率来减少删除操作对CPU时间的影响,同时,通过定期删除过期键,也有效地减少了因为过期键而带来的内存浪费。
其中定时删除和定期删除为主动删除策略,惰性删除为被动删除策略。
## redis中使用的过期删除策略是什么?
两种策略,定期删除和惰性删除。
定期删除是定时扫描过期时间的 key的字典删除到期的 key。惰性删除是在客户端访问这个key的时候,redis对key的过期时间进行检查,如果过期了就立即删除,不会给你返回任何东西。
定期删除是集中处理,惰性删除是零散处理。
### **定期删除**
redis 会将每个设置了过期时间的 key 放入到一个独立的字典中,以后会定期遍历这个字典来删除到期的 key。
Redis 默认会每秒进行十次过期扫描(100ms一次),过期扫描不会遍历过期字典中所有的 key,而是采用了一种简单的贪心策略。
1.从过期字典中随机 20 个 key;
2.删除这 20 个 key 中已经过期的 key;
3.如果过期的 key 比率超过 1/4,那就重复步骤 1;
redis默认是每隔 100ms就随机抽取一些设置了过期时间的key,检查其是否过期,如果过期就删除。注意这里是随机抽取的。为什么要随机呢?你想一想假如 redis 存了几十万个 key ,每隔100ms就遍历所有的设置过期时间的 key 的话,就会给 CPU 带来很大的负载。
### **惰性删除**
所谓惰性策略就是在客户端访问这个key的时候,redis对key的过期时间进行检查,如果过期了就立即删除,不会给你返回任何东西。
定期删除可能会导致很多过期key到了时间并没有被删除掉。所以就有了惰性删除。假如你的过期 key,靠定期删除没有被删除掉,还停留在内存里,除非你的系统去查一下那个 key,才会被redis给删除掉。这就是所谓的惰性删除,即当你主动去查过期的key时,如果发现key过期了,就立即进行删除,不返回任何东西.
## redis支持的内存淘汰策略有哪些?
1. **no-eviction**:禁止驱逐数据,也就是说当内存不足以容纳新写入数据时,新写入操作会报错。
2. **volatile-ttl**:从已设置过期时间的数据集(server.db\[i\].expires)中挑选将要过期的数据淘汰;
3. **volatile-random**:从已设置过期时间的数据集(server.db\[i\].expires)中任意选择数据淘汰;
4. **allkeys-lru**:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 key;
5. **allkeys-random**:从数据集(server.db\[i\].dict)中任意选择数据淘汰;
6. **volatile-lru**:从已设置过期时间的数据集(server.db\[i\].expires)中挑选最近最少使用的数据淘汰;
4.0 版本后增加以下两种:
7. **volatile-lfu**:从已设置过期时间的数据集(server.db\[i\].expires)中挑选最不经常使用的数据淘汰;
8. **allkeys-lfu**:当内存不足以容纳新写入数据时,在键空间中,移除最不经常使用的 key。
> 注意:系统默认**no-eviction**。
> 当使用volatile-lru、volatile-random、volatile-ttl这三种策略时,如果没有key可以被淘汰,则和noeviction一样返回错误。
## 关于使用这6种策略,开发者还需要根据自身系统特征,正确选择或修改。
* 在Redis中,数据有一部分访问频率较高,其余部分访问频率较低,或者无法预测数据的使用频率时,设置allkeys-lru是比较合适的。
* 如果所有数据访问概率大致相等时,可以选择allkeys-random。
* 如果研发者需要通过设置不同的ttl来判断数据过期的先后顺序,此时可以选择volatile-ttl策略。
* 如果希望一些数据能长期被保存,而一些数据可以被淘汰掉时,选择volatile-lru或volatile-random都是比较不错的。
* 由于设置expire会消耗额外的内存,如果计划避免Redis内存在此项上的浪费,可以选用allkeys-lru 策略,这样就可以不再设置过期时间,高效利用内存了。
## LRU和LFU的区别
LRU是最近最少使用页面置换算法(Least Recently Used),也就是首先淘汰最长时间未被使用的页面!
LFU是最近最不常用页面置换算法(Least Frequently Used),也就是淘汰一定时期内被访问次数最少的页!
比如,第二种方法的时期T为10分钟,如果每分钟进行一次调页,主存块为3,若所需页面走向为2 1 2 1 2 3 4
注意,当调页面4时会发生缺页中断
若按LRU算法,应换页面1(1页面最久未被使用) 但按LFU算法应换页面3(十分钟内,页面3只使用了一次)
可见LRU关键是看页面最后一次被使用到发生调度的时间长短,
而LFU关键是看一定时间段内页面被使用的频率!
## 什么是LRU(高频问题)?
**介绍**
LRU(Least Recently Used),即最近最少使用,是一种缓存置换算法。
**背景**
在使用内存作为缓存的时候,缓存的大小一般是固定的。当缓存被占满,这个时候继续往缓存里面添加数据,就需要淘汰一部分老的数据,释放内存空间用来存储新的数据。这个时候就可以使用LRU算法了。
**核心思想**
如果一个数据在最近一段时间没有被用到,那么将来被使用到的可能性也很小,所以就可以被淘汰掉。
**标准LRU实现方式**
![](https://img.kancloud.cn/bc/2d/bc2dfcfc769158908c48335b624a02c3_718x960.png)
## redis是如何判断数据是否过期的呢?
Redis 通过一个叫做过期字典(可以看作是 hash 表)来保存数据过期的时间。过期字典的键指向 Redis 数据库中的某个 key(键),过期字典的值是一个 long long 类型的整数,这个整数保存了 key 所指向的数据库键的过期时间(毫秒精度的 UNIX 时间戳)。
## redis的内存淘汰策略是什么?
> 首先,需要知道,内存淘汰策略和过期键删除,是两码事儿。
因为不管是定期采样删除还是惰性删除都不是一种完全精准的删除,就还是会存在key没有被删除掉的场景,可以理解为:**内存淘汰策略是过期键删除策略的补充**。
## 怎么解释过期键删除策略和内存淘汰机制之间的关系?
* 过期键删除策略强调的是对过期健的操作,如果有键过期了,而内存还足够,不会使用内存淘汰机制,这时也会使用过期键删除策略删除过期键。
* 内存淘汰机制强调的是对内存的操作,如果内存不够了,即使有的键没有过期,也要删除一部分,同时也针对没有设置过期时间的键。
- 消息队列
- 为什么要用消息队列
- 各种消息队列产品的对比
- 消息队列的优缺点
- 如何保证消息队列的高可用
- 如何保证消息不丢失
- 如何保证消息不会重复消费?如何保证消息的幂等性?
- 如何保证消息消费的顺序性?
- 基于MQ的分布式事务实现
- Beanstalk
- PHP
- 函数
- 基础
- 基础函数题
- OOP思想及原则
- MVC生命周期
- PHP7.X新特性
- PHP8新特性
- PHP垃圾回收机制
- php-fpm相关
- 高级
- 设计模式
- 排序算法
- 正则
- OOP代码基础
- PHP运行原理
- zavl
- 网络协议new
- 一面
- TCP和UDP
- 常见状态码和代表的意义以及解决方式
- 网络分层和各层有啥协议
- TCP
- http
- 二面
- TCP2
- DNS
- Mysql
- 锁
- 索引
- 事务
- 高可用?高并发?集群?
- 其他
- 主从复制
- 主从复制数据延迟
- SQL的语⾔分类
- mysqlQuestions
- Redis
- redis-question
- redis为什么那么快
- redis的优缺点
- redis的数据类型和使用场景
- redis的数据持久化
- 过期策略和淘汰机制
- 缓存穿透、缓存击穿、缓存雪崩
- redis的事务
- redis的主从复制
- redis集群架构的理解
- redis的事件模型
- redis的数据类型、编码、数据结构
- Redis连接时的connect与pconnect的区别是什么?
- redis的分布式锁
- 缓存一致性问题
- redis变慢的原因
- 集群情况下,节点较少时数据分布不均匀怎么办?
- redis 和 memcached 的区别?
- 基本算法
- MysqlNew
- 索引new
- 事务new
- 锁new
- 日志new
- 主从复制new
- 树结构
- mysql其他问题
- 删除
- 主从配置
- 五种IO模型
- Kafka
- Nginx
- trait
- genergtor 生成器
- 如何实现手机扫码登录功能
- laravel框架的生命周期