欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

淺談Redis中LFU算法源碼解析

 更新時(shí)間:2025年04月10日 09:53:30   作者:百里自來卷  
Redis的LFU淘汰算法主要用于?maxmemory-policy?設(shè)置為allkeys-lfu或volatile-lfu時(shí),以最少使用頻率的鍵進(jìn)行淘汰,本文主要介紹了淺談Redis中LFU算法源碼解析,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

Redis 的 LFU(Least Frequently Used,最不經(jīng)常使用)淘汰算法主要用于 maxmemory-policy 設(shè)置為 allkeys-lfu 或 volatile-lfu 時(shí),以最少使用頻率的鍵進(jìn)行淘汰。其核心實(shí)現(xiàn)涉及到 訪問頻率計(jì)數(shù) 和 時(shí)間衰減機(jī)制,源碼主要集中在 src/server.c 和 src/evict.c 文件中。

1. LFU 計(jì)數(shù)存儲

Redis 采用 8-bit 的 LRU 字段 來存儲訪問頻率計(jì)數(shù),存儲在 robj 結(jié)構(gòu)體的 lru 字段中:

struct redisObject {
    unsigned type:4;
    unsigned encoding:4;
    unsigned lru:LRU_BITS; // 用于 LRU/LFU 計(jì)算
    int refcount;
    void *ptr;
};

其中 lru 變量的 8-bit 空間被拆分:

  • 前 6-bit(counter):用于存儲訪問計(jì)數(shù),最大值 63。
  • 后 2-bit(clock):用于時(shí)間衰減計(jì)算。

2. 訪問計(jì)數(shù)的計(jì)算

LFU 計(jì)數(shù)在每次訪問鍵時(shí)都會遞增,但遞增方式不是簡單 +1,而是使用 對數(shù)增長 方式,避免某些鍵因高訪問量而壟斷:

unsigned long LFUDecrAndReturn(robj *o) {
    unsigned long counter = LFUGetCounter(o);
    if (counter == 0) return 0;
    if (rand() % (counter + 1) == 0) counter--;
    LFUSetCounter(o, counter);
    return counter;
}

計(jì)數(shù)增長時(shí):

int LFUIncrAndReturn(robj *o) {
    unsigned long counter = LFUGetCounter(o);
    if (counter < 63) {
        if (rand() % (counter + 1) == 0) counter++;
    }
    LFUSetCounter(o, counter);
    return counter;
}

這意味著:

  • 初始時(shí)計(jì)數(shù)增長較快 (1 → 2 → 3…)
  • 計(jì)數(shù)越高,增長概率越低(符合 對數(shù)曲線)
  • 這樣可以防止某些高訪問量鍵長期存活。

3. LFU 訪問頻率的衰減

由于有些數(shù)據(jù)可能短期內(nèi)訪問頻繁,但長期不再被訪問,因此 Redis 采用了 時(shí)間衰減機(jī)制:

每 1 分鐘 遞減一次訪問計(jì)數(shù)。

使用 2-bit 記錄最近訪問的時(shí)間 lfu_clock,每隔 60s 觸發(fā) 衰減:

#define LFU_INIT_VAL 5 // 初始訪問計(jì)數(shù)
unsigned long LFUDecrAndReturn(robj *o) {
    unsigned long counter = LFUGetCounter(o);
    if (counter == 0) return 0;
    if (rand() % (counter + 1) == 0) counter--;
    LFUSetCounter(o, counter);
    return counter;
}

該方法會按照一定概率減少計(jì)數(shù),確保 近期訪問過的鍵不會輕易被淘汰,而 長時(shí)間未訪問的鍵會逐步淘汰。

4. 淘汰策略

當(dāng) maxmemory 超出時(shí),Redis 需要淘汰一部分?jǐn)?shù)據(jù),LFU 主要執(zhí)行:

遍歷數(shù)據(jù),找到訪問計(jì)數(shù)最小的鍵。

采用 volatile-lfu 或 allkeys-lfu 進(jìn)行數(shù)據(jù)刪除:

evictionPoolPopulate(dict *sample_dict) {
    // 從字典中隨機(jī)采樣 N 個(gè)鍵
    for (i = 0; i < EVPOOL_SIZE; i++) {
        lfu = LFUGetCounter(entry);
        if (lfu < min_lfu) {
            min_lfu = lfu;
            min_entry = entry;
        }
    }
    // 淘汰訪問次數(shù)最少的
    dictDelete(sample_dict, min_entry);
}

采用 近似隨機(jī)采樣,而不是遍歷所有鍵,提高效率。

5. 關(guān)鍵總結(jié)

  • 存儲方式:使用 robj.lru 變量的 8-bit 空間存儲訪問計(jì)數(shù)和時(shí)間信息。
  • 訪問計(jì)數(shù)增長:采用對數(shù)增長策略,防止單個(gè)鍵因訪問量過大而占用內(nèi)存。
  • 時(shí)間衰減:每分鐘對訪問頻率計(jì)數(shù)進(jìn)行衰減,確保長期未訪問的鍵被淘汰。
  • 淘汰策略:采樣多個(gè)鍵,找到訪問計(jì)數(shù)最少的鍵進(jìn)行刪除。

Redis 的 LFU 機(jī)制相比 LRU 更適用于熱點(diǎn)數(shù)據(jù)訪問場景,避免了某些短期流行的鍵占用大量緩存,同時(shí)也能讓真正的 高頻訪問數(shù)據(jù) 存活更久。

到此這篇關(guān)于淺談Redis中LFU算法源碼解析的文章就介紹到這了,更多相關(guān)Redis LFU算法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot 集成Redis 過程

    SpringBoot 集成Redis 過程

    redis是一個(gè)開源的、使用C語言編寫的、支持網(wǎng)絡(luò)交互的、可基于內(nèi)存也可持久化的Key-Value數(shù)據(jù)庫。本文給大家介紹SpringBoot 集成Redis 過程,感興趣的朋友一起看看吧
    2021-06-06
  • 手把手教你使用redis實(shí)現(xiàn)排行榜功能

    手把手教你使用redis實(shí)現(xiàn)排行榜功能

    使用Redis中有序集合的特性來實(shí)現(xiàn)排行榜是又好又快的選擇,一般排行榜都是有實(shí)效性的,比如“用戶積分榜”,下面這篇文章主要給大家介紹了關(guān)于使用redis實(shí)現(xiàn)排行榜功能的相關(guān)資料,需要的朋友可以參考下
    2023-04-04
  • 淺談redis在項(xiàng)目中的應(yīng)用

    淺談redis在項(xiàng)目中的應(yīng)用

    下面小編就為大家?guī)硪黄獪\談redis在項(xiàng)目中的應(yīng)用。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-12-12
  • Redis中不同持久化方式的差異對比

    Redis中不同持久化方式的差異對比

    大家應(yīng)該都知道,Redis持久化方式主要有兩種:RDB(Redis DataBase)和AOF(Append-only file),但是他們各自存儲了什么內(nèi)容?有什么差異呢?今天我來給大家做個(gè)小試驗(yàn),需要的朋友可以參考下
    2024-03-03
  • Redis緩存空間優(yōu)化實(shí)踐詳解

    Redis緩存空間優(yōu)化實(shí)踐詳解

    緩存Redis,是我們最常用的服務(wù),其適用場景廣泛,被大量應(yīng)用到各業(yè)務(wù)場景中。也正因如此,緩存成為了重要的硬件成本來源,我們有必要從空間上做一些優(yōu)化,降低成本的同時(shí)也會提高性能,本文通過代碼示例介紹了redis如何優(yōu)化緩存空間,需要的朋友可以參考一下
    2023-04-04
  • Redis中的3種特殊數(shù)據(jù)結(jié)構(gòu)詳解

    Redis中的3種特殊數(shù)據(jù)結(jié)構(gòu)詳解

    在本文中,我們對三種特殊的數(shù)據(jù)類型進(jìn)行了介紹,它們分別是geospatial(地理空間數(shù)據(jù)類型)、HyperLogLogs和Bitmaps(位圖),這些數(shù)據(jù)類型在不同的領(lǐng)域和應(yīng)用中發(fā)揮著重要作用,并且具有各自獨(dú)特的特性和用途,對Redis特殊數(shù)據(jù)結(jié)構(gòu)相關(guān)知識感興趣的朋友一起看看吧
    2024-02-02
  • Redis 使用跳表實(shí)現(xiàn)有序集合的方法

    Redis 使用跳表實(shí)現(xiàn)有序集合的方法

    Redis有序集合底層為什么使用跳表而非其他數(shù)據(jù)結(jié)構(gòu)如平衡樹、紅黑樹或B+樹的原因在于其特殊的設(shè)計(jì)和應(yīng)用場景,跳表提供了與平衡樹類似的效率,同時(shí)實(shí)現(xiàn)更簡單,調(diào)試和修改也更加容易,感興趣的朋友一起看看吧
    2024-09-09
  • redis的list數(shù)據(jù)類型相關(guān)命令介紹及使用

    redis的list數(shù)據(jù)類型相關(guān)命令介紹及使用

    本文主要介紹了redis的list數(shù)據(jù)類型相關(guān)命令介紹及使用,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • odoo中使用redis實(shí)現(xiàn)緩存的步驟

    odoo中使用redis實(shí)現(xiàn)緩存的步驟

    這篇文章主要介紹了odoo中使用redis實(shí)現(xiàn)緩存的步驟,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-04-04
  • Redis緩存降級的四種策略

    Redis緩存降級的四種策略

    在高并發(fā)系統(tǒng)架構(gòu)中,Redis作為核心緩存組件扮演著至關(guān)重要的角色,它不僅能夠顯著提升系統(tǒng)響應(yīng)速度,還能有效減輕數(shù)據(jù)庫壓力,然而,當(dāng)Redis服務(wù)出現(xiàn)故障、性能下降或連接超時(shí)時(shí),如果沒有適當(dāng)?shù)慕导墮C(jī)制,可能導(dǎo)致系統(tǒng)雪崩,所以本文給大家介紹了Redis緩存降級的四種策略
    2025-04-04

最新評論