1. 程式人生 > >Redis中的過期鍵刪除策略

Redis中的過期鍵刪除策略

我們知道在Redis資料庫中,我們可以為相應的鍵設定過期時間
那麼在相應鍵的過期時間到了,我們要通過什麼方法來回收相應的鍵呢?

對於上面的問題,我們有以下三種不同的刪除策略

定時刪除:在設定鍵過期時間的同時,建立一個定時器,讓定時器在過期時間來臨的時候,立即刪除相應的鍵。
惰性刪除:我們先不管當前鍵是否過期,在使用的時候檢查一下當前鍵是否已經過期,如果過期就立即刪除當前鍵。
定期刪除:系統每隔一定的時間對資料庫做一次檢查,刪除裡面的過期鍵。

注:以上的三種刪除策略裡面,第一和第三種被稱為主動刪除策略,第二種被稱為被動刪除策略。

定時刪除
定時刪除對於記憶體是最友好的,通過使用定時器,可以保證過期的鍵會盡可能快的被刪除,並釋放其佔用的記憶體。

但是在過期鍵比較多的情況下,刪除過期鍵可能會佔用佔用相當一部分的CPU(如果這個時候記憶體並不是很緊張但是有大量的命令在請求CPU處理),所以說這種策略是對CPU不友好的。

除此之外,建立定時器需要用到Redis伺服器中的時間事件,而當前時間事件的實現方式是無序連結串列,建立一個事件的時間複雜度為O(n) —— 並不能高效的處理大量時間時間。

因此,要讓伺服器建立大量的定時器從而時間定時刪除策略,當前來說還並不現實。(引用自《Redis設計與實現》)

惰性刪除
惰性刪除對於CPU是最友好的,其只在當前鍵的時候才會做其過期檢查,這可以保證刪除過期鍵的操作只會在非做不可得情況下才會進行,從而使CPU不會在刪除其他無關緊要的鍵上面浪費時間。

非常明顯,這種策略對於記憶體是不友好的。

同時還可能會造成記憶體洩漏——比如有的鍵可能永遠也不會再使用了,這樣子就永遠存在記憶體中不會被釋放。而Redis伺服器又是非常依賴記憶體的,所以這是一個非常不好的結果。

定期刪除
上面的兩種策咯都有明顯的缺點

定時刪除:可能會佔用大量的CPU時間,影響伺服器的響應時間和吞吐量
惰性刪除:可能會浪費大量的記憶體,導致記憶體洩漏

而定期操作是前面兩種策略的一個折中

通過每隔一定的時間刪除過期鍵,並通過限制刪除操作的時長和頻率來減少對CPU影響(相對定時刪除)
定期刪除不會導致有的鍵因為很長時間才會使用或者永不使用(但是已經過期)而帶來的記憶體浪費甚至記憶體洩漏問題

定期刪除策略需要考慮的問題有兩個:刪除操作執行的時長,刪除操作執行的頻率

所以說,如果採取定期刪除策略的話就需要根據當前專案的情況,合理的設定刪除操作的時長和頻率,從而使系統的效能達到最優。

那麼在Redis資料庫中使用的是哪種刪除策略呢?—— 惰性刪除和定期刪除

惰性刪除策略的實現
Redis的原始碼中是使用db.c/expireIfNeed()函式實現的

/**
 * 檢查 key 是否已經過期,如果是的話,將它從資料庫中刪除。
 *
 * 返回 0 表示鍵沒有過期時間,或者鍵未過期。
 *
 * 返回 1 表示鍵已經因為過期而被刪除了。
 */
int expireIfNeeded(redisDb *db, robj *key) {
    /* 取出鍵的過期時間 */
    mstime_t when = getExpire(db,key);
    mstime_t now;

    /* 如果沒有過期時間 */
    if (when < 0) return 0; 

    /* 伺服器loading的時候暫時先不工作 */
    if (server.loading) return 0;

    /* 獲取當前時間*/
    now = server.lua_caller ? server.lua_time_start : mstime();

    /* 如果當前的是從(Slave)機
     * 0 if we think the key should be still valid,
     * 1 if we think the key is expired at this time. 
     * */
    if (server.masterhost != NULL) return now > when;

    /* 如果未過期,返回 0 */
    if (now <= when) return 0;

    /* 刪除鍵 */
    server.stat_expiredkeys++;
    propagateExpire(db,key,server.lazyfree_lazy_expire);
    notifyKeyspaceEvent(NOTIFY_EXPIRED,
        "expired",key,db->id);

    return server.lazyfree_lazy_expire ? dbAsyncDelete(db,key) :
                                         dbSyncDelete(db,key);
}

命令呼叫expireIfNeeded()的過程如圖所示

Created with Raphaël 2.1.0開始 所有讀寫資料可的命令(GET,LRANGE,SADD等)所操作的鍵是否已經過期?刪除鍵執行實際的命令流程yesno

定期刪除策略的實現
過期鍵的定期刪除策略由expire.c/activeExpireCycle()函式實現,每當伺服器週期性操作server.c/serverCron函式執行時,activeExpireCycle()函式就會被呼叫,在短時間內,分多次便利伺服器中的資料庫,從資料庫的expires字典中隨機檢查一部分鍵的過期時間,並刪除其中的過期鍵。

相關推薦

Redis過期刪除策略

我們都知道資料庫鍵的過期時間都儲存在過期字典中,那麼如果一個鍵過期了,那麼什麼時候會被刪除呢? 以下三種不同的刪除策略: 定時刪除: 在設定鍵的過期時間的同時,建立一個定時器(timer),讓定時器在鍵的過期時間來臨時,立即執行刪除鍵。 惰性刪除:放任過期

Redis系列(五):Redis過期刪除策略

本篇部落格是Redis系列的第5篇,主要講解下Redis的過期鍵刪除策略。 本系列的前4篇可以點選以下連結檢視: Redis系列(一):Redis簡介及環境安裝 Redis系列(二):Redis的5種資料結構及其常用命令 Redis系列(三):Redis的持久化機制(RDB、AOF) Redis系列(四):R

Redis過期刪除策略

我們知道在Redis資料庫中,我們可以為相應的鍵設定過期時間 那麼在相應鍵的過期時間到了,我們要通過什麼方法來回收相應的鍵呢? 對於上面的問題,我們有以下三種不同的刪除策略 定時刪除:在設定鍵過期時間的同時,建立一個定時器,讓定時器在過期時間來臨的時

Redis物件型別與過期刪除策略

Redis物件型別: string(int、embstr、raw): 儲存字串值長度小於 32 位元組的時候,採用 embstr 編碼儲存,如果大於32     用raw編碼儲存,或者當字串修改時,無論是否大於32位元組,都將改用raw編碼儲存。

redis 過期刪除策略

redis 的過期鍵的過期時間都儲存在過期字典中,過期鍵的刪除策略有3種 定時刪除:在設定鍵的過期時間的同時,建立一個定時器,讓定時器在鍵的過期時間來臨時,立即刪除對鍵的刪除操作。 惰性刪除:放任鍵過期不管,但每次從鍵空間中獲取鍵時,都檢查取得的鍵是否過期,如果過期的話,就刪除該鍵。如果沒有過期,

一文了解:Redis過期刪除策略

Redis過期鍵刪除策略 Redis中所有的鍵都可以設定過期策略,就像是所有的鍵都可以上"生死簿",上了生死簿的鍵到時間後閻王就會叉掉這個鍵。同一時間大量的鍵過期,閻王就會忙不過來。同時因為Redis是單執行緒的,導致閻王的處理時間會變得很長,而且處理繁忙,Redis就會出現卡頓現象。 R

redis學習之四】Redis過期處理及淘汰策略

    在redis中可以通過如下命令設定鍵的生存時間或生命週期: EXPIRE KEY TTL 命令用於將key的生存時間設定為ttl秒 PEXPIRE KEY TTL 命令用於將key的生存時間設定為ttl毫秒 EXPIREAT KEY TIMESTAMP

Redis過期操作

1.過期設定 Redis 中設定過期時間主要通過以下四種方式: expire key seconds:設定 key 在 n 秒後過期; pexpire key milliseconds:設定 key 在 n 毫秒後過期; expireat key timestamp:設定 key 在某個時間戳(精確到秒)之

Redis的批量刪除資料庫的Key

./redis-cli keys "*" | xargs ./redis-cli del   批量刪除Key Redis 中有刪除單個 Key 的指令 DEL,但好像沒有批量刪除 Key 的指令,不過我們可以藉助 Linux 的 xargs 指令來完成這個動作 1

py-redis的批量刪除key方法

py-redis中有個delete介面,既可以刪除單個key,也可以批量刪除key,後者的正確用法網上很少,我在實踐中遇到該問題,特此記錄一下。 網上的資料,大多都是這樣的 r.delete('age') r.delete('sex', 'age') 正確的方法 keys

Redis的LRU淘汰策略分析

Redis作為快取使用時,一些場景下要考慮記憶體的空間消耗問題。Redis會刪除過期鍵以釋放空間,過期鍵的刪除策略有兩種: 惰性刪除:每次從鍵空間中獲取鍵時,都檢查取得的鍵是否過期,如果過期的話,就刪除該鍵;如果沒有過期,就返回該鍵。 定期刪除:每隔一段時間,程式就對資料庫進行一次檢查,刪除裡面的過期

Redis 的資料持久化策略(RDB)

Redis 是一個記憶體資料庫,所有的資料都直接儲存在記憶體中,那麼,一旦 Redis 程序異常退出,或伺服器本身異常宕機,我們儲存在 Redis 中的資料就憑空消失,再也找不到了。 Redis 作為一個優秀的資料中介軟體,必定是擁有自己的持久化資料備份機制的,redis 中主要有兩種持久化策略,用於將儲存在

Redis 的資料持久化策略(AOF)

上一篇文章,我們講的是 Redis 的一種基於記憶體快照的持久化儲存策略 RDB,本質上他就是讓 redis fork 出一個子程序遍歷我們所有資料庫中的字典,進行磁碟檔案的寫入。 但其實這種方式是有缺點的,先不說阻塞式 save 呼叫會阻塞整個 redis 服務,即便非同步式 bgsave 也是基於時間間隔

動手實現 LRU 演算法,以及 Caffeine 和 Redis 的快取淘汰策略

> 我是風箏,公眾號「古時的風箏」。 文章會收錄在 [JavaNewBee](https://github.com/huzhicheng/JavaNewBee) 中,更有 Java 後端知識圖譜,從小白到大牛要走的路都在裡面。 那天我在 LeetCode 上刷到一道 LRU 快取機制的問題,第 146 題

Redis刪除過期Key的三種策略

專案中有個介面要頻繁呼叫查詢資料庫中的資料,為了降低資料庫的壓力,所以把一部分記錄先快取在redis中,對redis中的資料設定了期限。今天無意間發現一個問題,使用dbsize查詢出來的數量,比實際快取量要高一部分。用 redis-cli keys '*'|wc -l 1 獲取到的資料和實際情

redis過期刪除策略

Redis過期鍵的刪除策略 對於過期鍵一般有三種刪除策略 定時刪除:在設定鍵的過期時間的同時,建立一個定時器(timer),讓定時器在鍵的過期時間來臨時,立即執行對鍵的刪除操作; 惰性刪除:放任鍵過期不管,但是每次從鍵空間中獲取鍵時,都檢查取得的鍵是否過期,如果過期的話,就刪除該

探索Redis設計與實現9:資料庫redisDb與過期刪除策略

一. 資料庫Redis的資料庫使用字典作為底層實現,資料庫的增、刪、查、改都是構建在字典的操作之上的。 redis伺服器將所有資料庫都儲存在伺服器狀態結構redisServer(redis.h/redisServer)的db陣列(應該是一個連結串列)裡:struct redisServer { //..

StringRedisTemplate常用操作 / Redis刪除過期Key的三種策略

stringRedisTemplate.opsForValue().set("test", "100",60*10,TimeUnit.SECONDS);//向redis裡存入資料和設定快取時間 stringRedisTemplate.boundValueOps("t

Redis 過期的設置、獲取和刪除過期時間

sans tle 整數 時間 lis class 情況下 title 結構 Redis 過期鍵的設置、獲取和刪除過期時間 轉自http://blog.51cto.com/littledevil/1813956 設置過期 默認情況下鍵是沒有生存時間的,也就是永不過期,除非

Redis過期命令

鍵過期命令EXPIRE key seconds 將鍵 key 的生存時間設定為指定的秒數。複雜度為O(1) PEXPIRE key milliseconds 將鍵 key 的生存時間