欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

什么是Redis-LFU

這篇文章主要講解了“什么是redis-LFU”,文中的講解內(nèi)容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“什么是Redis-LFU”吧!

創(chuàng)新互聯(lián)建站主營江西網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營網(wǎng)站建設(shè)方案,重慶APP開發(fā),江西h5微信小程序開發(fā)搭建,江西網(wǎng)站營銷推廣歡迎江西等地區(qū)企業(yè)咨詢

LFU是redis中被使用的一個淘汰策略,當然redis實現(xiàn)的是非常的巧妙,它的全稱是Least  Frequently  Used,即用的次數(shù)少的被淘汰。它相比于LRU(大家可以自行了解,后續(xù)博文會對它進行補充)更精確通過讀redis相關(guān)源碼(version:6.2)發(fā)現(xiàn),每次操作db的時候都會調(diào)用 robj *lookupKey(redisDb *db, robj *key, int flags)函數(shù),這個函數(shù)是這樣實現(xiàn)的

robj *lookupKey(redisDb *db, robj *key, int flags) {
    dictEntry *de = dictFind(db->dict,key->ptr);
    if (de) {
        robj *val = dictGetVal(de);

        /* Update the access time for the ageing algorithm.
         * Don't do it if we have a saving child, as this will trigger
         * a copy on write madness. */
        if (!hasActiveChildProcess() && !(flags & LOOKUP_NOTOUCH)){
            if (server.maxmemory_policy & MAXMEMORY_FLAG_LFU) {
                updateLFU(val);
            } else {
                val->lru = LRU_CLOCK();
            }
        }
        return val;
    } else {
        return NULL;
    }
}

當在字典中發(fā)現(xiàn)存在這個key的時候&它沒有開啟一個子線程去做saving操作的時候&配了最大內(nèi)存策略&MAXMEMORY_FLAG_LFU 它都會updateLFU,讓我們看看updateLFU函數(shù)是怎么實現(xiàn)的吧,先上代碼:

void updateLFU(robj *val) {
    unsigned long counter = LFUDecrAndReturn(val);
    counter = LFULogIncr(counter);
    val->lru = (LFUGetTimeInMinutes()<<8) | counter;
}

先講下LFU的結(jié)構(gòu),這樣對理解代碼有一定的幫助。LFU像LRU一樣都用了24bit去表示,不同的是,LFU用前16bit表示時間,剩余的8bit表示被訪問次數(shù),即counter,而LRU用全部的24bit表示時間。表象是結(jié)構(gòu)的區(qū)別,其實是內(nèi)在算法實現(xiàn)上的區(qū)別。LRU僅根據(jù)時間去判斷這個key是否該刪除,而LFU是根據(jù)時間和訪問次數(shù)兩個因子去確定該key是否被刪,從概率上來判斷,LFU是更準確的。updateLFU中,最后會算出val的真正的lru,time<<8位是為了給counter留出8bit的位置,然后|counter,得出正確的var的lfu。這個時候你會問了,那明明是lru,其實在源碼中它既可以表示lru,又可以表示lfu,其實它就是24bit的int類型字段。它的定義是這樣的

typedef struct redisObject {
    unsigned type:4;
    unsigned encoding:4;
    unsigned lru:LRU_BITS; /* LRU time (relative to global lru_clock) or
                            * LFU data (least significant 8 bits frequency
                            * and most significant 16 bits access time). */
    int refcount;
    void *ptr;
} robj;

下面我們介紹LFU中的幾個重要的概念

1.LFU的counter(訪問次數(shù))不是一直遞增的,它有一個遞減策略,它的實現(xiàn),上源碼:

unsigned long LFUDecrAndReturn(robj *o) {
    unsigned long ldt = o->lru >> 8;
    unsigned long counter = o->lru & 255;
    unsigned long num_periods = server.lfu_decay_time ? LFUTimeElapsed(ldt) / server.lfu_decay_time : 0;
    if (num_periods)
        counter = (num_periods > counter) ? 0 : counter - num_periods;
    return counter;
}

方法中的第1行,

unsigned      long      ldt      =      o  ->  lru      >>      8  ;

這個是算出最近一次的訪問時間,可能這里有人會問,為什么會右移8bit,是因為右邊的8位是counter,必須被移出去,才能得到時間。如果你現(xiàn)在左右移都弄不清的話,那么就先復習復習左右移。

第2行  

unsigned   long   counter   =   o -> lru   &   255 ;  

這個會算出counter,&255正好把前邊的16bit都變成0,同樣的話,如果你現(xiàn)在不懂&,請復習復習&。  

第3行

unsigned              long              num_periods              =              server      .      lfu_decay_time              ?              LFUTimeElapsed      (      ldt      )        /              server      .      lfu_decay_time              :              0      ;    

它的作用是算出遞減num,lfu_decay_time表示lfu遞減因子,LFUTimeElaspsed這個函數(shù)的作用是算出,當前now和最近一次訪問的差,即算出多久沒有訪問了。然后/遞減因子,算出需要counter遞減的多少。    

最后      

if  ( num_periods )      

counter   =  ( num_periods   >   counter )  ?   0   :   counter   -   num_periods ;      

return   counter ;      

算出counter。      

2.counter先做遞減,然后再做遞增,上代碼,具體講解,就看我的注釋吧

void updateLFU(robj *val) {
    unsigned long counter = LFUDecrAndReturn(val);   // 遞減操作
    counter = LFULogIncr(counter);  // 遞增操作
    val->lru = (LFUGetTimeInMinutes()<<8) | counter; // 生成真正的LFU
}
uint8_t LFULogIncr(uint8_t counter) {
    if (counter == 255) return 255; // counter的最大值是255
    double r = (double)rand()/RAND_MAX;
    double baseval = counter - LFU_INIT_VAL;
    if (baseval < 0) baseval = 0;
    double p = 1.0/(baseval*server.lfu_log_factor+1);
    if (r < p) counter++; // 經(jīng)過算法運算,r < p才做counter++
    return counter;
}

3.redis每次創(chuàng)建obj的時候都會設(shè)置LFU或者LRU,當然默認是LRU

robj *createObject(int type, void *ptr) {
    robj *o = zmalloc(sizeof(*o));
    o->type = type;
    o->encoding = OBJ_ENCODING_RAW;
    o->ptr = ptr;
    o->refcount = 1;

    /* Set the LRU to the current lruclock (minutes resolution), or
     * alternatively the LFU counter. */
    if (server.maxmemory_policy & MAXMEMORY_FLAG_LFU) { // 當設(shè)置了最大內(nèi)存策略和LFU的時候走LFU
        o->lru = (LFUGetTimeInMinutes()<<8) | LFU_INIT_VAL;
    } else {
        o->lru = LRU_CLOCK();
    }
    return o;
}

當設(shè)置了最大內(nèi)存策略和LFU的時候走LFU,else走LRU

感謝各位的閱讀,以上就是“什么是Redis-LFU”的內(nèi)容了,經(jīng)過本文的學習后,相信大家對什么是Redis-LFU這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!

本文名稱:什么是Redis-LFU
網(wǎng)站路徑:http://aaarwkj.com/article12/gdgsgc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供商城網(wǎng)站、用戶體驗外貿(mào)建站、App設(shè)計、網(wǎng)站設(shè)計、域名注冊

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站建設(shè)
精品一区二区亚洲精品| 亚洲日本韩国在线免费| 久久精品国产视频在热| 欧美日韩国产一区在线观看| 人妻大乳一区二区三区| 懂色av中文字幕一区| 男人天堂av网在线观看| 日韩精品中文一区二区| 午夜两性做爰免费视频| 99热这里只有精品免费播放| 午夜丁香婷婷爽少妇av| 欧美aⅴ一区二区三区| 我要看亚洲黄色片一级| 亚洲av毛片在线网站| 在线日韩中文字幕二区| 亚洲av蜜臀在线播放| 国产传媒在线免费播放视频| 欧美午夜福利在线电影| 国内传媒视频免费观看| 精品久久久久久久中文字幕| 欧美日韩中文国产天堂| 亚洲精品一区二区午夜| 亚洲激情视频在线视频| 国产精品国产三级专区| 黑人精品少妇一区二区三区| 中文字幕你懂的在线观看| 亚洲综合一区二区在线视频| 亚洲免费视频一二三区| 少妇人妻系列中文在线| 欧美电影剧情av在线| 青草草在线观看视频| av免费在线观看麻豆| 亚洲国产成在人网站天堂| 国产精品一区巨乳人妻| 久久精品午夜福利一区| 国产性做爰片免费视频| 亚洲一区二区三区在线播| 好吊妞在线新免费视频| 免费高清av一区二区| 在线国产丝袜自拍观看| 夜夜操狠狠操天天摸|