Redis の強化
キャッシュ使用の原則
Redis には、いつ、どのようなデータを保存できますか?
1. データ量が多すぎないこと
2. 頻繁に使用されるほど、Redis がこのデータを保存する価値が高くなります
3. Redis に保存されているデータは、通常、データベース内で頻繁に変更されることはありません。
キャッシュ削除ポリシー
Redis はデータをメモリに保存しますが、メモリの容量には制限があります。Redis サーバーのメモリがいっぱいで、今すぐ新しいデータを Redis に保存する必要がある場合、それを行う方法はキャッシュの削除戦略です。
- noeviction: エラーを返します **(デフォルト)**
間違いを起こしたくない場合は、特定の条件を満たす情報を削除し、新しい情報を保存するように設定できます。
- allkeys-random: 全データからランダムにデータを削除します
- volatile-random: 有効期限のあるデータからランダムにデータを削除します
- volatile-ttl: 残り有効時間が最も短いデータを削除します。
- allkeys-lru:全データ中、現在から最終使用時間が最も長いデータを削除
- volatile-lru: 有効期限のあるデータから、最後に使用してから最も長い期間のデータを削除します
- allkeys-lfu: 全データの中で最も使用頻度の低いデータを削除します
- volatile-lfu: 有効期限を設定して最も使用頻度の低いデータを削除します
生存時間 (ttl)
最も最近使用されていない (lru)
最も使用頻度の低いもの (lfu)
キャッシュの侵入
いわゆるキャッシュペネトレーションとは、ビジネスリクエストが最初にredisにクエリを実行し、redisにはこのデータが存在せず、次にデータベースにクエリを実行しますが、データベースにもデータが存在しないことを意味します。
通常のビジネス状況では、リクエストでデータをクエリした後、そのデータをRedisに保存し、以降のリクエストはデータベースに接続せずにRedisから直接クエリを実行できますが、上記のペネトレーション現象が発生すると、引き続きデータベースに接続する必要があり、データベースに接続すると、プロジェクト全体の効率に影響を及ぼします。悪意のあるリクエストや、データベースに存在しないデータへの同時アクセスが多い場合、深刻な場合には、現在のサーバーがダウンする可能性があります。
業界の主流ソリューション: ブルーム フィルター。
ブルームフィルターの使い方
1. 既存のすべてのデータに対してブルーム フィルターを生成し、Redis に保存します。
2. ビジネス ロジック層で、Redis を判断する前に、ID がブルーム フィルターに含まれているかどうかを確認します。
3. ブルーム フィルタが ID が存在しないと判断した場合は、ID を直接返します。
4. ブルームフィルタによりidが存在すると判断された場合、以降の業務実行を行う。
キャッシュの内訳
Redis にデータを保存する計画、ビジネス クエリ、クエリされたデータは Redis に存在せず、データベースに存在します。この場合、データベースからクエリを実行してから Redis に保存する必要があります。
キャッシュ シュートスルー自体は致命的な問題ではなく、許容できない現象でもありません。
キャッシュ雪崩
前述したように、少量の故障が同時に発生するのが通常ですが、多数の故障が同時に発生した場合は次のようになります。
いわゆるキャッシュ雪崩とは、Redis に保存されているデータのことで、短期間に大量のデータが同時に期限切れになり、上図のように Redis からフィードバックされるべき情報が、Avalanche が Mysql を訪問したために Mysql が耐えられず、例外が発生する可能性があります。これを回避するには、同時に多数のキャッシュが無効になることを避ける必要があります。
多数のキャッシュが同時に無効化される理由:通常、同時にロードされたデータに同じ有効期間が設定されていることが原因です。
有効期間を設定する際に乱数を付加することで、大量のデータが同時に無効になることを防ぐことができます。
Redis の永続性
Redis は情報をメモリに保存します。メモリの特性は、電源を切るとすべての情報が失われることです。Redis の場合、すべてのデータが失われ、再ロードされた後、データベースからすべてのデータを再クエリする必要があります。この操作は時間がかかるだけでなく、データベースに多大な負荷をかけます。
さらに、一部の企業では、データは最初に Redis に保存され、その後一定間隔でデータベースと同期されます。Redis の電源がオフになると、この期間のデータは完全に失われます。Redis の再起動によってデータベースにさらなる負荷がかかり、データが失われるのを防ぐために、Redis は永続化機能をサポートしています。
いわゆる永続化とは、Redis に保存されているデータを指定された方法で現在の Redis サーバーのハードディスクに保存することです。ハードディスク上に存在していれば、電源を切ってもデータが失われることはなく、Redisを再起動した際にハードディスク内の情報を使ってデータが復元されます。
Redis が永続性を実現するには 2 つの戦略があります。
RDB:(Redisデータベースバックアップ)
RDB は本質的にデータベースのスナップショットです (つまり、Redis 内のすべてのデータは現在バイナリ オブジェクトに変換され、ハード ディスクに保存されています)。デフォルトでは、各バックアップで dump.rdb ファイルが生成されます。Redis の電源がオフまたはダウンしている場合、再起動すると、このファイルからデータが復元され、dump.rdb のすべての内容が取得されます。この効果を実現するには、Redis 構成ファイルに次の情報を追加します。
save 60 5
上記の構成では、60 は秒を意味し、5 は Redis キーが変更された回数を意味します。
構成の影響: 1 分以内に 5 つを超えるキーが変更されると、rdb データベース スナップショット プログラムが開始されます。
アドバンテージ:
- Redis データ全体のバイナリ形式であるため、データの回復は全体として実行されます。
欠点:
- 生成されたrdbファイルはハードディスク上にあるファイルのため、読み書き効率が悪く、
- 突然の停電が発生した場合、最後に生成された rdb 内のデータのみを復元できます。
AOF(追加専用ファイル):
AOF 戦略は、Redis が実行したすべてのコマンド (ログ) をバックアップし、ハードディスクに保存することで、Redis の電源がオフになっても、実行されたログに基づいて電源障害前の状態に復元できます。次の構成情報を Redis 構成ファイルに追加できます。
appendonly yes
この設定を行うと、実行されたコマンドのログが保存されます。理論上は、実行されたすべてのコマンドを復元できますが、実際には、Redis が非常にビジーな場合、ログ コマンドをキャッシュしてバックアップに全体として送信し、IO 数を削減してバックアップのパフォーマンスと Redis のパフォーマンスへの影響を向上させます。実際の開発では、ログファイルを 1 秒に 1 回送信する構成が一般的で、電源を切ると最大 1 秒間データが失われます。
アドバンテージ:
RDBと比べて情報の損失が少ない。
欠点:
実行ログが保存されるため、かなりの容量を消費します。
実際の開発では、RDB と AOF を同時に、または選択的に有効にすることができます。
Redis の AOF は、ログ ファイルのサイズを削減するための AOF リライトをサポートしています
簡単に言えば、ログ内の無効なステートメントを削除することで、占有スペースを削減できます。
Redis ストレージの原則
ビジネス用の Java コードを作成する場合、複数の要素のコレクションから要素を検索する必要がある場合、またはキーの有無を確認する必要がある場合は、HashMap または HashSet を使用することをお勧めします。このデータ構造は内部で使用されるため、最もクエリ効率が高いからです。
"ハッシュ表"
次の図はハッシュテーブルの格納原理です。
スロットが多いほど、要素が多い場合のクエリのパフォーマンスが向上します。HashMap にはデフォルトで 16 スロットがあります。
Redis の最下位層でもこのようなハッシュ テーブル構造を使用してデータを格納します。Redis はメモリを 16384 個の領域 (ハッシュ スロットと同様) に分割し、CRC16 アルゴリズムを使用してデータのキーの値を計算し、その余りを 16384 とります。結果は 0 ~ 16383 になるため、Redis は非常に効率的に要素を検索できます。
Redis クラスター
Redis の最小状態はサーバーです。このサーバーの実行状態によって、Redis が利用可能かどうかが直接決まります。オフラインの場合、Redis はプロジェクト全体で利用できなくなり、システムがクラッシュします。これを防ぐために、バックアップ マシンを準備できます。
マスター/スレーブ レプリケーション
つまり、マスター(マスター)が稼働しているときにバックアップマシン(スレーブ)を配置し、リアルタイムでデータを同期し、マスターがダウンした場合にはバックアップマシンに切り替えて稼働させることができます。
欠点: このようなスキームでは、スレーブ ノードには実際の影響はなく、マスターがダウンしない限り何もないのと同じであり、値は反映されません。
読み取りと書き込みの分離
このようにして、マスターが正常に動作しているときは、スレーブもマスターの作業を共有できますが、マスターがダウンしている場合、実際には、マスターとスタンバイ マシン間の切り替えには依然として手動介入が必要であり、依然として時間がかかります。したがって、障害発生時に自動切り替えを実現したい場合は、固定戦略を構成する必要があります。
Sentinelモード:フェイルオーバー自動切り替え
センチネル ノードは、一定の間隔ですべてのノードにリクエストを送信します。応答が正常であれば、ノードは正常であるとみなされます。応答がない場合は、ノードに問題があるとみなされます。センチネルは、メイン マシンとスタンバイ マシンを自動的に切り替えることができます。ホストのマスターがオフラインになると、自動的にスタンバイ マシンに切り替えて動作します。
ただし、センチネルがノードの状態を判断する際に判断を誤ると、マスターを誤ってオフラインにし、全体の動作パフォーマンスが低下するため、センチネルの誤判断の可能性は低くなるはずです。
センチネルクラスター
センチネル ノードをクラスターに組み込むことができ、複数のセンチネルが特定のノードをオフラインにするかどうかを決定します。センチネル クラスターでは、各ノードがマスターとスレーブに定期的に ping リクエストを送信します。3 つ以上のセンチネル ノード (クラスター内のノードの半分) が ping リクエストに対する正常な応答を受信しない場合、そのノードはオフラインとみなされます。ビジネスが拡大し続け、同時実行数が増加し続ける場合。
シャード化されたクラスター
書き込み操作をサポートするノードが 1 つだけで全体のパフォーマンス要件を満たせない場合、システムのパフォーマンスがボトルネックに達するため、プログラム全体のパフォーマンスを向上させるために、シャーディング用の書き込み操作をサポートする複数のノードをデプロイする必要があります。
断片化とは、各ノードが異なる領域を担当することを意味します。
たとえば、Redis スロット 0 ~ 16383:
MasterA は 0 ~ 5000 を担当します
MasterB は 5001 ~ 10000 を担当します
MasterC は 10001 ~ 16383 を担当します
キーは CRC16 アルゴリズムに従って固定された結果のみを取得でき、データは指定されたサーバー上で見つかる必要があります。
このクラスタ構成により、業務リクエストをより安定かつ効率的に処理できるようになります。
Sentinel サーバーのコストを節約するために、一部の企業は Redis クラスターに Sentinel 機能を直接追加し、マスター/スレーブ ノードがデータの読み取りおよび書き込みタスクを完了しながら互いの健全性状態をチェックできるようにしています。