「redisラーニング」--キャッシュ・トーナメント・ポリシー

7746 ワード

redis
  • redis
  • キャッシュ淘汰ポリシー
  • 失効の内部実装
  • passive wayネガティブメソッド
  • Active Way




  • キャッシュ・トーナメント・ポリシー
    参考:Redisメモリ淘汰メカニズム
    Redisプライマリ・キーの失効原理と実現メカニズムを深く理解する
  • 認識
  • 最大キャッシュ
  • redisでは、ユーザが最大使用メモリサイズserverを設定ことができる.maxmemory、デフォルトは0で、最大キャッシュは指定されていません.新しいデータが追加され、最大メモリを超えるとredisがクラッシュするので、必ず設定してください.redisメモリデータセットサイズが一定サイズに上昇すると、データ淘汰ポリシーが実行されます.
  • プライマリ・キー失効
  • 無効なデータを定期的にクリーンアップする重要なメカニズムとして、Redisが提供する多くのコマンドの中で、EXPIRE、EXPIREAT、PEXPIRE、PEXPIREATおよびSETEXおよびPSETEXはいずれもKeyValueペアの失効時間を設定するために使用することができ、1つのKeyValueペアが失効に関連付けられると、失効後に自動的に削除される(またはアクセスできなくなるより正確な)
  • 淘汰メカニズム
  • redisにデータを保存するにつれて、メモリの空き容量が追加したデータを満たすことができない場合、redis内ではデータ淘汰ポリシーが実行され、一部のコンテンツが消去され、新しいデータがメモリに保存されることを保証します.
    メモリ淘汰メカニズムはメモリをよりよく使用するために、一定のmissでメモリの利用率を交換し、redisキャッシュに保存されているのがホットスポットデータであることを保証する.

  • 有効期限の設定
    redisのkeyに有効期限を設定できます.keyが有効期限切れの場合(生存期間は0)、削除されます.
  • keyを上書きすると、setコマンドやgetSetコマンド
  • などのデータの生存時間が変更されます.
  • keyに対応するvalueを変更すると、他の同じkeyとvalueを使用して上書きすると、現在のデータの生存時間が異なります.キーに対してINCRコマンドを実行したり、リストに対してLPUSHコマンドを実行したり、ハッシュ・テーブルに対してHSETコマンドを実行したりすると、キー自体の生存時間は変更されません.
  • renameを使用して1つのkeyを改名すると、改名後のkeyの生存時間は改名前と同じである.
  • persistコマンドを使用すると、keyを削除することなく、keyの生存時間を削除し、keyをpersistent key
  • に再することができる.
  • expireコマンドを使用するとkeyの生存時間
  • を更新できます.
  • 淘汰戦略
  • redis淘汰ポリシー構成:maxmemory-policy voltile-lru、ホット構成
  • をサポート
  • redisは、6つのデータ淘汰ポリシーを提供します.
  • voltile-lru:有効期限が設定されているデータセット(server.db[i].expires)から、最近最も少ない使用データを選択して
  • を淘汰する.
  • volatile-ttl:有効期限が設定されているデータセット(server.db[i].expires)から有効期限が切れるデータを選択する
  • .
  • volatile-random:有効期限が設定されているデータセット(server.db[i].expires)から任意に選択するデータ淘汰
  • allkeys-lru:データセット(server.db[i].dict)から最近最も少ない使用データを選択して
  • を淘汰する
  • allkeys-random:データセット(server.db[i].dict)から任意選択データ淘汰
  • no-enviction(駆逐):駆逐禁止データ

  • ポリシー・ルール
  • データがべき乗則分布を示す、すなわち、一部のデータアクセス頻度が高く、一部のデータアクセス頻度が低い場合、allkeys-lru
  • を用いる.
  • データが平等に分布する場合、すなわちすべてのデータアクセス頻度が同じである場合、allkeys-random
  • が使用される.
  • volatile-lruポリシーとvolatile-randomポリシーは、キャッシュおよび永続化ストレージに1つのRedisインスタンスを適用する場合に適していますが、2つのRedisインスタンスを使用することで同じ効果を達成することもできます.
  • key設定の期限切れ時間は実際にはより多くのメモリを消費するため、allkeys-lruポリシーを使用してメモリ
  • をより効率的に使用することをお勧めします.
  • 非精確なLRU
    上記のLRU(Least Recenly Used)ポリシーは、実際にRedisが実現するLRUは信頼できるLRUではありません.つまり、名目上、LRUアルゴリズムを使用してキーを淘汰しますが、実際に淘汰されたキーは必ずしも実際に最も長く使われていないわけではありません.ここでは、すべてのキー空間で最適解を検索する必要がある場合、システムのオーバーヘッドが必然的に増加します.Redisは単一スレッドであり、同じインスタンスが各時点で1つのクライアントにしかサービスできないため、時間のかかる操作は慎重に行わなければならない.一定のコスト内で相対的なLRUを実現するために、初期のRedisバージョンは、サンプリングされたLRUに基づいており、すなわち、すべてのキー空間内探索解を放棄してサンプリング空間探索最適解に変更された.Redis 3から0バージョン以降、Redisの作成者は、サンプルベースのLRUをいくつか最適化し、一定のコストで結果を実際のLRUに近づけることを目的としています.

  • 失効した内部実装
    Redisが失効したプライマリ・キーを削除する方法は、主に2つあります.
  • ネガティブメソッド(passive way)は、プライマリ・キーがアクセスされたときに失効したことが発見された場合、
  • を削除する.
  • ポジティブメソッド(active way)は、失効時間が設定されたプライマリ・キーから失効したプライマリ・キーの一部を周期的に選択する
  • を削除する.
  • アクティブ削除:現在使用されているメモリがmaxmemoryの制限を超えている場合、アクティブクリーンアップポリシーがトリガーされます.このポリシーは、起動パラメータの構成によってプライマリ・キーの具体的な失効時間を決定し、すべてexpiresという辞書表に維持されます.
    typedef struct redisDb {
      dict *dict; //key-value
      dict *expires;  //    key
      dict *blocking_keys;
      dict *ready_keys;
      dict *watched_keys;
      int id;
    } redisDb;

  • passive wayネガティブメソッド
  • passive wayでは、redisは、GET、MGET、HGET、LRANGEなどのデータの読み取りに関するすべてのコマンドを実装する際にexpireIfNeededを呼び出し、データの読み取り前に失効の有無を確認し、失効したら削除するという意味である.
  • expireIfNeeded関数で呼び出された別の関数propagateExpire.この関数は、失効したプライマリ・キーが正式に削除される前に、このプライマリ・キーが失効した情報をブロードキャストするために使用され、この情報は2つの宛先に伝播します.
  • はAOFファイルに送信され、失効したプライマリ・キーを削除する操作をDEL Keyの標準コマンド・フォーマットで記録する.
  • は、現在のRedisサーバに送信されたすべてのSlaveであり、同様に失効したプライマリ・キーを削除する操作をDEL Keyの標準コマンド形式でこれらSlaveにそれぞれの失効したプライマリ・キーを削除することを通知する.Slaveとして動作するすべてのRedisサーバは、ネガティブな方法で失効したプライマリ・キーを削除する必要はなく、Masterに従うだけでOKであることがわかります.


  • コードセグメント2:
    int expireIfNeeded(redisDb *db, robj *key) {
                 
        long long when = getExpire(db,key);
                 ,            (       -1),    0
        if (when < 0) return 0;
          Redis      RDB       ,            ,    0
        if (server.loading) return 0;
             Redis      Slave   ,            ,  Slave
                  Master    ,                    
            ,                  
        if (server.masterhost != NULL) {
            return mstime() > when;
        }
                  ,                  ,         
                 0
        if (mstime() <= when) return 0;
                     ,                 ,       
                ,             
        server.stat_expiredkeys++;
        propagateExpire(db,key);
        return dbDelete(db,key);
    }
    
    void propagateExpire(redisDb *db, robj *key) {
        robj *argv[2];
        shared.del  Redis                   Redis  , DEL  
        argv[0] = shared.del;
        argv[1] = key;
        incrRefCount(argv[0]);
        incrRefCount(argv[1]);
          Redis        AOF,               DEL  
        if (server.aof_state != REDIS_AOF_OFF)
            feedAppendOnlyFile(server.delCommand,db->id,argv,2);
          Redis       Slave,       Slave  DEL       ,   
          expireIfNeeded        Slave               ,   
            Master        OK 
        if (listLength(server.slaves))
            replicationFeedSlaves(server.slaves,db->id,argv,2);
        decrRefCount(argv[0]);
        decrRefCount(argv[1]);
    }
    

    Active Way
    ネガティブな方法の欠点は、keyがなかなかアクセスされないと、メモリ領域が多く消費されることです.したがって、アクティブな方法(Active Way):この方法は、失効したプライマリ・キーのチェックと削除を含む指定された操作を一定時間ごとに中断するredisの時間イベントを利用します.
  • タイムイベント
  • 時間イベントを作成します.コールバック関数はserverCronです.Redisサーバの起動時に作成され、1秒当たりの実行回数はマクロ定義REDIS_によって定義されます.DEFAULT_HZで指定します.デフォルトでは1秒に10回実行されます.
  • activeExpireCycleを使用して失効key
  • をクリア
    その実現原理は、Redis内の各データベースのexpires辞書テーブルから、ランダムにREDIS_をサンプリングすることである.EXPIRELOOKUPS_PER_CRON(デフォルトは10)個の失効時間が設定されているプライマリ・キーは、失効したかどうかを確認し、失効したプライマリ・キーを削除します.失効したプライマリ・キーの数が今回のサンプリング個数に占める割合が25%を超えると、次のランダムなサンプリングと削除が継続され、先ほどの割合が25%を下回るまで現在のデータベースの処理が停止し、次のデータベースに移行します.
    なお、activeExpireCycle関数は、Redis内のすべてのデータベースを一度に処理しようとはしません.最大REDIS_のみを処理します.DBCRON_DBS_PER_CALL(デフォルトは16)に加え、activeExpireCycle関数には処理時間の制限があり、実行したいだけ実行するのではなく、実行したいだけ実行するのではなく、失効したプライマリ・キーの削除に多くのCPUリソースを消費しないようにすることが目的です.