Redis はメモリベースの操作であるため、CPU がパフォーマンスのボトルネックになることはありません。それどころか、サーバーのメモリ使用率、ネットワーク IO、ディスクの読み取りと書き込みは、Redis のパフォーマンスに重要な役割を果たします。
したがって、ネットワーク、メモリ、ディスク、ブロッキング ポイントなどの側面からの最適化に焦点を当てます。用語が不明瞭な場合は、以前の号の Redis コンテンツを参照するか、関連情報を参照することをお勧めします。
ネットワークの最適化
クライアントがサーバーを要求する場合、つまり「要求/応答」モードで、可能な限りバッチ処理を使用して、ネットワーク IO オーバーヘッドを削減します。
バッチ処理テクノロジー: アトミックバッチ処理命令、パイプラインテクノロジー、Redis、トランザクション、Lua スクリプト。
バッチ処理によりネットワーク IO オーバーヘッドが削減されます
Atomic m バッチ処理命令: 文字列タイプの場合は、get/set の代わりに mget/mset を使用することをお勧めします; ハッシュタイプの場合は、hget/hset の代わりに hmget/hmset を使用することをお勧めします。
pipline テクノロジー: パイプライン テクノロジーは、list、set、zset を使用するときにバッチ操作がある場合に使用できます。
redis トランザクション: 特別なビジネス要件により複数の命令が保証される場合に推奨されます。
lua スクリプト: 分散ロック解除、フラッシュセール、在庫削減など、複数の命令のアトミック性を確保する必要がある場合は、lua スクリプトの使用をお勧めします。
ノード間ネットワークの最適化
同じ LAN 内にクラスターを構築します;
クラスターを分割するノードの数を制御します。Redis インスタンスに割り当てられたハッシュ スロットは、異なるインスタンス間で転送する必要があります。負債分散インスタンスが削除されると、データは異なるインスタンス間で転送されます。ただし、ハッシュ スロット情報は大きくなく、データの移行は段階的に行われますが、主な問題ではありません。
メモリの最適化
キーの長さを制御する: キーがシンプルかつ明確であることを保証するために、開発前に仕様を定義し、ビジネスに応じてキーを可能な限り短縮することをお勧めします。
bigkey を避ける: 文字列型の推奨サイズは 20KB 以内です。 hash、list、set、zsetの閾値を5000以内に制御することを推奨します。
キー設定の有効期限が切れます: メモリを最大限に活用してください。
適切なデータ構造を選択してください
文字列型。整数型を使用することをお勧めします。その基礎となるエンコーディングでは、メモリ オーバーヘッドが低い整数エンコーディングが選択されます。
ハッシュ タイプの場合、要素のしきい値を制御することをお勧めします。要素が少ない場合、最下層はメモリ オーバーヘッドが小さい圧縮リスト データ構造を使用します。リスト タイプの場合、要素のしきい値を制御することをお勧めします。要素が少ない場合、最下層はメモリ オーバーヘッドが小さい圧縮リスト データ構造を使用します。セット タイプ、整数型を格納することをお勧めします。基になるエンコーディングは、メモリ オーバーヘッドが低い整数エンコーディングを選択します。
zset タイプでは、要素のしきい値を制御することをお勧めします。要素が少ない場合、最下層はメモリ オーバーヘッドが低い圧縮リスト データ構造を使用します。
データ圧縮: クライアントは、メモリ使用量を削減するために、Redis に書き込む前に、snappy、gzip、およびその他の圧縮アルゴリズムを使用してデータを圧縮できますが、クライアントはデータを読み取った後にデータを解凍する必要があるため、より多くの CPU を消費します。
メモリ排除戦略を有効にする
デフォルトのメモリ削除戦略を避けてください。メモリ使用率を向上させるために、実際のビジネスに基づいて適切なメモリ削除戦略を選択してください。
LRU: アクセス数を重視し、最も最近使用されていないキーを削除し、幅広い使用シナリオを用意します。 Redis の LRU は、LRU と同様のアルゴリズムを使用し、最終アクセスのタイムスタンプである 24 ビット長の追加フィールドをキーに追加します。遅延処理方法を採用し、書き込み操作を実行するときに最大メモリを超えた場合、LRU 削除アルゴリズムを 1 回実行し、5 つのキー (数は設定可能) をランダムにサンプリングし、最も古いキーを削除します。削除後も最大メモリを超えているため、削除は続行されます。
LFU: アクセス頻度に焦点を当て、キャッシュ汚染に対処する場合に推奨されます。
メモリ断片化最適化問題
理由: 1 つは、メモリ アロケータの割り当て戦略によって引き起こされます。メモリ アロケータは、実際に要求されたサイズではなく、固定サイズに従って割り当てます。要求されたバイトが要求されたバイト数内にある場合、実際には 32 バイトが割り当てられます。割り当てられたもの、もう 1 つは、redis のキーと値のペアが削除された後に解放される領域の一部によって引き起こされるメモリの断片化です。
位置付け: 命令 INFO メモリを通じて men_fragmentation_ratio のインジケーターを観察します。インジケーターが 1 ~ 1.5 の場合は正常です。インジケーターが 1.5 より大きい場合は、メモリの断片化率が 50% を超えており、メモリの断片化が必要です。処理対象;
解決策: Redis インスタンスを再起動します;
Redis の自動メモリ断片化クリーニング機能を有効にします。
ディスクの最適化
redis サービスを物理的に構築する: 永続化する場合、redis はサブプロセス (オペレーティング システムのフォーク システムを呼び出す) を作成する方法を使用します。仮想マシン環境でのフォークの実行は、仮想マシン環境でのフォークの実行よりも遅くなります。物理マシン。
永続性最適化メカニズム
永続性を有効にしないでください: Redis はキャッシュにのみ使用されるため、ディスクのオーバーヘッドを削減するために永続性を有効にする必要はありません。
AOF 最適化: AOF をバックグラウンドで処理し、データ永続化フラッシュ操作をバックグラウンド スレッドで実行するように apenfsync Everyec を構成し、ディスクへの Redis 書き込みによるパフォーマンスへの影響を軽減します。
高頻度の AOF 永続性を構築しないでください。AOF 永続性のデフォルトの頻度は 1 秒に 1 回です。この構成を変更することはお勧めできません。データが最大 1 秒間失われることがすでに保証されています。
ハイブリッド永続性を有効にする、redis4.0 はハイブリッド永続性 RDB インクリメンタル AOF をサポートします;
マルチスレッド構成を有効にします。redis 6.0 より前では、永続性はメイン スレッドのフォーク サブプロセスを通じて処理されていましたが、フォークは同期的にブロックされていました。6.0 以降では、永続性操作を処理するために複数のプロセスがサポートされています;
クラスターの最適化
スレーブは永続性の最適化を実行します: マスターは永続性を実行せず、マスター ディスク IO の圧力を可能な限り共有します。マスター/スレーブの最適化: インクリメンタル モード、マスター/スレーブの同期方法はインクリメンタル モードとして指定され、完全なRDB モードは選択されません。このモードはパフォーマンスを非常に消費します。1 つのマスターと複数のスレーブでカスケード同期モードを使用する場合、複数のスレーブがデータを同期するためにマスターにアクセスするため、マスターのパフォーマンスが直接低下します。
この問題に関して、redis はカスケード同期をサポートしています。つまり、マスターはデータを 1 つのスレーブにのみ同期し、その後、マスターへの負担を軽減するために他のスレーブのデータがこのスレーブから同期されます。
実際のサイズは 6G を超えないようにすることをお勧めします。インスタンスが大きすぎると、マスターとスレーブの同期が停止し、深刻な場合にはマスターがダウンしてしまいます。
異常な再起動中にAOF が再生されます。インスタンスが大きすぎると、データの回復が異常に遅くなります。
チョークポイントの最適化
分析: Redis はリクエストと命令を処理するときにシングルスレッドであるため、そのパフォーマンスのボトルネックは同期ブロックの問題です。
重要な質問
危険: bigkey の読み取りと書き込みによりタイムアウトが発生する可能性があり、redis は単一スレッドでデータを操作するため、redis サービス全体が深刻にブロックされる可能性があります。また、キーは 1 つのノードにのみ分割されるため、スケッチの圧力を共有することはできません。 Bigkey 検出: コマンド bredis-cli-bigkeys に付属しています。 Redis には 5 つのデータ型の中で最大のキーのみを検索する命令が付属していますが、これはあまり役に立たず、推奨されません。 Pythonのスキャンスクリプト。特定のキーを見つけることはできますが、精度は高くないため、お勧めできません。
rdb_bigkeys ツール。 Go で書かれたツールなので高速かつ高精度で、CSV ファイルに直接エクスポートして簡単に閲覧したり、推奨したりすることもできます。
最適化: 非文字列タイプの bigkey の場合、要素セットは複数に分割できます。たとえば、bigkey が 1000 個のキーに分割される場合、キーのサフィックスはハッシュ モジュロ 1000 を使用します。
ローカル キャッシュを使用します。たとえば、ビジネス ID のバージョン番号を Redis に保存します。特定のコンテンツをローカル キャッシュに置きます。クエリごとに最初に Redis キャッシュを確認し、次にローカル キャッシュでバージョン番号を確認します。
bigkey の最適化は一般的に面倒なプロセスです。bigkey の問題を回避するために、開発中に仕様を定義することをお勧めします。
有効期限ポリシー
スケジュールされた削除: 期限切れの各キーにはスケジュールされたジョブが与えられ、期限切れになると直接削除されますが、メモリ使用率と CPU 使用率が高くなります。遅延削除: キーのクエリ時にキーの有効期限が切れているかどうかが判断され、期限切れの場合は削除されるため、CPU 使用率が低くなり、メモリ使用率が高くなります。定期的な削除: 時々スキャンし、期限切れのキーは直接削除され、CPU とメモリの使用率は平均的です。
1. 貪欲な戦略。 Redis は、期限切れのキーを別の辞書に設定します。
2. スキャンプロセス。期限切れの辞書から 20 個のキーを選択し、20 個のキーのうち期限切れのキーを削除します。削除されたキーの割合が 1/4 を超える場合は、手順 1 を繰り返します。
上記のロジックに基づいて、過剰なループによって引き起こされるスレッドのスタックの問題を解決するために、アルゴリズムにタイムアウト メカニズムが追加されます (デフォルト時間は 25ms)。
3. スキャン頻度: Redis のデフォルトの有効期限スキャンは 1 秒あたり 10 回です。
Redis のデフォルトでは、遅延削除と定期的な削除が行われます。
最適化: レイジーフリーをオンにすると、メモリ解放という時間のかかる操作が、redis4.0 でサポートされるバックグラウンド スレッドで実行されます。
マルチスレッド モードを有効にする。redis6.0 より前では、有効期限ポリシーはメイン スレッドの同期操作でしたが、6.0 以降はマルチスレッドが処理に使用されます。
複雑性の高い命令
バッチでクエリを実行するにはスキャンを使用し、キーは使用しないことをお勧めします。集約操作には適用されません: redis はシングルスレッド モデルを使用してリクエストを処理します。複雑すぎるコマンドを実行すると (より多くの CPU リソースを消費する)、後続のリクエストはキューに入れられ、遅延が発生します (SINTER、SINTERSTORW、ZUNIONSTORE、ZINTERSTORE、等スキャンを使用してコレクション内の要素をバッチで検索し、クライアントで集計計算を実行することをお勧めします。
コンテナクラスのデータ操作: コンテナクラスの要素が多すぎる場合、直接クエリするとネットワークの影響で遅延が発生するため、バッチでクエリすることを推奨します。
コンテナ要素が多すぎる場合、キーを直接削除するとredisがフリーズする可能性があるため、一括で削除することをお勧めします。
以上がRedis 最適化ガイド: ネットワーク、メモリ、ディスク、ブロッキング ポイントの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。