自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

面試必問:Redis過期Key刪除和內(nèi)存淘汰策略

存儲 存儲軟件 Redis
眾所周知,Redis是一種內(nèi)存級kv數(shù)據(jù)庫,所有的操作都是在內(nèi)存里面進行,定期通過異步操作把數(shù)據(jù)庫數(shù)據(jù)flush到硬盤上進行保存。因此它是純內(nèi)存操作,Redis的性能非常出色,每秒可以處理超過10萬次讀寫操作。

 [[423221]]

本文轉(zhuǎn)載自微信公眾號「蟲爸說說」,作者蟲爸 。轉(zhuǎn)載本文請聯(lián)系蟲爸說說公眾號。

眾所周知,Redis是一種內(nèi)存級kv數(shù)據(jù)庫,所有的操作都是在內(nèi)存里面進行,定期通過異步操作把數(shù)據(jù)庫數(shù)據(jù)flush到硬盤上進行保存。因此它是純內(nèi)存操作,Redis的性能非常出色,每秒可以處理超過10萬次讀寫操作。雖然是內(nèi)存數(shù)據(jù)庫,但是其數(shù)據(jù)可以持久化,而且支持豐富的數(shù)據(jù)類型。

正因為是內(nèi)存級操作,那么其受限于物理內(nèi)存,所以Redis提供了過期key的刪除以及內(nèi)存淘汰策略,從而在一定程度上,能夠避免達到內(nèi)存上限。

在本文中,我們首先介紹下如何對某個key設(shè)置過期時間,然后再次介紹對于這些過期key都有哪些處理策略,隨后分析下在內(nèi)存達到上限時候,redis采取的策略。

設(shè)置過期

redis中設(shè)置過期時間有四種方式:

  • expire key seconds:設(shè)置key在N秒后過期;
  • pexpire key milliseconds:設(shè)置key在n毫秒后過期;
  • expire key timestamp:設(shè)置key在某個時間戳后過期(精確到秒)
  • pexpireat key millisecondstimestamp:設(shè)置key在一個時間戳后過期(精確到毫秒)

下面,我們來看看具體命令的用法。

expire: N秒后過期

  1. 127.0.0.1:6379> set key value 
  2. OK 
  3. 127.0.0.1:6379> expire key 100 
  4. (integer) 1 
  5. 127.0.0.1:6379> ttl key 
  6. (integer) 93 

其中命令TTL的全稱是 time to live,意思是key在N秒后過期。比如上面的結(jié)果93表示key在93s后過期。

pexpire: N毫秒后過期

  1. 127.0.0.1:6379> set key2 value2 
  2. OK 
  3. 127.0.0.1:6379> pexpire key2 100000 
  4. (integer) 1 
  5. 127.0.0.1:6379> pttl key2 
  6. (integer) 94524 

pexpire key2 100000 表示 key2 設(shè)置為在 100000 毫秒(100 秒)后過期。

expireat: 在某個時間戳過期(精確到秒)

  1. 127.0.0.1:6379> set key3 value3 
  2. OK 
  3. 127.0.0.1:6379> expireat key3 1630644399 
  4. (integer) 1 
  5. 127.0.0.1:6379> ttl key3 
  6. (integer) 67 

expired Key3 1630644399(精確到秒)之后過期。使用TTL查詢,可以發(fā)現(xiàn)Key3會在67s后過期。

在redis中,可以使用time命令查詢當前時間的時間戳(精確到秒),例如:

127.0.0.1:6379> time

1) "1630644526"

2) "239640"

pexpireat: 在某個時間戳過期(精確到毫秒)

  1. 127.0.0.1:6379> set key4 value4 
  2. OK 
  3. 127.0.0.1:6379> pexpireat key4 1630644499740 
  4. (integer) 1 
  5. 127.0.0.1:6379> pttl key4 
  6. (integer) 3522 

其中,pexpireat key4 1630644499740表示key4在時間戳1630644499740(精確到毫秒)之后過期。使用TTL查詢可以發(fā)現(xiàn)key4會在3522ms后過期。

value為string時候的過期設(shè)置

直接操作value為string的過期時間有幾種方法,如下所示:

  • set key value ex seconds:N秒后過期
  • set key value ex milliseconds:設(shè)置key在n毫秒后過期;
  • setex key seconds value:為指定的 key 設(shè)置值及其過期時間,如果 key 已經(jīng)存在, SETEX 命令將會替換舊的值。

設(shè)置kv對在N秒后過期

  1. 127.0.0.1:6379> set k v ex 100 
  2. OK 
  3. 127.0.0.1:6379> ttl k 
  4. (integer) 97 

設(shè)置kv對在N毫秒后過期

  1. 127.0.0.1:6379> set k2 v2 px 100000 
  2. OK 
  3. 127.0.0.1:6379> pttl k2 
  4. (integer) 92483 

使用setex來設(shè)置

  1. 127.0.0.1:6379> setex k3 100 v3 
  2. OK 
  3. 127.0.0.1:6379> ttl k3 
  4. (integer) 91 

取消過期

使用命令:persist key去除key值的過期時間,如下代碼所示:

  1. 127.0.0.1:6379> ttl k3 
  2. (integer) 97 
  3. 127.0.0.1:6379> persist k3 
  4. (integer) 1 
  5. 127.0.0.1:6379> ttl k3 
  6. (integer) -1 

可以看出,第一次使用TTL查詢K3,97s后就會過期。使用persist命令查詢K3的生命周期的結(jié)果是-1,表示K3永不過期。

過期策略

redis對過期key的刪除策略,有定時刪除、定期刪除和惰性刪除三種。

定時刪除

創(chuàng)建一個定時器,當key設(shè)置有過期時間,且過期時間到達時,由定時器任務(wù)執(zhí)行對key的刪除操作。

  • 優(yōu)點:節(jié)約內(nèi)存,到時就刪除,快速釋放掉不必要的內(nèi)存占用
  • 缺點:CPU壓力很大,無論CPU此時負載量多高,均占用CPU,會影響redis服務(wù)器響應(yīng)時間和指令吞吐量

定期刪除

redis默認是每隔100ms就隨機抽取一些設(shè)置了過期時間的key,檢查其是否過期,如果過期就刪除。注意這里是隨機抽取的。為什么要隨機呢?假如redis存了幾十萬個key,每隔100ms就遍歷所有的設(shè)置過期時間的key的話,就會給CPU帶來很大的負載。

  • 優(yōu)點:可以通過限制刪除操作執(zhí)行的時長和頻率來減少刪除操作對 CPU 的影響。另外定期刪除,也能有效釋放過期鍵占用的內(nèi)存。
  • 缺點:難以確定刪除操作執(zhí)行的時長和頻率。

如果執(zhí)行的太頻繁,定期刪除策略變得和定時刪除策略一樣,對CPU不友好,如果執(zhí)行的太少,那又和惰性刪除一樣了,過期鍵占用的內(nèi)存不會及時得到釋放。

另外最重要的是,在獲取某個鍵時,如果某個鍵的過期時間已經(jīng)到了,但是還沒執(zhí)行定期刪除,那么就會返回這個鍵的值,這是業(yè)務(wù)不能忍受的錯誤。

惰性刪除

定期刪除可能會導(dǎo)致很多過期key到了時間并沒有被刪除掉。所以就有了惰性刪除。假如你的過期key,靠定期刪除沒有被刪除掉,還停留在內(nèi)存里,除非你的系統(tǒng)去查一下那個key,才會被redis給刪除掉。這就是所謂的惰性刪除。expireIfNeeded(),檢查數(shù)據(jù)是否過期,執(zhí)行g(shù)et的時候調(diào)用。

  • 優(yōu)點:節(jié)約CPU性能,發(fā)現(xiàn)必須刪除的時候才刪除。
  • 缺點:內(nèi)存壓力很大,出現(xiàn)長期占用內(nèi)存的數(shù)據(jù)

換句話說,惰性刪除就是用存儲空間換取處理器性能

結(jié)合上述三種策略的優(yōu)缺點,redis采取了折中的刪除策略,即采用的是定期刪除+惰性刪除策略。

1、定時刪除,用一個定時器來負責(zé)監(jiān)視key,過期則自動刪除。雖然內(nèi)存及時釋放,但是十分消耗CPU資源。在大并發(fā)請求下,CPU要將時間應(yīng)用在處理請求,而不是刪除key,因此沒有采用這一策略

定期刪除+惰性刪除是如何工作的呢?

2、定期刪除,redis默認每個100ms檢查,是否有過期的key,有過期key則刪除。需要說明的是,redis不是每個100ms將所有的key檢查一次,而是隨機抽取進行檢查(如果每隔100ms,全部key進行檢查,redis豈不是卡死)。因此,如果只采用定期刪除策略,會導(dǎo)致很多key到時間沒有刪除。

3、惰性刪除,也就是說在你獲取某個key的時候,redis會檢查一下,這個key如果設(shè)置了過期時間那么是否過期了?如果過期了此時就會刪除。

但是這種方案,仍然存在缺點: 如果定期刪除沒刪除key。然后你也沒及時去請求key,也就是說惰性刪除也沒生效。這樣,redis的內(nèi)存會越來越高。那么就應(yīng)該采用內(nèi)存淘汰機制。

內(nèi)存淘汰策略

maxmemory 用于指定 Redis 能使用的最大內(nèi)存。既可以在 redis.conf 文件中設(shè)置, 也可以在運行過程中通過 CONFIG SET 命令動態(tài)修改。

例如, 要設(shè)置 100MB 的內(nèi)存限制, 可以在 redis.conf 文件中這樣配置:

  1. maxmemory 100mb 

上述命令設(shè)置了redis內(nèi)存上限,當內(nèi)存中的數(shù)據(jù)量達到其設(shè)置的上限的時候,就需要采取一定的淘汰策略,否則會影響redis的正常訪問。

為了更好的實現(xiàn)這一點,必須針對不同的應(yīng)用場景提供不同的策略,下面,我們將介紹下redis支持的幾種內(nèi)存淘汰策略。

Redis 提供了以下幾種策略供用戶選擇,其中noeviction 策略的默認策略為。

  • noeviction:當內(nèi)存不足以容納新寫入數(shù)據(jù)時,新寫入操作會報錯。
  • allkeys-lru:當內(nèi)存不足以容納新寫入數(shù)據(jù)時,在鍵空間中,移除最近最少使用的key。
  • allkeys-random:當內(nèi)存不足以容納新寫入數(shù)據(jù)時,在鍵空間中,隨機移除某個key。
  • volatile-lru:當內(nèi)存不足以容納新寫入數(shù)據(jù)時,在設(shè)置了過期時間的鍵空間中,移除最近最少使用的key。
  • volatile-random:當內(nèi)存不足以容納新寫入數(shù)據(jù)時,在設(shè)置了過期時間的鍵空間中,隨機移除某個key。
  • volatile-ttl:當內(nèi)存不足以容納新寫入數(shù)據(jù)時,在設(shè)置了過期時間的鍵空間中,有更早過期時間的key優(yōu)先移除。

需要注意的是,如果沒有設(shè)置 expire 的key, 不滿足先決條件,那么 volatile-lru, volatile-random 和 volatile-ttl 策略的行為, 和 noeviction(不刪除) 基本上一致。

Redis 使用的并不是完全LRU算法。自動驅(qū)逐的 key , 并不一定是最滿足LRU特征的那個. 而是通過近似LRU算法, 抽取少量的 key 樣本, 然后刪除其中訪問時間最古老的那個key。

驅(qū)逐算法, 從 Redis 3.0 開始得到了巨大的優(yōu)化, 使用 pool(池子) 來作為候選. 這大大提升了算法效率, 也更接近于真實的LRU算法。

在 Redis 的 LRU 算法中, 可以通過設(shè)置樣本(sample)的數(shù)量來調(diào)優(yōu)算法精度。

maxmemory-samples 5

以上就是Redis的六種淘汰策略。關(guān)于這六種策略的使用,使用者需要根據(jù)自身實際需要,選擇合理的淘汰策略。讀者可以根據(jù)自身需求,再結(jié)合下面的筆者經(jīng)驗,進行策略選擇。

  • 當部分數(shù)據(jù)訪問頻率較高而其余部分訪問頻率較低,或者數(shù)據(jù)的使用頻率無法預(yù)測時,設(shè)置allkeys-lru比較合適。
  • 如果所有數(shù)據(jù)訪問概率大致相等,可以選擇allkeys-random。
  • 如果開發(fā)者需要通過設(shè)置不同的ttls來確定數(shù)據(jù)過期的順序,此時可以選擇volatile-ttl策略。
  • 如果你想讓一些數(shù)據(jù)長期保存,而一些數(shù)據(jù)可以消除,最好選擇volatile-lru或volatile-random。
  • 由于設(shè)置expire會消耗額外的內(nèi)存,如果你打算避免Redis內(nèi)存浪費在這一項上,可以選擇allkeys-lru策略,這樣就可以不再設(shè)置過期時間,高效利用內(nèi)存。

經(jīng)驗之談

對于redis的操作,我們應(yīng)該慎之又慎。

  • 不要放垃圾數(shù)據(jù),及時清理無用數(shù)據(jù)。
  • key盡量都設(shè)置過期時間。對具有時效性的key設(shè)置過期時間,通過redis自身的過期key清理策略來降低過期key對于內(nèi)存的占用,同時也能夠減少業(yè)務(wù)的麻煩,不需要定期手動清理了。
  • 單Key不要過大,這種key在get的時候網(wǎng)絡(luò)傳輸延遲會比較大,需要分配的輸出緩沖區(qū)也比較大,在定期清理的時候也容易造成比較高的延遲. 最好能通過業(yè)務(wù)拆分,數(shù)據(jù)壓縮等方式避免這種過大的key的產(chǎn)生。
  • 不同業(yè)務(wù)如果公用一個業(yè)務(wù)的話,最好使用不同的邏輯db分開。這是因為Redis的過期Key清理策略和強制淘汰策略都會遍歷各個db。將key分布在不同的db有助于過期Key的及時清理。另外不同業(yè)務(wù)使用不同db也有助于問題排查和無用數(shù)據(jù)的及時下線。

 

責(zé)任編輯:武曉燕 來源: 蟲爸說說
相關(guān)推薦

2023-10-26 07:13:14

Redis內(nèi)存淘汰

2022-07-01 14:20:49

Redis策略函數(shù)

2024-08-19 09:13:02

2024-06-04 07:38:10

2019-11-22 09:36:00

Redis數(shù)據(jù)存儲

2024-09-26 06:30:36

2020-07-17 21:15:08

Redis內(nèi)存數(shù)據(jù)庫

2024-10-08 10:13:17

2023-06-07 08:08:43

JVM內(nèi)存模型

2023-03-14 11:00:05

過期策略Redis

2020-02-18 14:25:51

Java線程池拒絕策略

2021-02-23 12:43:39

Redis面試題緩存

2023-10-16 23:57:35

Redis內(nèi)存

2024-12-25 10:24:31

2019-09-27 09:13:55

Redis內(nèi)存機制

2021-03-13 14:04:43

Redis內(nèi)存策略

2019-04-10 10:43:15

Redis內(nèi)存淘汰策略

2023-02-17 08:02:45

@Autowired@Resource

2023-02-01 07:15:16

2021-12-09 12:22:28

MyBatis流程面試
點贊
收藏

51CTO技術(shù)棧公眾號