共計 2793 個字符,預計需要花費 7 分鐘才能閱讀完成。
丸趣 TV 小編給大家分享一下 Redis 數據刪除方式有哪些,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
同步和異步刪除 1.DEL 和 UNLINK
Redis 服務自身對 Key 的刪除,可以分為「同步刪除」和「異步刪除」。使用 DEL 命令會觸發「同步刪除」,如果 Key 是一個有很多元素的復雜類型,這個過程可能會堵塞一下 Redis 服務自身,從而影響用戶的訪問。如果使用 UNLINK 命令,Redis 服務會先計算刪除 Key 的成本,從而更智能地做出「同步刪除」或「異步刪除」的選擇。注意,只有 4.0 版本后,才有 UNLINK 命令。
2. 成本計算
那么,成本是如何計算的呢?對于 list,hash,set,zset 的對象類型,如果長度大于 64(由宏 LAZYFREE_THRESHOLD 定義),才會采用異步刪除的手段,從當前 db 先釋放該 key,再由另外一個線程做異步刪除。對于長度不大于 64 的復雜類型,異步刪除比同步刪除還多了一些函數調用與多線程同步的代價,所以同步刪除更好。對于 string 對象,底層的數據結構 sds 是一份連續的內存,內存分配器回收這塊內存的復雜度是 O(1),所以采用同步刪除也不會堵塞服務。
總的來說,我們作為用戶,都能用 UNLINK 替代 DEL。
Key 的驅逐 1. 定義
Redis 處理命令前根據內存容量是否觸達上限而進行的 Key 驅逐。
2. 驅逐策略
Redis 通過參數 maxmemory 來選擇不同的驅逐策略:
volatile-random 從已設置過期時間的數據集(server.db[i].expires)中任意選擇數據驅逐;volatile-lru 從數據集(server.db[i].dict)中挑選最近最少使用的數據驅逐(2.8 默認);
volatile-ttl 從已設置過期時間的數據集 (server.db[i].expires) 中尋找最近即將過期 (ttl 最小) 的 key 來驅逐;
allkeys-random 從數據集(server.db[i].dict)中任意選擇數據驅逐;
allkeys-lru 從數據集(server.db[i].dict)中挑選最近最少使用的數據驅逐;
noeviction 禁止驅逐數據,永遠不驅逐,僅對寫操作返回一個錯誤(4.0 默認);
在 4.0 版本后,還增加了以下兩種驅逐策略。
volatile-lfu 在過期集合中使用 LFU 鏈來驅逐數據;
allkeys-lfu 從數據集(server.db[i].dict)使用 LFU 算法來驅逐數據;
3. 簡述
Redis 在處理命令前,會看看容量是否觸達上限。
如果驅逐策略為 noeviction,則不會驅逐 Key,而是返回寫失敗。4.0 后,在返回寫入失敗前,還會先檢測 lazyfree 線程是否還有待刪除的 Key,沒有才會給用戶返回寫入失敗。
對于其他策略,都會根據相應定義,進行 Key 的驅逐,這里不再詳述。
在 4.0 或以上的版本,Key 的驅逐會基于參數 lazyfree_lazy_eviction,來決定采用 unlink 還是 del。在 2.8 版本,則只會用 del。lazyfree_lazy_eviction 參數在 Qcloud 4.0 上是 no。
這里試問,主從節點都會進行「驅逐」么?
答案是都會的,各自會因應自身的驅逐策略進行驅逐,并且 Master 節點驅逐的刪除命令還會傳播到 Slave 節點。
Key 的訪問淘汰 1. 定義
訪問一個已過期的 Key 會觸發對其的刪除。
2. 簡述
與 Key 的驅逐一樣,Key 的訪問淘汰同樣是基于訪問事件來觸發的。
主從角色的節點在處理訪問淘汰上的邏輯是不同的。
對于 Slave 節點,訪問到了已過期的 Key,Slave 節點會返回該 Key 不存在,但不會主動刪除該 Key。刪除的動作,還是會從 Master 上同步過來。
對于 Master 節點,在 4.0 或以上的版本,會根據參數 lazyfree-lazy-expire,來決定用 DEL 還是 UNLINK。對于 2.8 版本,則只能用 DEL 了。這些刪除的動作,都會同步到 Slave 與 AOF 文件中。
在 Qcloud 4.0 以上的版本,默認是開啟異步刪除的,即 lazyfree-lazy-expire=yes
Key 的定時淘汰 1. 定義
Redis 自身的定時調度把已過期 Key 刪除。
2. 簡述
多久會執行一次定時調度呢?
redis 服務的參數 hz 能控制定時淘汰的頻率,hz 默認是 10,即每秒能調度 100 次。
剛才說「訪問淘汰」的邏輯只會在 Master 角色上發生,那「訪問淘汰」也是嗎?
一般來說,Slave 節點不會進行定時淘汰,它只會等待從 Master 節點同步過來的刪除命令,這樣就保持了主從之間的一致性。然而,有些時候,用戶會把 Slave 節點設置成可寫,那么 Slave 上寫的帶有過期時間的 Key,因為 Master 是不知道的,就一直不會淘汰掉。所以在版本 4.0 以后,Redis 增加了單獨的邏輯,在定時淘汰中刪除這些在 slave 節點上寫入的過期 Key。
對于 Master 節點,根據宏 ACTIVE_EXPIRE_CYCLE_SLOW,能選擇兩種淘汰模式,分別是“FAST 淘汰”和“SLOW 淘汰”,前者每次淘汰只能花 1 毫秒,不能花更多了,后者是 Qcloud 默認的選項,這樣能在每次調度中淘汰更多的 Key,但會花更多的 CPU 時間在淘汰上,降低了處理的訪問吞吐量。下面我們針對“SLOW 淘汰”展開描述。
SLOW 淘汰模式,以 hz=10 為例,每次調度的總時間是 100ms,這里調度不會 25% 的 cpu 時間,即 25ms。
每淘汰多少個 key,就檢測一次是否超 25ms 呢?
如果每淘汰 1 個 Key 就檢測一次,無疑代價太大。從源碼上看,定時淘汰會嘗試遍歷每個 db,遍歷完了或者時間到了就退出循環。第一層循環是遍歷各個 db,第二層循環是遍歷 db 里面的一批批 key,一批 key 是 20 個,如果第三層循環結束后有大于 5 個 key 是成功淘汰的(說明這個 db 很多淘汰 key),那么二層就繼續循環,如果小于等于 5 個 key,說明這個 db 沒有很多 key 需要淘汰,則退出二層循環,第三層循環是一批 key 里面逐個 key 進行淘汰。即最多 320 個 key 進行判斷后,就會看看是否已經超過 cpu 占用時間。
在 4.0 或以上的版本,會根據參數 lazyfree-lazy-expire(默認 no)來做 DEL 還是 UNLINK。在 Qcloud 的 4.0 以上版本,這里會特意配置成 yes,以便盡量采用 UNLINK 操作。2.8 版本不支持 lazyfree-lazy-expire,就只能選擇 DEL 命令。
這里的定時淘汰,也會以命令的形式,傳播到 Slave 節點與記錄到 AOF 文件中。
以上是“Redis 數據刪除方式有哪些”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注丸趣 TV 行業資訊頻道!