熟悉 Redis 嗎,那 Redis 的過期鍵刪除策略是什么?
共 7731字,需瀏覽 16分鐘
·
2024-06-17 14:25
來源:blog.csdn.net/hdgaadd/article/details/138577716
?? 歡迎加入小哈的星球 ,你將獲得: 專屬的項目實戰(zhàn) / Java 學習路線 / 一對一提問 / 學習打卡 / 每月贈書
新項目:仿小紅書(微服務架構)正在更新中... 。全棧前后端分離博客項目 2.0 版本完結啦, 演示鏈接:http://116.62.199.48/ 。全程手摸手,后端 + 前端全棧開發(fā),從 0 到 1 講解每個功能點開發(fā)步驟,1v1 答疑,直到項目上線。目前已更新了287小節(jié),累計45w+字,講解圖:2008張,還在持續(xù)爆肝中.. 后續(xù)還會上新更多項目,目標是將Java領域典型的項目都整一波,如秒殺系統(tǒng), 在線商城, IM即時通訊,Spring Cloud Alibaba 等等,戳我加入學習,已有1600+小伙伴加入(早鳥價超低)
-
1.Redis數(shù)據(jù)庫 -
2.內存回收策略
對于Redis,我們業(yè)務開發(fā)一般都只關心Redis鍵值對的查詢、修改操作,可能因為懶或者只想能用就行,呵呵。很少關心鍵值對存儲在什么地方、鍵值對過期了會怎么樣、Redis有沒什么策略處理過期的鍵、Redis處理過期鍵又有什么作用?
但這些問題卻是Java程序員在Redis上進階的必備知識,不要埋怨Java要學習的系統(tǒng)知識為什么這么多,因為這些確確實實是程序員進階所必須掌握的。我們往下看看~
1. Redis數(shù)據(jù)庫
1.1 Redis數(shù)據(jù)庫的理解
面試官:Redis的數(shù)據(jù)庫知道吧?
我們可以把Redis的數(shù)據(jù)庫和MySQL的數(shù)據(jù)庫理解成同一個東西,不同數(shù)據(jù)庫之間都是相互隔離的,在一個數(shù)據(jù)庫中定義的鍵對其他數(shù)據(jù)庫不可見。例如我們在Redis的數(shù)據(jù)庫1設置鍵值對,在數(shù)據(jù)庫1可以查詢出來,而在數(shù)據(jù)庫2中是查詢不出來的。
# 示例命令
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> set name JavaGetOffer
OK
127.0.0.1:6379[1]> select 2
OK
127.0.0.1:6379[2]> get name
(nil)
127.0.0.1:6379[2]> select 1
OK
127.0.0.1:6379[1]> get name
"JavaGetOffer"
Redis默認會創(chuàng)建16個數(shù)據(jù)庫,在業(yè)務上我們可以把不同業(yè)務所需鍵值對存儲在不同Redis數(shù)據(jù)庫,來達到根據(jù)業(yè)務劃分不同數(shù)據(jù)庫存儲的作用。
# 查詢一共有幾個數(shù)據(jù)庫
127.0.0.1:6379> config get databases
1) "databases"
2) "16"
另外Redis數(shù)據(jù)庫主要由這兩部分組成:dict字典即鍵空間、expires字典即過期字典,我們下文會講到。
1.2 數(shù)據(jù)庫的鍵空間
面試官:那數(shù)據(jù)庫的鍵空間呢?
鍵空間顧名思義是存儲鍵的容器,在Redis上字典存儲了數(shù)據(jù)庫中所有的鍵值對,這個字典也就是鍵空間。
大家記住不要把字典和Redis提供的哈希對象弄混淆了,前者是Redis的底層數(shù)據(jù)結構支持,而后者是Redis提供給外部使用的。
鍵空間的概念圖如下,dict字典存儲了所有鍵,每個鍵的指針指向值的引用地址。
Redis對鍵值對的添加、刪除、更新、查詢操作都是基于鍵空間的基礎上,先從dict字典查詢出鍵,再根據(jù)鍵找到對應值進行操作。
1.3 鍵過期時間
面試官:一個鍵要怎么設置過期時間?
可以先設置鍵值對,后使用EXPIRE命令來設置鍵的過期時間,過期時間的單位是秒。
127.0.0.1:6379> set name0 JavaOffer訓練營
OK
127.0.0.1:6379> expire name0 66
(integer) 1
127.0.0.1:6379> ttl name0
(integer) 66
127.0.0.1:6379> get name0
"JavaOffer訓練營"
另外也可以使用SETEX命令一步到位,同時設置值和過期時間。
127.0.0.1:6379> setex name 66 JavaGetOffer
OK
127.0.0.1:6379> ttl name
(integer) 66
127.0.0.1:6379> get name
"JavaGetOffer"
大家回答面試官時補充企業(yè)實戰(zhàn)的具體細節(jié)是可以加分的,例如對鍵值對設置過期時間,可以使用Jedis客戶端的setex方法。
public String setex(String key, int seconds, String value) {
this.checkIsInMultiOrPipeline();
this.client.setex(key, seconds, value);
return this.client.getStatusCodeReply();
}
1.4 過期字典
面試官:那鍵的過期時間知道用什么存儲嗎?
既然所有鍵使用字典存儲起來,那鍵的過期時間也可以使用字典存儲起來,這個字典我們稱它為過期字典。
因為鍵空間已經存儲了所有的鍵值對,過期字典沒必要再存儲一次,所以過期字典的鍵地址指向的是鍵空間的指針。而過期字典的值是一個long long類型的整數(shù),代表了過期日期的UNIX時間戳。
2. 內存回收策略
2.1 過期鍵刪除策略
面試官:鍵的過期刪除策略是什么?
過期鍵刪除策略一共有三種:定時刪除策略、惰性刪除策略、定期刪除策略。其中定時刪除、定期刪除是主動刪除,而惰性刪除是被動刪除。
每一種刪除策略都有其優(yōu)缺點,也適應不同的業(yè)務場景。
一、定時刪除對內存友好,對CPU不友好。 定時刪除策略會為設置過期時間的鍵創(chuàng)建一個定時器,使用定時器可以定時刪除過期的鍵值對,釋放出內存;但在大量定時器執(zhí)行過程中會占用一部分CPU。如果在Redis的內存充沛但CPU非常緊張的業(yè)務場景下,此時定時器再執(zhí)行,無疑會影響Redis的響應時間和吞吐量。
二、惰性刪除對CPU友好,對內存不友好,可能會出現(xiàn)內存泄漏。 該策略會放任過期的鍵不管,直到每次獲取鍵,如果發(fā)現(xiàn)鍵過期了,才會釋放出鍵內存。如果在大量鍵沒被訪問的業(yè)務場景下,Redis內存會大量浪費在已過期的鍵上。
三、定期刪除策略。 每隔一段時間檢查數(shù)據(jù)庫中一部分的鍵,刪除其中的過期鍵,該策略可以設置刪除操作的執(zhí)行時長和頻率。它的缺點在于確認刪除操作的執(zhí)行時長和頻率比較麻煩。
三種過期鍵刪除策略各有優(yōu)缺點,Reids服務器實際上是采用了惰性刪除策略、定期刪除策略這兩種策略配合使用,讓服務器在避免CPU緊張和內存消耗過多之間取得平衡。
2.2 內存淘汰策略
面試官:Redis還有什么策略可以釋放內存?
為了節(jié)約內存,Reids除了會對過期鍵進行刪除外,還會在內存達到內存上限時進行內存回收,也就是Redis的內存淘汰策略。
內存上限可以通過config命令來動態(tài)配置。
127.0.0.1:6379> config set maxmemory 1GB
OK
127.0.0.1:6379> config get maxmemory
1) "maxmemory"
2) "1073741824"
而內存溢出控制策略一共有六種,我們可以通過配置maxmemory-policy參數(shù)來進行控制。
-
noeviction:默認策略不會刪除任何鍵值對,同時會拒絕所有寫命令。 -
volatile-lru:根據(jù)LRU最近最少使用算法刪除設置了過期時間的鍵,直到騰出足夠的空間。如果沒有可刪除的鍵對象,則會回退到noeviction策略。 -
allkeys-lru:和volatile-lru同樣的作用,不過針對的是所有鍵。 -
allkeys-random:隨機刪除所有鍵,直到騰出足夠的空間。 -
volatile-random:隨機刪除過期鍵,直到騰出足夠的空間。 -
volatile-ttl:刪除最近將要過期的鍵。看到后綴ttl我們就知道這個策略和過期時間相關。
以下是Redis配置文件提供的六種內存淘汰策略介紹,大家可以參考下。
# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory
# is reached. You can select among five behaviors:
#
# volatile-lru -> Evict using approximated LRU among the keys with an expire set.
# allkeys-lru -> Evict any key using approximated LRU.
# volatile-lfu -> Evict using approximated LFU among the keys with an expire set.
# allkeys-lfu -> Evict any key using approximated LFU.
# volatile-random -> Remove a random key among the ones with an expire set.
# allkeys-random -> Remove a random key, any key.
# volatile-ttl -> Remove the key with the nearest expire time (minor TTL)
# noeviction -> Don't evict anything, just return an error on write operations.
#
# LRU means Least Recently Used
# LFU means Least Frequently Used
#
# Both LRU, LFU and volatile-ttl are implemented using approximated
# randomized algorithms.
#
# Note: with any of the above policies, Redis will return an error on write
# operations, when there are no suitable keys for eviction.
#
# At the date of writing these commands are: set setnx setex append
# incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd
# sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby
# zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby
# getset mset msetnx exec sort
#
# The default is:
#
# maxmemory-policy noeviction
?? 歡迎加入小哈的星球 ,你將獲得: 專屬的項目實戰(zhàn) / Java 學習路線 / 一對一提問 / 學習打卡 / 每月贈書
新項目:仿小紅書(微服務架構)正在更新中... 。全棧前后端分離博客項目 2.0 版本完結啦, 演示鏈接:http://116.62.199.48/ 。全程手摸手,后端 + 前端全棧開發(fā),從 0 到 1 講解每個功能點開發(fā)步驟,1v1 答疑,直到項目上線。目前已更新了287小節(jié),累計45w+字,講解圖:2008張,還在持續(xù)爆肝中.. 后續(xù)還會上新更多項目,目標是將Java領域典型的項目都整一波,如秒殺系統(tǒng), 在線商城, IM即時通訊,Spring Cloud Alibaba 等等,戳我加入學習,已有1600+小伙伴加入(早鳥價超低)
1. 我的私密學習小圈子~
最近面試BAT,整理一份面試資料《Java面試BATJ通關手冊》,覆蓋了Java核心技術、JVM、Java并發(fā)、SSM、微服務、數(shù)據(jù)庫、數(shù)據(jù)結構等等。
獲取方式:點“在看”,關注公眾號并回復 Java 領取,更多內容陸續(xù)奉上。
PS:因公眾號平臺更改了推送規(guī)則,如果不想錯過內容,記得讀完點一下“在看”,加個“星標”,這樣每次新文章推送才會第一時間出現(xiàn)在你的訂閱列表里。
點“在看”支持小哈呀,謝謝啦
