redisのデータ淘汰ポリシー

4915 ワード

redisメモリデータセットのサイズが一定に大きくなると、データ淘汰ポリシー(回収ポリシー)が実行されます.
1,volatile-lru:有効期限が設定されているハッシュテーブル(server.db[i].expires)から複数のkeyをランダムに選択し、選択したkeyで最も最近使用されているデータをlruアルゴリズムで淘汰する
2,allkey-lru:すべてのkeyのハッシュテーブル(server.db[i].dict)から複数のkeyをランダムに選択し、次に選択したkeyでlruアルゴリズムを用いて最近最も使用されているデータを淘汰する
3,volatile-ttl:有効期限が設定されているハッシュテーブル(server.db[i].expires)から複数のkeyをランダムに選択し、選択したkeyで有効期限が最も小さいデータを選択して淘汰します.
4,volatile-random:有効期限が設定されているハッシュテーブル(server.db[i].expires)からランダムにキーを選択して淘汰します.
5,allkey-random:すべてのkeyのハッシュテーブル(server.db[i].dict)からランダムにデータを選択して淘汰する
6,no-eviction(駆逐):メモリが上限に達し、データを淘汰しない.
 
redisは、キー値ペアの駆逐を確認すると、このデータが削除され、このデータ変更メッセージがローカル(AOF永続化)とスレーブ(プライマリスレーブ接続)にパブリッシュされます.
LRUデータ淘汰メカニズムは、データセット内でランダムにいくつかのキー値ペアを選択し、最近最も使用されているキー値ペアの淘汰を除去する.したがって、Redisは、すべてのデータセットで最も少なく使用されるキー値ペアを取得することを保証するのではなく、ランダムに選択されたいくつかのキー値ペアにすぎない.
TTLデータ淘汰メカニズム:国有企業からの時間redisDB.expiresテーブルでランダムにいくつかのキー値ペアを選択し、最も期限切れのキー値ペアの淘汰を取り出します.したがって、Redisは、すべての期限切れスケジュールの中で最も早く期限切れしたキー値ペアを取得することを保証するのではなく、ランダムに選択されたいくつかのキー値ペアの中である.
どんなメカニズムでも、すべてのキー値ペアの中から適切な淘汰を選択します.
データの淘汰はどこで始まりますか.
Redisサーバは、コマンドを実行するたびに、使用するメモリが超過しているかどうかを検出します.超過した場合は、データの淘汰を行います.
int freeMemoryIfNeeded(void) {
    /**
     * noeviction      ,     
     */
    if (server.maxmemory_policy == MAXMEMORY_NO_EVICTION)
        return C_ERR;
    while (mem_freed < mem_tofree) {
        int j, k, keys_freed = 0;
        for (j = 0; j < server.dbnum; j++) {
            /**
             *         ,Redis              key=>expire      
             */
            if (server.maxmemory_policy == MAXMEMORY_ALLKEYS_LRU ||
                server.maxmemory_policy == MAXMEMORY_ALLKEYS_RANDOM)
            {
                dict = server.db[j].dict;
            } else {
                dict = server.db[j].expires;
            }
            /**
             *    :                 ,      key
             */
            if (server.maxmemory_policy == MAXMEMORY_ALLKEYS_RANDOM ||
                server.maxmemory_policy == MAXMEMORY_VOLATILE_RANDOM)
            {
                de = dictGetRandomKey(dict);
                bestkey = dictGetKey(de);
            }
            /**
             *    :                 ,        ,   lru        
             */
            else if (server.maxmemory_policy == MAXMEMORY_ALLKEYS_LRU ||
                server.maxmemory_policy == MAXMEMORY_VOLATILE_LRU)
            {
                /*     */
                struct evictionPoolEntry *pool = db->eviction_pool;
                while(bestkey == NULL) {
                    /* 
                     *   ,        ;
                     *         ,             ;
                     *       ,        ,                ,         ;
                     */ 
                    evictionPoolPopulate(dict, db->dict, db->eviction_pool);
                    /**
                     *         lru  ,             key
                     */
                    for (k = MAXMEMORY_EVICTION_POOL_SIZE-1; k >= 0; k--) {
                        if (pool[k].key == NULL) continue;
                        de = dictFind(dict,pool[k].key);
                        /*      key        */
                        sdsfree(pool[k].key);
                        memmove(pool+k,pool+k+1,
                            sizeof(pool[0])*(MAXMEMORY_EVICTION_POOL_SIZE-k-1));
                        pool[MAXMEMORY_EVICTION_POOL_SIZE-1].key = NULL;
                        pool[MAXMEMORY_EVICTION_POOL_SIZE-1].idle = 0;
                        /* pool     key,    ,    db     ,   ,   db       ,       */
                        if (de) {
                            bestkey = dictGetKey(de);
                            break;
                        } else {
                            /* Ghost... */
                            continue;
                        }
                    }
                }
            }
            /**
             *    :                    key,     key               
             */
            else if (server.maxmemory_policy == MAXMEMORY_VOLATILE_TTL) {
                for (k = 0; k < server.maxmemory_samples; k++) {
                    sds thiskey;
                    long thisval;
                    de = dictGetRandomKey(dict);
                    thiskey = dictGetKey(de);
                    thisval = (long) dictGetVal(de);
                    if (bestkey == NULL || thisval < bestval) {
                        bestkey = thiskey;
                        bestval = thisval;
                    }
                }
            }
            if (bestkey) {
                long long delta;
                robj *keyobj = createStringObject(bestkey,sdslen(bestkey));
                //     ,   key          slave
                propagateExpire(db,keyobj);
                //   key
                dbDelete(db,keyobj);
            }
        }
    }
    return C_OK;
}