RedisのLRUアルゴリズムの詳しい説明
次のコラム Redis チュートリアル では、Redis の LRU アルゴリズムについて詳しく説明します。困っている友人のお役に立てれば幸いです。
Redis の LRU アルゴリズム
LRU アルゴリズムの背後にある考え方はコンピューター サイエンスのいたるところに普及しており、プログラムの「局所性原理」と非常によく似ています。 。運用環境では、Redis のメモリ使用量アラームがありますが、それでも Redis のキャッシュ使用戦略を理解することは有益です。運用環境での Redis の使用戦略は次のとおりです。使用可能な最大メモリは 4 GB に制限されており、allkeys-lru 削除戦略が採用されています。いわゆる削除戦略: Redis の使用量が最大メモリ (4 GB など) に達したとき、この時点で新しいキーが Redis に追加されると、Redis は削除するキーを選択します。では、削除する適切なキーを選択するにはどうすればよいでしょうか?
CONFIG GET maxmemory
- "maxmemory"
- "4294967296"
CONFIG GET maxmemory-policy
- "maxmemory-policy"
- "allkeys-lru"
公式ドキュメント「LRU キャッシュとしての Redis の使用」の説明では、いくつかの説明が提供されています。 allkeys-lru、volatile-lru などのさまざまな削除戦略。私の意見では、選択する際には、ランダム性、キーが最近アクセスされた時間、キーの有効期限 (TTL)
# の 3 つの要素が考慮されます。例: allkeys-lru, "Count all"キーの履歴アクセス時間。「最も古い」キーを削除します。注: ここでは引用符を追加しましたが、実際、redis の特定の実装では、すべてのキーの最近のアクセス時間をカウントするのは非常にコストがかかります。考えてみてください、どうすればいいでしょうか?
新しいデータを追加するためのスペースを確保するために、最初にあまり使用されていない (LRU) キーを削除してキーを削除します。別の例: allkeys-ランダムとは、キーをランダムに選択して削除することを意味します。新しいデータを追加するためのスペースを確保するために、キーをランダムに削除します。
別の例: volatile-lru。expire コマンドを使用して期限切れになったキーのみを削除します。時間キーは、LRU アルゴリズムに従って削除されます。新しいデータのためのスペースを確保するために、最初にあまり使用されていない (LRU) キーを削除しようとしてキーを削除します。ただし、
有効期限が設定されたキーの間でのみです。追加しました。有効期限セット別の例: volatile-ttl は、expire コマンドを使用して有効期限が設定されているキーのみを削除します。どのキーの生存時間が短いか (TTL キーが小さいほど)、最初に移動し、削除します。
を使用してキーを削除し、新しいデータを追加するためのスペースを確保するために、最初に有効期間 (TTL) の短いキーを削除してみます。。ここで、expires 辞書のキーは、redis データベース キー スペース (redisServer) を指します。 -- ->redisDb--->redisObject)、expires ディクショナリの値は、このキーの有効期限 (long 型の整数) です。揮発性戦略 (エビクション方法) が機能するキーは、有効期限が設定されているキーです。 redisDb 構造では、expires という名前の辞書 (dict) が、
expired コマンドによって設定された有効期限を持つすべてのキーを保存するために定義されています
追加の説明: Redis データベースのキー スペースとは、構造体 redisDb で定義され、ハッシュ ディクショナリ型の「dict」という名前のポインタを指します。これは、redis DB に各キー オブジェクトを保存するために使用されます。および対応する値オブジェクト。 非常に多くの戦略があるので、どれを使用すればよいでしょうか?これには、Redis のキーのアクセス パターン (access-pattern) が関係します。アクセス パターンは、コードのビジネス ロジックに関連しています。たとえば、特定の特性を満たすキーには頻繁にアクセスされますが、他のキーはほとんど使用されません。すべてのキーがアプリケーションによってアクセスされる機会が等しい場合、そのアクセス パターンは一様分布に従います。ほとんどの場合、アクセス パターンは
べき乗則分布
捕捉 (キャプチャ) するには適切な削除戦略が必要です。電力指数分布の下では、LRU は優れた戦略です: キャッシュは将来を予測できませんが、次のように推論できます: 再び要求される可能性のあるキーは次のとおりです。最近頻繁にリクエストされたキー
。通常、アクセス パターンはそれほど突然変化しないため、これは効果的な戦略です。Redis での LRU 戦略の実装
最も直感的なアイデア: LRU、各キーの最新のアクセス時刻 (UNIX タイムスタンプなど) を記録します。UNIX タイムスタンプが最も小さいキーは最近使用されていないキーであり、このキーを削除します。 HashMapならできるようです。はい、ただし最初に各キーとそのタイムスタンプを保存する必要があります。次に、タイムスタンプを比較して最小値を取得する必要があります。コストは非常に高く、非現実的です。
2 番目の方法: 観点を変えて、特定のアクセス時点 (UNIX タイムスタンプ) を記録するのではなく、アイドル時間を記録します。アイドル時間が短いほど、最近アクセスされたことを意味します。
LRU アルゴリズムは、最も長く使用されていないキー、つまりアイドル時間が最も長いキーを削除します。
例: A、B 、 C 、 D の 4 つのキー、A は 5 秒ごとにアクセスされ、B は 2 秒ごとにアクセスされ、C と D は 10 秒ごとにアクセスされます。 (チルダは 1 秒を表します)、上の図からわかるように、A のアイドル時間は 2 秒、B のアイドル時間は 1 秒、C のアイドル時間は 5 秒、D はちょうど訪問したばかりなので、アイドル時間は 0 秒です
ここ、すべてのキーをリストするには、二重リンク リストを使用します。キーにアクセスした場合は、キーをリンク リストの先頭に移動します。キーを削除する場合は、リストの最後から直接削除します。
これは、特定のキーが最後にアクセスされた時刻を追跡するだけで済むため、実装が簡単です。場合によっては、これが必要ない場合もあります。必要なオブジェクトがすべて揃っているだけかもしれません。リンク リストでリンクされた削除。
しかし、redis では、LinkedList がスペースを取りすぎると考えられるため、この方法では実装されません。 Redis は、文字列、リンク リスト、辞書などのデータ構造に直接基づいて KV データベースを実装するのではなく、これらのデータ構造に基づいてオブジェクト システム Redis オブジェクトを作成します。 24 ビットの符号なしフィールドが redisObject 構造で定義され、コマンド プログラムによってオブジェクトが最後にアクセスされた時刻を保存します。
Redis オブジェクト構造を少し変更することで、24 ビットにすることができました。リンク リスト (ファット ポインタ!) でオブジェクトをリンクする余地はありませんでした。
結局のところ、最新の LRU アルゴリズムが削除されたとしても、完全に正確な LRU アルゴリズムは必要ありません。アクセスされたキーはほとんど影響しません。
#このメタデータを取得するために別のデータ構造を追加するという選択肢はありませんでしたが、LRU 自体が達成したいことの近似であるため、LRU 自体を近似するのはどうでしょうか?もともと Redis は次のように実装されました。 ランダムに 3 つのキーを選択し、アイドル時間が最も長いキーを削除します。その後、3 が設定可能なパラメータに変更され、デフォルトは N=5 になりました:
maxmemory-samples 5
キーを削除する必要がある場合は、ランダムなキーを 3 つ選択します。そしてアイドル時間が最も長いものを排除しますこれはとてもシンプルで、信じられないほどシンプルで、非常に効果的です。しかし、それでも欠点があります。ランダムに選択されるたびに、
歴史情報が使用されません。各ラウンドでキーを削除 (エビクト) する場合、N からランダムにキーを選択し、アイドル時間が最も大きいキーを削除します。次のラウンドでは、N からランダムにキーを選択します...考えたことはありますか? 過去:前回のラウンドでキーを削除するプロセスで、実際に N 個のキーのアイドル時間がわかったのですが、次のラウンドでキーを削除するときに、前のラウンドで学んだ情報の一部をうまく活用できますか?
しかし、このアルゴリズム最初から開始するのはあまりにも愚かです。そこで Redis は別の改善を行いました: バッファー プーリングを使用する 各ラウンドでキーが削除されると、N 個のキーのアイドル時間が取得されます。アイドル時間がプール内のキーよりも長い場合は、アイドル時間が取得されます。まだ大きい場合は、プールに追加します。このようにして、毎回削除されるキーは、ランダムに選択された N 個のキーの中で最大であるだけでなく、プール内のアイドル時間も最大になります。また、プール内のキーは複数回の比較ラウンドを通じて選別されており、そのアイドル時間はtime この時間は、ランダムに取得された Key のアイドル時間よりも大きくなる可能性が高く、プール内の Key には「過去の経験情報」が保持されていると理解できます。の実行全体を考えてみると、どのようにして大量の興味深いデータを廃棄しているかがわかります。おそらく、N 個のキーをサンプリングするときに、多くのデータに遭遇するでしょう。良い候補者を絞り込みましたが、その後は最良の候補者を排除し、次のサイクルで再び最初から開始します。
基本的に、N キーのサンプリングが実行されるとき、それはより大きなキーのプール (デフォルトではわずか 16 キー) を設定するために使用されました。このプールにはアイドル時間によってソートされたキーがあるため、新しいキーのみが含まれます。プール内のアイドル時間が 1 つのキーよりも長い場合、またはプールに空きスペースがある場合に、プールに入ります。「プール」を使用すると、グローバルな並べ替え問題がローカルな並べ替え問題に変換されます。比較の質問。 (並べ替えは本質的には比較ですが、囧)。アイドル時間が最大のキーを知るために、正確な LRU はグローバル キーのアイドル時間を並べ替えてから、アイドル時間が最大のキーを見つける必要があります。ただし、近似的なアイデアを採用することもできます。つまり、グローバル キーを表すいくつかのキーをランダムにサンプリングし、サンプリングによって取得したキーをプールに入れ、各サンプリング後にプールを更新することで、プール内のキーがランダムに選択されたキーの中でアイドル時間が最も長いキーが常に保存されます。エビクトキーが必要な場合は、アイドル時間が最も大きいキーをプールから直接取り出してエビクトします。この考え方は学ぶ価値があります。 この時点で、LRU ベースの削除戦略の分析は完了です。 Redis には LFU (アクセス頻度) に基づいた削除戦略もありますが、これについては後ほど説明します。
JAVA での
LRU 実装
JDK の LinkedHashMap は、次の構築メソッドを使用して LRU アルゴリズムを実装します。accessOrder は「最も最近使用されていない」測定標準を表します。たとえば、accessOrder=true は、java.util.LinkedHashMap#get 要素を実行するときに、この要素が最近アクセスされたことを意味します。
/** * Constructs an empty <tt>LinkedHashMap</tt> instance with the * specified initial capacity, load factor and ordering mode. * * @param initialCapacity the initial capacity * @param loadFactor the load factor * @param accessOrder the ordering mode - <tt>true</tt> for * access-order, <tt>false</tt> for insertion-order * @throws IllegalArgumentException if the initial capacity is negative * or the load factor is nonpositive */ public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) { super(initialCapacity, loadFactor); this.accessOrder = accessOrder; }
次に、java.util.LinkedHashMap#removeEldestEntry メソッドを書き換えます。
#{@link #removeEldestEntry(Map.Entry)} メソッドをオーバーライドして、新しいマッピングがマップに追加されたときに古いマッピングを自動的に削除するポリシーを適用することができます。スレッドの安全性を確保するために、Collections.synchronizedMap を使用して LinkedHashMap オブジェクトをラップします:
この実装は同期されていないことに注意してください。複数のスレッドがリンクされたハッシュ マップに同時にアクセスし、少なくとも 1 つのスレッドがリンクされたハッシュ マップにアクセスする場合、スレッドの数はマップを構造的に変更するため、外部で同期する必要があります。これは通常、マップを自然にカプセル化するオブジェクトを同期することによって実現されます。次のように実装されます: (org.elasticsearch.transport.TransportService )
final Map<Long, TimeoutInfoHolder> timeoutInfoHandlers = Collections.synchronizedMap(new LinkedHashMap<Long, TimeoutInfoHolder>(100, .75F, true) { @Override protected boolean removeEldestEntry(Map.Entry eldest) { return size() > 100; } });
- Redis LRU アルゴリズム改善に関するランダムメモ
- Redis を LRU キャッシュとして使用する
5G には、あらゆる種類のノードがネットワークに接続できるようにする機能があり、大量のデータが生成されます。このデータを処理してマイニングする方法これらのデータは実際には人間の行動を客観的に反映しているため、背後に隠されたパターン (機械学習、深層学習) は非常に興味深いものです。たとえば、WeChat Sports の歩数計測機能を使用すると、次のことがわかります。ねえ、私の活動レベルは毎日約 10,000 歩であることがわかりました。さらに一歩進んで、将来的にはさまざまな産業機器や家電製品から、社会的な事業活動や人間の活動を反映するさまざまなデータが生成されるようになります。このデータを合理的に利用するにはどうすればよいでしょうか?既存のストレージ システムはこのデータのストレージをサポートできますか? データに隠された値を分析するための効率的なコンピューティング システム (Spark または tensorflow...) はありますか?さらに、これらのデータに基づいてトレーニングされたアルゴリズム モデルは、適用後にバイアスをもたらすのでしょうか?データの悪用はありますか?オンラインで物を購入するときに、アルゴリズムがおすすめのものを表示します。モーメントを閲覧しているときに、ターゲットを絞った広告が表示されます。また、モデルは、必要な金額と借りたい額を評価します。ニュースを読むときにも、アルゴリズムがおすすめを表示します。そしてエンターテイメントのゴシップ。私たちが毎日見たり触れたりするものの多くは、これらの「データ システム」によって決定されていますが、それらは本当に公平なのでしょうか?実際には、失敗しても先生や友達、家族がフィードバックや修正をしてくれ、修正すれば、またゼロからやり直すことができます。しかし、これらのデータ システムではどうなるでしょうか?エラー修正のためのフィードバック メカニズムはありますか?それは人々をますます深く沈めるよう刺激するでしょうか?たとえあなたが正しく、良い信用を持っていたとしても、アルゴリズム モデルには依然として確率的なバイアスが存在する可能性があります。これは人間にとっての「公正な競争」の機会に影響を与えますか?これらはデータ開発者にとって考慮に値する質問です。
以上がRedisのLRUアルゴリズムの詳しい説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











Redisクラスターモードは、シャードを介してRedisインスタンスを複数のサーバーに展開し、スケーラビリティと可用性を向上させます。構造の手順は次のとおりです。異なるポートで奇妙なRedisインスタンスを作成します。 3つのセンチネルインスタンスを作成し、Redisインスタンスを監視し、フェールオーバーを監視します。 Sentinel構成ファイルを構成し、Redisインスタンス情報とフェールオーバー設定の監視を追加します。 Redisインスタンス構成ファイルを構成し、クラスターモードを有効にし、クラスター情報ファイルパスを指定します。各Redisインスタンスの情報を含むnodes.confファイルを作成します。クラスターを起動し、CREATEコマンドを実行してクラスターを作成し、レプリカの数を指定します。クラスターにログインしてクラスター情報コマンドを実行して、クラスターステータスを確認します。作る

Redisデータをクリアする方法:Flushallコマンドを使用して、すべての重要な値をクリアします。 FlushDBコマンドを使用して、現在選択されているデータベースのキー値をクリアします。 [選択]を使用してデータベースを切り替え、FlushDBを使用して複数のデータベースをクリアします。 DELコマンドを使用して、特定のキーを削除します。 Redis-CLIツールを使用してデータをクリアします。

Redisのキューを読むには、キュー名を取得し、LPOPコマンドを使用して要素を読み、空のキューを処理する必要があります。特定の手順は次のとおりです。キュー名を取得します:「キュー:キュー」などの「キュー:」のプレフィックスで名前を付けます。 LPOPコマンドを使用します。キューのヘッドから要素を排出し、LPOP Queue:My-Queueなどの値を返します。空のキューの処理:キューが空の場合、LPOPはnilを返し、要素を読む前にキューが存在するかどうかを確認できます。

Redis指令を使用するには、次の手順が必要です。Redisクライアントを開きます。コマンド(動詞キー値)を入力します。必要なパラメーターを提供します(指示ごとに異なります)。 Enterを押してコマンドを実行します。 Redisは、操作の結果を示す応答を返します(通常はOKまたは-ERR)。

Redisを使用して操作をロックするには、setnxコマンドを介してロックを取得し、有効期限を設定するために有効期限コマンドを使用する必要があります。特定の手順は次のとおりです。(1)SETNXコマンドを使用して、キー価値ペアを設定しようとします。 (2)expireコマンドを使用して、ロックの有効期限を設定します。 (3)Delコマンドを使用して、ロックが不要になったときにロックを削除します。

Redisソースコードを理解する最良の方法は、段階的に進むことです。Redisの基本に精通してください。開始点として特定のモジュールまたは機能を選択します。モジュールまたは機能のエントリポイントから始めて、行ごとにコードを表示します。関数コールチェーンを介してコードを表示します。 Redisが使用する基礎となるデータ構造に精通してください。 Redisが使用するアルゴリズムを特定します。

Centosシステムでは、Redis構成ファイルを変更するか、Redisコマンドを使用して悪意のあるスクリプトがあまりにも多くのリソースを消費しないようにすることにより、LUAスクリプトの実行時間を制限できます。方法1:Redis構成ファイルを変更し、Redis構成ファイルを見つけます:Redis構成ファイルは通常/etc/redis/redis.confにあります。構成ファイルの編集:テキストエディター(VIやNANOなど)を使用して構成ファイルを開きます:sudovi/etc/redis/redis.conf luaスクリプト実行時間制限を設定します。

Redisコマンドラインツール(Redis-Cli)を使用して、次の手順を使用してRedisを管理および操作します。サーバーに接続し、アドレスとポートを指定します。コマンド名とパラメーターを使用して、コマンドをサーバーに送信します。ヘルプコマンドを使用して、特定のコマンドのヘルプ情報を表示します。 QUITコマンドを使用して、コマンドラインツールを終了します。
