"アルゴリズム - Lruを"

ワン:概要

  - 管理のためのLRUキャッシュポリシー自体は中のLinux / Redisの/ MySQLで実施しています、。ただ、異なる実装。

  - LRUアルゴリズム[ 最小最近使用(最低使用) ]

  -過去のデータレコードに基づいてデータアクセスを排除するために、その核となるアイデアは、「データが最近訪問された場合には、将来のアクセスの確率も高くなっています。」されます

   - GitHubの

 

2:LRUアルゴリズム実装単独リンクリスト

  - アイデア

    -  単独リンクリスト達成するために

 

  - プロセス

    - 1. 新しいデータがリンクリストの先頭に挿入されています

    - 2 たびにキャッシュヒット(すなわち、キャッシュデータをアクセスする)、次いで、データがリンクされたリストの先頭に移動されます

    - 3. リストがいっぱいになると、データは破棄され、リンクされたリストの末尾

 

  - 利点

    - シンプル。

    - ホットデータ、LRU良い効率がある場合もございます。

 

  - 欠点

    -  散発的、定期的なバッチ操作は、LRUの急激な減少につながるヒット率キャッシュ汚染は非常に深刻です

    -  ヒットリストトラバースする必要がある、データ・ブロック・インデックス・ヒットを見つけ、その後、頭部にデータを移動する必要があります。

 

  - フローチャート

    - 

 

  - コードの実装(PHP)

    • / * * 
       *アイデア
       *単鎖を達成
       *原理は
       *単鎖
       *プロセス
       * 1.新しいデータがリンクリストの先頭に挿入される。
       * 2キャッシュヒット(すなわち、キャッシュデータをアクセスする)、データはリストの先頭に移動されるたびに; 
       * 3.リストがいっぱいになると、データは破棄され、リンクされたリストの末尾。
       *メリット
       *シンプル。
       *現在ホットスポットデータ、LRU効率よく。
       *短所が
       散発*、定期的なバッチ操作はLRUヒット率の急激な減少につながる、キャッシュ汚染は非常に深刻です。
       ヒットリストは、データ・ブロック・インデックス・ヒットを見つけたとき*あなたは頭にデータを移動する必要があり、トラバースする必要があります。
       * / 
      クラスLRU 
      { 
          公共 静的 $ lruList = []; // 順次記憶単鎖構造
          パブリック 静的 $ = MAXLEN 5。 ;   // 許可リストの最大長
          パブリック 静的 $ nowLen = 0;   // 現在の長さをリストする
      
          * / * 
           。* LRU_1コンストラクタ
           * PHP常駐プログラム処理ではないので、リストが初期化のMysql / Redisのことによって達成することができるように、
           * / 
          パブリック関数__construct()
          { 
              自己:: $ lruList = []; 
              自己: :$ nowLen   = COUNT(自己:: $ lruList); 
          } 
      
          / * * 
           * =キー>の値を取得します
           * @paramキーの$ 
           *の@returnヌル
           * / 
          パブリック関数GET (キー$)
          { 
              $値は = ヌル; 
      
              // LRUキューが空である、ダイレクトリターン
              IF(!:: $ lruListセルフ){ 
                  自己lruList :: $ [] = [キー$ => $ この - >のgetData(キー$)]; //は、実際の状況のデータ項目を取得 
                  自己:: $ nowLenを++ ;
                   戻り$値; 
              } 
      
              // LRUバッファを探す
              ために($ I = 0 ; $ Iは自己:: $ nowLen <; $ Iは++ ){ 
      
                  // キャッシュが存在する場合、プロセスは直接戻り、リスト・ヘッダ・データを再挿入
                  IF (ISSET(自己:: lruList $ [$ I] [キー$])){ 
      
                      $値 = 自己:: $ lruList [$ I] [キー$]; 
      
                      解除($ lruList自己:: [$ I]); 
      
                      するarray_unshift(自己:: $ lruList 、[キー$ => $値]); 
      
                      BREAK; 
                  } 
              } 
      
      
              // もしノーキャッシュLRU 
              IF(!{ISSET($値))
      
                  // 挿入ヘッドの 
                  するarray_unshift(自己:: $ lruList、[キー$ => $ この - >のgetData(キー$)]); // 実際の状況に応じてデータ項目を取得 
                  自己:: $ nowLen ++ ; 
      
                  IF(自己:: $ nowLen> セルフMAXLEN :: $を){ 
                      自己nowLen :: $ - ; 
                      array_pop(自己:: $ lruList); 
                  } 
              } 
      
              戻り$値; 
      
          } 
      
          / * * 
           *のLRU出力キュー
           * / 
          パブリック関数echoLruList() 
          { 
              のvar_dump(自己:: $ lruList); 
          } 
      
          / * * 
           *取得し、実際の環境データに基づいて
           * @paramキーの$ 
           * @returnの文字列
           * / 
          パブリック関数のgetData(キー$)
          { 
              リターン ' データ' ; 
          } 
      }

       

 

3:LruをKアルゴリズム

  - アイデア

    -するためにLRU「キャッシュ汚染」を回避し、問題

    -  キューに追加キャッシュが生じるの数を維持するために。核となるアイデアは、のために「最近使用した1時間」の基準を拡張することで、「最近使用したK回。」

 

  - 原理

    - LRUに比べ、LRU-Kは、アクセスされている歴史のキューを維持するために、より多くを必要とするすべてのキャッシュされたデータを記録しました。

    -のみアクセスデータの数は、キャッシュにデータの前にK回に到達したとき。

    - あなたはデータを排除する必要がある場合には、LRU-Kは、現在の時刻から最大のデータをK番目のアクセス時間を排除するであろう。

 

  - プロセス

    - 1.データが最初にアクセスされ、アクセス履歴リストに追加

    - 2履歴リスト内のデータ・アクセスは、場合K回数に達していない特定の規則に従って、アクセスをLRUを排除

    - 3の数は、データ・アクセス履歴キューがアクセスするとK倍に達し、データは、インデックス履歴キューから削除されますバッファキューにデータが、バッファおよびデータバッファキュー時間で再注文しました。

    - 4.キャッシュ・データ・キューは、並べ替え、再度アクセスされます。

    - データ・バッファ・キュー行を排除する5.必要性、すなわち、データの最後に、段階的に廃止:データ消去「今、最も古いから最後から二番目のK訪問を」。

 

  - 利点

    - LRU-Kが発生し、「キャッシュ汚染」の問題を低減し、ヒット率はLRUよりも高くなっています。

 

  - 欠点

    -  LRU-K・キューは、優先キュー、アルゴリズムの複雑さとコストが比較的高いです。

    - LRU-Kのでも歴史的コホートを維持する必要があるので、メモリ消費量がよりあろう

 

  - フローチャート

    - 

 

  - コードの実装

    • /**
       * 思路
       *     为了避免 LRU 的 '缓存污染' 问题
       *     增加一个队列来维护缓存出现的次数。其核心思想是将“最近使用过1次”的判断标准扩展为“最近使用过K次”。
       * 原理
       *     相比LRU,LRU-K需要多维护一个队列,用于记录所有缓存数据被访问的历史。
       *     只有当数据的访问次数达到K次的时候,才将数据放入缓存。
       *     当需要淘汰数据时,LRU-K会淘汰第K次访问时间距当前时间最大的数据
       * 流程
       *     1.数据第一次被访问,加入到访问历史列表;
       *     2.如果数据在访问历史列表里后没有达到K次访问,则按照一定规则 LRU淘汰;
       *     3.当访问历史队列中的数据访问次数达到K次后,将数据索引从历史队列删除,将数据移到缓存队列中,并缓存此数据,缓存队列重新按照时间排序;
       *     4.缓存数据队列中被再次访问后,重新排序;
       *     5.需要淘汰数据时,淘汰缓存队列中排在末尾的数据,即:淘汰“倒数第K次访问离现在最久”的数据。
       * 优点
       *     LRU-K降低了“缓存污染”带来的问题,命中率比LRU要高。
       * 缺点
       *     LRU-K队列是一个优先级队列,算法复杂度和代价比较高。
       *     由于LRU-K还需要维护历史队列,所以消耗的内存会更多。
       */
      class Lru_K
      {
          public static $historyList = []; // 访问历史队列
          public static $lruList     = []; // 顺序存储单链表结构
          public static $maxLen      = 5;  // 链表允许最大长度
          public static $nowLen      = 0;  // 链表当前长度
      
          /**
           * LRU_K constructor.
           * 由于 PHP 不是常驻进程程序,所以链表初始化可以通过 Mysql/Redis 实现
           */
          public function __construct()
          {
              self::$lruList     = [];
              self::$historyList = [];
              self::$nowLen      = count(self::$lruList);
          }
      
          /**
           * 获取 key => value
           * @param $key
           * @return null
           */
          public function get($key)
          {
              $value = null;
      
              // 查找 lru 缓存
              for ($i = 0; $i < self::$nowLen; $i++) {
      
                  // 如果存在缓存,则直接返回,并将数据重新插入链表头部
                  if (isset(self::$lruList[$i][$key])) {
      
                      $value = self::$lruList[$i][$key];
      
                      unset(self::$lruList[$i]);
      
                      array_unshift(self::$lruList, [$key => $value]);
      
                      break;
                  }
              }
      
              // 如果没有找到 lru 缓存, 则进入历史队列进行计数,当次数大于等于5时候,进入缓存队列
              if (!isset($value)) {
                  self::$historyList[$key]++;
      
                  $value = $this->getData($key);
      
                  // 进入缓存队列
                  if (self::$historyList[$key] >= 5) {
                      array_unshift(self::$lruList, [$key => $value]); // 根据实际项目情况获取数据
                      self::$nowLen++;
      
                      if (self::$nowLen > self::$maxLen) {
                          self::$nowLen--;
                          array_pop(self::$lruList);
                      }
      
                      unset(self::$historyList[$key]); // 历史队列推出
                  }
              }
      
              return $value;
      
          }
      
          /**
           * 输出 Lru 队列
           */
          public function echoLruList()
          {
              var_dump(self::$lruList);
              var_dump(self::$historyList);
          }
      
          /**
           * 根据真实环境获取数据
           * @param $key
           * @return string
           */
          public function getData($key)
          {
              return 'data';
          }
      }

       

おすすめ

転載: www.cnblogs.com/25-lH/p/11121172.html
おすすめ