誇張ではなく、絶対にそうはならない

誇張ではなく、絶対にそうはならない
[[280896]]

01. はじめに

データのクエリ速度を向上させるために、キャッシュがよく使用されます。キャッシュ容量には制限があるため、キャッシュ容量が上限に達すると、新しいデータを追加できるように、一部のデータを削除してスペースを確保する必要があります。キャッシュされたデータはランダムに削除することはできません。一般的に、特定のアルゴリズムに基づいてキャッシュされたデータを削除する必要があります。一般的な除去アルゴリズムには、LRU、LFU、FIFO などがあります。この記事では、LRU アルゴリズムについて説明します。

02. LRUの紹介

LRU は Least Recently Used の略です。このアルゴリズムでは、最も最近使用されたデータはホット データであり、次回も高い確率で再び使用されるとみなされます。最近ほとんど使用されていないデータは、次回も使用されなくなる可能性があります。キャッシュ容量がいっぱいになると、最近あまり使用されていないデータが最初に削除されます。

キャッシュの内部データが以下のようになっていると仮定します。


ここでは、リストの最初のノードをヘッド ノード、最後のノードをテール ノードと呼びます。

キャッシュを呼び出してキー = 1 のデータを取得する場合、図に示すように、LRU アルゴリズムはノード 1 をヘッド ノードに移動する必要があり、他のノードは変更されません。


次にkey=8のノードを挿入します。このときキャッシュ容量が上限に達しているため、追加する前にデータを削除する必要があります。各クエリはデータをヘッド ノードに移動するため、クエリされていないデータはテール ノードに移動します。テールのデータは最もアクセスが少ないデータであると考えられるため、テール ノードのデータは削除されます。


次に、データをヘッドノードに直接追加します。


LRU アルゴリズムの具体的な手順の概要は次のとおりです。

  • 新しいデータはリストの先頭に直接挿入されます
  • キャッシュデータがヒットし、データがリストの先頭に移動される
  • キャッシュがいっぱいになったら、リストの末尾にあるデータを削除します。

03. LRUアルゴリズムの実装

上記の例からわかるように、LRU アルゴリズムではヘッド ノードを追加し、テール ノードを削除する必要があります。リンクリスト内のノードの追加/削除の時間計算量は O(1) であるため、ストレージ キャッシュ データ コンテナーとして非常に適しています。ただし、通常の一方向リンク リストは使用できません。一方向リンク リストには、いくつかの欠点があります。

  1. 任意のノードからデータを取得するたびに、最初のノードからトラバースする必要があり、その結果、ノードを取得する複雑さは O(N) になります。
  2. 中間ノードをヘッドノードに移動するには、中間ノードの前のノードの情報を知る必要があるため、一方向リンクリストを再度走査して情報を取得する必要があります。

上記の問題は、他のデータ構造を組み合わせることで解決できます。

ハッシュテーブルを使用してノードを格納すると、ノードを取得する複雑さは O(1) に削減されます。ノード移動の問題は、前のノード情報を記録するための先行ポインタをノードに追加することで解決できます。これにより、リンク リストが一方向リンク リストから双方向リンク リストに変更されます。

要約すると、図に二重リンクリストとハッシュテーブルの組み合わせを使用したデータ構造が示されています。


2 つの「センチネル」ノードは双方向リンク リストに意図的に追加されており、データの保存には使用されません。センチネル ノードを使用すると、ノードを追加/削除するときに境界ノードが存在しないかどうかを考慮する必要がなくなり、プログラミングの難易度が軽減され、コードの複雑さが軽減されます。

LRU アルゴリズムの実装コードは次のとおりです。簡略化のため、key と val は両方とも int 型とみなされます。

  1. パブリッククラスLRUCache {
  2.  
  3. エントリーヘッド、テール;
  4. int容量;
  5. 整数 サイズ;
  6. マップキャッシュ;
  7.  
  8.  
  9. パブリックLRUCache( int容量) {
  10. this.capacity = 容量;
  11. // リンクリストを初期化する
  12. リンクリストを初期化します。
  13. サイズ= 0;
  14. キャッシュ = 新しい HashMap<>(容量 + 2);
  15. }
  16.  
  17. /**
  18. * ノードが存在しない場合は -1 を返します。存在する場合は、ノードをヘッド ノードに移動し、ノードのデータを返します。
  19. *
  20. * @paramキー 
  21. * @戻る 
  22. */
  23. 公共  int get( int  ) {
  24. エントリノード = cache.get( key );
  25. if (ノード == null ) {
  26. -1 を返します
  27. }
  28. // モバイルノードがあります
  29. ノードを先頭に移動します。
  30. ノード値を返します
  31. }
  32.  
  33. /**
  34. * ヘッドノードにノードを追加します。容量がいっぱいになると、テールノードは削除されます。
  35. *
  36. * @paramキー 
  37. * @パラメータ値
  38. */
  39. パブリックvoid put( int  キー int値){
  40. エントリノード = cache.get( key );
  41. if (ノード ​​!= null ) {
  42. ノードの値 = 値;
  43. ノードを先頭に移動します。
  44. 戻る;
  45. }
  46. // 存在しません。最初に追加し、その後末尾のノードを削除します
  47. // この時点で容量がいっぱいなので、末尾のノードを削除します
  48. if (サイズ== 容量 ) {
  49. エントリ lastNode = tail.pre;
  50. 最後のノードを削除します。
  51. cache.remove( lastNode.key );
  52. サイズ- ;  
  53. }
  54. // ヘッドノードを追加する
  55.  
  56. エントリ newNode = new Entry();
  57. newNode.key =キー;
  58. 新しいノードの値 = 値;
  59. ノードを追加します(新しいノード)。
  60. cache.put(キー、newNode);
  61. サイズ++;
  62.  
  63. }
  64.  
  65. プライベート void moveToHead(エントリノード) {
  66. // まず元のノードの関係を削除します
  67. ノードを削除します。
  68. ノードを追加します。
  69. }
  70.  
  71. プライベート void addNode(エントリノード) {
  72. ノードを次のノードにドラッグします。
  73. ノードの次=ヘッドの次;
  74.  
  75. ノードの先頭に、
  76. ノードを次に示します
  77. }
  78.  
  79. プライベート void deleteNode(エントリノード) {
  80. ノードのpre.next =ノードのnext ;
  81. ノードを次のノードにリンクします。
  82. }
  83.  
  84.  
  85. 公共 静的クラスエントリ{
  86. 公開エントリー事前;
  87. 公開エントリ次へ;
  88. 公共 整数 ;
  89. 公共  int値;
  90.  
  91. パブリックエントリ( int  キー int値){
  92. this.key =キー;
  93. this.value = 値;
  94. }
  95.  
  96. パブリックエントリ() {
  97. }
  98. }
  99.  
  100. プライベートvoid initLinkedList() {
  101. head = 新しいエントリ();
  102. tail = 新しいエントリ();
  103.  
  104. ヘッドの次= テール;
  105. tail.pre = ヘッド;
  106.  
  107. }
  108.  
  109. 公共 静的void main(String[] args) {
  110.  
  111. LRUCache キャッシュ = 新しい LRUCache(2);
  112.  
  113. キャッシュに1をセットします。
  114. キャッシュにデータを格納する。
  115. System.out.println (cache.get(1)) ;
  116. キャッシュにデータを格納する。
  117. System.out.println (cache.get(2)) ;
  118.  
  119. }
  120. }

04. LRUアルゴリズムの分析

キャッシュ ヒット率は、キャッシュ システムの非常に重要な指標です。キャッシュ システムのキャッシュ ヒット率が低すぎると、クエリがデータベースに逆流し、データベースにかかる負荷が増加します。

上記の分析と組み合わせると、LRU アルゴリズムの長所と短所がわかります。

LRU アルゴリズムの利点は、実装が難しくなく、ホット データの場合、LRU 効率が非常に優れていることです。

LRU アルゴリズムの欠点は、履歴データのバッチ クエリなどの不定期のバッチ操作では、キャッシュ内の人気データがこれらの履歴データに置き換えられ、キャッシュ汚染が発生し、キャッシュ ヒット率が低下し、通常のデータ クエリが遅くなる可能性があることです。

05. LRUアルゴリズムの改善

以下のソリューションはMySQL InnoDB LRU改良アルゴリズムから派生したものである。

図に示すように、リンク リストをホット データ領域とコールド データ領域の 2 つの部分に分割します。


改善後、アルゴリズムのフローは次のようになります。

  1. アクセスされたデータがホット データ領域にある場合、以前の LRU アルゴリズムと同様に、ホット データ領域のヘッド ノードに移動されます。
  2. データを挿入するときに、キャッシュがいっぱいの場合は、末尾のノードにあるデータを削除します。次に、コールド データ領域のヘッド ノードにデータを挿入します。
  3. コールド データ領域のデータにアクセスするたびに、次の判断を行う必要があります。
  4. データが指定された時間(1 秒など)を超えてキャッシュ内に保持されている場合、そのデータはホット データ領域のヘッド ノードに移動されます。
  5. データが指定された時間より前の時間に存在する場合、位置は変更されません。

時々実行されるバッチ クエリの場合、データは単にコールド データ領域に送られ、すぐに削除されます。よく使用されるデータ領域のデータは影響を受けないため、LRU アルゴリズムのキャッシュ ヒット率が低下する問題が解決されます。

その他の改良された方法には、LRU-K、2Q、LIRS アルゴリズムなどがあります。興味のある学生はぜひチェックしてみてください。

<<:  PythonコードからAPPまで、必要なのは小さなツールだけ:GitHubには3,000以上のスターがある

>>:  自動運転車の未来はどうなるのか?マッキンゼーは言う

ブログ    
ブログ    

推薦する

人工知能を軸に:現代の情報管理の力を解き放つ

情報の海の中で、価値ある洞察を見つけることが重要です。最新の情報管理は、高度なテクノロジーと革新的な...

人工知能エンジニアリングについて知らないかもしれない7つのこと

[[387622]]ビジネスの世界が人々の想像よりも速く変化することは周知の事実です。この問題に対処...

百度研究所が新しいAIツールを発表:10分以内に記事を自動的に動画に変換可能

[[322859]]この記事はAI新メディアQuantum Bit(公開アカウントID:QbitAI...

3万回以上の地震訓練を実施した後、彼らは揺れの強さを素早く予測する新しい方法を発見した。

[[396585]]ビッグデータダイジェスト制作編纂者:朱克進DeepShake ネットワークのト...

...

...

ロボット産業発展の鍵は人材にある

製造強国戦略の徹底的な実行の重要な部分として、ロボット産業はますます多くの人々の注目を集めています。...

自動運転について話しましょう

自動運転とは何ですか?自動運転とは、さまざまなセンサー、コンピュータービジョン、人工知能、機械学習な...

人工知能と機械学習の違いを本当に理解していますか?

この記事はLeiphone.comから転載したものです。転載する場合は、Leiphone.com公式...

チューリングテストは死んだ! ChatGPTは人間テストに合格してもカウントされない、スーパーAIが新参者「ロジックパズル」を評価

世界で最も強力な AI - ChatGPT は、さまざまなテストに合格し、真偽を区別するのが難しい回...

2024年のAIに関する5つの予測

2023 年には、AI、ML、特に GenAI があらゆるところに存在しますが、内容よりもパフォーマ...

Unity が開発者向け AI ソフトウェア マーケットプレイス AI Hub を立ち上げ、株価が 15% 上昇

6月28日、Unityは開発者向けAIソフトウェアマーケット「AI Hub」を正式に立ち上げ、AIソ...

有名人の「ペイント肌」顔変更技術を悪用したいたずら合成AI動画の調査

[[265249]]新華社、上海、5月13日。AI技術の発展により、動画の顔を変える技術的ハードルが...

感動して泣きました。ロボットはついに自分で服をたたむことを覚えました。

人間の子どもの最も基本的な運動知能、例えばつかむ、持ち上げる、あるいはキルトや衣服をたたむといった家...

IBM、スタートアップを支援するために5億ドルのエンタープライズAIベンチャーファンドを設立

IBMは最近、新たな企業投資ツールであるEnterprise AI Venture Fundを立ち上...