[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實現方式**

## 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框架的生命周期