メモリがいっぱいになったときに Redis を最適化する方法の詳細な分析

WBOY
リリース: 2022-03-14 17:09:27
転載
3483 人が閲覧しました

この記事では、Redis に関する関連知識を提供し、メモリがいっぱいになったときに Redis を最適化する方法に関する関連問題を主に紹介し、削除メカニズム、LRU アルゴリズム、削除の処理についても説明します。 , 皆様のお役に立てれば幸いです。

メモリがいっぱいになったときに Redis を最適化する方法の詳細な分析

推奨学習: Redis 学習チュートリアル

Redis メモリがいっぱいの場合はどうすればよいですか?メモリを最適化するにはどうすればよいですか?

MySQL には 2,000 万のデータがあり、redis には 200,000 のデータのみが保存されます。redis のデータがホット データであることを確認する方法

Redis メモリ データ セットのサイズが増加した場合一定のサイズに達すると、データ削除戦略が実装されます。

Redis は主にどのような物理リソースを消費しますか? ######メモリ。

Redis のメモリが不足するとどうなりますか?

設定された上限に達すると、Redis 書き込みコマンドはエラー メッセージを返します (ただし、読み取りコマンドは正常に戻ることができます)。または、メモリ削除メカニズムを構成して、Redis が上限メモリに達したときに設定することもできます。制限を超えると、古いコンテンツはフラッシュされます。

キャッシュされたデータの削除メカニズムについて話す

Redis キャッシュの削除戦略とは何ですか?

データを削除しない唯一の戦略は、noeviction です。
  • 消去法には 7 つの戦略があり、消去候補データセットの範囲に応じてさらに 2 つのカテゴリに分類できます。消去法には、volatile-random、volatile-ttl、volatile-lru、volatile-lfu の 4 種類があります。

allkeys-lru、allkeys-random、allkeys-lfu を含むすべてのデータ範囲で削除します。

  • #ポリシー
ルール##volatile-ttlフィルタリングの際、有効期限が設定されているキーと値のペアは有効期限が早い順に削除されます。 volatile-random 有効期限が設定されたキーと値のペアをランダムに削除します。 volatile-lruLRU アルゴリズムを使用して、有効期限を指定してキーと値のペアをフィルター処理しますvolatile-lfu LFU アルゴリズムを使用して有効期限が設定されたキーと値のペアを選択するルール
##戦略
## allkeys -lruLRU アルゴリズムを使用してすべてのデータをフィルター処理しますvalkeys-lfuLFU アルゴリズムを使用してすべてのデータをフィルター処理します
allkeys-random すべてのキーと値のペアからデータをランダムに選択して削除します。
#

LRU アルゴリズムについて話します

は、最も最近使用されていない原則に従ってデータをフィルタリングすることです。最も頻繁に使用されていないデータは除外されますが、最近頻繁に使用されたデータはキャッシュに残ります。

正確にはどのように審査されますか? LRU はすべてのデータをリンク リストに編成します。リンク リストの先頭と末尾はそれぞれ MRU の端と LRU の端を表し、最も最近使用されたデータと最も最近使用されなかったデータを表します。
メモリがいっぱいになったときに Redis を最適化する方法の詳細な分析
LRU アルゴリズムの背後にある考え方は非常に単純です。LRU アルゴリズムは、アクセスされたばかりのデータは必ず再びアクセスされると考えているため、アクセスされていないデータを MRU 側に配置します。長い間アクセスされることは絶対にありません、またアクセスされるので徐々にLRU側に戻していきます、キャッシュがいっぱいになったら一旦削除してください。

問題: LRUアルゴリズムを実際に実装する場合、リンクされたリストを使用してすべてのキャッシュされたデータを管理する必要があり、追加のスペースオーバーヘッドが発生します。さらに、データにアクセスすると、データをリンク リストの MRU に移動する必要があり、大量のデータにアクセスするとリンク リストの移動操作が多数発生し、非常に時間がかかり、Redis キャッシュのパフォーマンスが低下します。 。

解決策:
Redisでは、LRUアルゴリズムが簡素化され、キャッシュのパフォーマンスに対するデータの削除の影響が軽減されました。具体的には、Redis はデフォルトで各データの最新のアクセス タイムスタンプを記録します (キーと値のペアのデータ構造 RedisObject の lru フィールドによって記録されます)。そして、Redis は除外するデータを決定するときに、初めて N 個のデータをランダムに選択し、候補セットとして使用します。次に、Redis はこれらの N データの lru フィールドを比較し、lru フィールド値が最小のデータをキャッシュから削除します。
データを再度削除する必要がある場合、Redis は最初の削除時に作成された候補セットにデータを選択する必要があります。ここでの選択基準は、候補セットに入力できるデータの lru フィールド値が、候補セット内の最小の lru 値より小さくなければならないということです。新しいデータが候補データ セットに入ったとき、候補データ セット内のデータ数が maxmemory-samples に達すると、Redis は候補データ セット内の lru フィールド値が最小のデータを削除します。

使用上の推奨事項:

  • 最初に allkeys-lru ポリシーを使用します。このようにして、古典的なキャッシュ アルゴリズムである LRU の利点を最大限に活用して、最近アクセスされたデータをキャッシュに保持し、アプリケーションのアクセス パフォーマンスを向上させることができます。ビジネス データ内にホット データとコールド データが明確に区別されている場合は、allkeys-lru 戦略を使用することをお勧めします。
  • ビジネス アプリケーションのデータ アクセス頻度に大きな違いがなく、ホット データとコールド データの明確な区別がない場合は、allkeys-random 戦略を使用して、削除されたデータをランダムに選択することをお勧めします。
  • ビジネスで固定ニュースや固定ビデオなどの固定データが必要な場合は、volatile-lru 戦略を使用して、これらの固定データの有効期限を設定しないことができます。このようにして、固定する必要があるデータは削除されることはなく、他のデータは有効期限が切れたときに LRU ルールに従ってフィルタリングされます。

削除されたデータにどう対処するか?

削除されたデータが選択されたら、そのデータがクリーン データの場合は直接削除しますが、ダーティ データの場合はデータベースに書き戻す必要があります。

では、データがクリーンかダーティかを判断するにはどうすればよいでしょうか?

  • クリーン データとダーティ データの違いは、バックエンド データベースから最初に読み取られた値と比較して変更されているかどうかにあります。クリーンなデータは変更されていないため、バックエンド データベース内のデータも最新の値です。置き換える場合は直接削除できます。
  • ダーティ データとは、変更され、バックエンド データベースに保存されているデータと一致しなくなったデータを指します。このとき、ダーティ データをデータベースに書き戻さないと、このデータの最新の値が失われ、アプリケーションの通常の使用に影響します。

削除されたデータがダーティ データであっても、Redis はそれらをデータベースに書き戻しません。したがって、Redis キャッシュを使用する場合、データが変更された場合は、データが変更されたときにデータベースに書き戻す必要があります。そうしないと、ダーティ データが削除されるときに Redis によって削除され、データベースには最新のデータがなくなります。

Redis はどのようにメモリを最適化しますか?

1. キーの数を制御する: Redis を使用して大量のデータを保存する場合、通常は多数のキーがあり、キーが多すぎると大量のメモリも消費します。 Redis は本質的にデータ構造サーバーであり、ハッシュ、リスト、セット、zset、その他の構造などのさまざまなデータ構造を提供します。 Redis を使用する際に誤解しないように、get/set などの API を多用し、Redis を Memcached として使用します。同じデータ内容を保存する場合、Redis データ構造を使用して外部キーの数を減らすと、メモリを大幅に節約できます。
2. キーと値のオブジェクトを減らす: Redis のメモリ使用量を減らす最も直接的な方法は、キー (キー) と値 (値) の長さを減らすことです。

  • キーの長さ: キーを設計するとき、ビジネスが完全に説明されている場合、キーの値は短いほど良いです。
  • 値の長さ: 値オブジェクトの削減はより複雑で、一般的な要件は、ビジネス オブジェクトをバイナリ配列にシリアル化し、Redis に配置することです。まず、ビジネス オブジェクトを合理化し、無効なデータの保存を避けるために不要な属性を削除する必要があります。次に、シリアル化ツールの選択に関して、バイト配列サイズを削減するには、より効率的なシリアル化ツールを選択する必要があります。

3. コーディングの最適化。 Redis は、string、list、hash、set、zet などの外部型を提供しますが、Redis にはさまざまな型のエンコーディングの概念が内部的にあり、いわゆるエンコーディングは、実装に使用される特定の基礎となるデータ構造を指します。エンコーディングの違いは、メモリ使用量とデータの読み取りおよび書き込み効率に直接影響します。


    #1. redisObject オブジェクト

  • メモリがいっぱいになったときに Redis を最適化する方法の詳細な分析
##type フィールド

:コレクション型データを使用します
、通常、多くの小さな Key-Value をよりコンパクトな方法でまとめて保存できるためです。可能な限りハッシュを使用する ハッシュ テーブル (ハッシュ テーブルに格納される数値が小さいことを意味します) は非常に少量のメモリを使用するため、データ モデルを可能な限りハッシュ テーブルに抽象化する必要があります。たとえば、Web システムにユーザー オブジェクトがある場合、ユーザーの名前、姓、電子メール、パスワードに個別のキーを設定せず、すべてのユーザー情報をハッシュ テーブルに保存します。

encoding フィールド

:異なるエンコーディングを使用すると、メモリ使用量に明らかな違いがあります

lru フィールド

:開発のヒント: scan object idletime コマンドを使用すると、長期間アクセスされていないキーをバッチでクエリし、長期間アクセスされていないキーを見つけて、それらをクリーンアップしてメモリを削減できます。使用法。

refcount フィールド

:オブジェクトが整数で範囲が [0-9999] の場合、Redis は共有オブジェクトを使用してメモリを節約できます。

ptr フィールド

:開発のヒント: 同時書き込みが多いシナリオでは、条件が許せば文字列の長さを 39 バイト以内に制御することをお勧めします。 redisObject を作成するためのメモリ割り当ての数を減らし、パフォーマンスを向上させます。


#2. キーと値のオブジェクトを減らす
    Redis のメモリ使用量を減らす最も直接的な方法は、キーと値の長さを減らすことです。

  • 一般的な圧縮アルゴリズムを使用して、json と xml を Redis に保存する前に圧縮することで、メモリ使用量を削減できます

#3. 共有オブジェクト プール
    オブジェクト共有プールは、Redis によって内部的に維持される整数のオブジェクト プール [0-9999] を指します。整数型の redisObject を多数作成するとメモリ オーバーヘッドが発生し、各 redisObject 内部構造は少なくとも 16 バイトを占有し、整数自体のスペース消費量を超えます。したがって、Redis メモリはメモリを節約するために整数オブジェクト プール [0 ~ 9999] を維持します。整数値オブジェクトに加えて、list、hash、set、zset 内部要素などの他の型でも整数オブジェクト プールを使用できます。
  • したがって、開発ではニーズを満たすことを前提として、メモリを節約するために整数オブジェクトを使用するようにしてください。
    maxmemory が設定され、volatile-lru、allkeys-lru などの LRU 関連の削除戦略が有効になっている場合、Redis は共有オブジェクト プールの使用を禁止します。
maxmemory と LRU 排除戦略を有効にした後、オブジェクト プールが無効になるのはなぜですか?

LRU アルゴリズムは、オブジェクト プールを排除するために、オブジェクトの最終アクセス時刻を取得する必要があります。最も長くアクセスされていないデータ。オブジェクトの最終アクセス時刻は、redisObject オブジェクトの lru フィールドに保存されます。オブジェクトの共有とは、複数の参照が同じ redisObject を共有することを意味しますが、このとき lru フィールドも共有されるため、各オブジェクトの最終アクセス時刻を取得することができなくなります。 maxmemory が設定されていない場合、Redis はメモリが使い果たされるまでメモリのリサイクルをトリガーしないため、共有オブジェクト プールは正常に動作できます。 要約すると、共有オブジェクト プールは maxmemory LRU 戦略と競合するため、使用する場合は注意する必要があります。

整数オブジェクト プールしかないのはなぜですか?

まず第一に、整数オブジェクト プールは再利用の可能性が最も高くなります。第二に、オブジェクト共有の重要な操作は同等性を判断することです。Redis に整数オブジェクト プールしかない理由は、整数オブジェクト プールの時間計算量が高いためです。整数比較アルゴリズムは O(1) です。オブジェクト プールの無駄を防ぐために、10,000 個の整数のみを保持します。文字列の等しいかどうかを判断する場合、時間計算量は O(n) になり、特に長い文字列の場合、より多くのパフォーマンスが消費されます (浮動小数点数は文字列を使用して Redis の内部に格納されます)。ハッシュ、リストなどのより複雑なデータ構造の場合、同等性の判定には O(n2) が必要です。シングルスレッド Redis の場合、このようなオーバーヘッドは明らかに不当であるため、Redis は整数の共有オブジェクト プールのみを保持します。


4. 文字列の最適化
    Redis はネイティブ C 言語の文字列型を使用せず、SDS と呼ばれる内部の単純な動的文字列を使用した独自の文字列構造を実装します。

文字列構造

:

特徴:
    O(1) 時間計算量の取得: 文字列長、使用長、未使用長。
  • バイト配列の保存に使用でき、安全なバイナリ データ ストレージをサポートします。
    メモリの再割り当ての回数を減らすために、スペースの事前割り当てメカニズムを内部的に実装します。
    遅延削除メカニズム。文字列削減後のスペースは解放されず、事前に割り当てられたスペースとして予約されます。

事前割り当てメカニズム

:

  • 開発のヒント: append や setrange などの頻繁な文字列変更操作を減らし、代わりに set を直接使用して文字列を変更し、事前割り当てによるメモリの無駄やメモリの断片化を軽減するようにしてください。

文字列再構築: ハッシュ タイプに基づく 2 次エンコード方式。

  • セカンダリ エンコーディングを使用するにはどうすればよいですか?
    二次エンコード方式で使用される ID の長さは特殊です。
    問題が発生します。ハッシュ型の基礎となる構造が設定値より小さい場合は圧縮リストが使用され、設定値より大きい場合はハッシュ テーブルが使用されます。
    圧縮リストからハッシュ テーブルに変換されると、ハッシュ タイプは常にハッシュ テーブルに保存され、圧縮リストに逆変換されることはありません。
    メモリ領域の節約という点では、ハッシュ テーブルは圧縮リストほど効率的ではありません。圧縮リストのコンパクトなメモリ レイアウトを最大限に活用するには、一般に、ハッシュに格納される要素の数を制御する必要があります。

  • 5. エンコーディングの最適化
    圧縮リスト ziplist を使用してエンコードされたハッシュ タイプは、ハッシュテーブルを使用してエンコードされたセットよりも多くのメモリを節約します。

  • #6. キーの数を制御する
    開発のヒント: ziplist ハッシュを使用してキーを最適化した後、タイムアウトを使用したい場合は、削除機能を使用すると、開発者は各オブジェクトの書き込み時間を保存し、hscan コマンドを使用してスケジュールされたタスクを通じてデータをスキャンし、ハッシュ内でタイムアウトになったデータ項目を見つけて削除できます。

Redis のメモリが不足した場合、最初に考慮すべきことは、水平方向の拡張のためにマシンを追加しないことです。まずメモリの最適化を試みる必要があります。ボトルネックに遭遇した場合は、水平方向の拡張を検討してください。クラスタリング ソリューションの場合でも、クラスタリング後のリソースと管理コストの不必要な浪費を避けるために、垂直レベルの最適化が同様に重要です。

推奨される学習: Redis チュートリアル

以上がメモリがいっぱいになったときに Redis を最適化する方法の詳細な分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:csdn.net
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート