目次
3.1.4 キャッシュブレークダウンソリューションにおけるミューテックスの詳細説明
3.2.4 キャッシュペネトレーションソリューションのブルームフィルターの詳細説明
3.3.4 キャッシュアバランシェソリューションにおけるロックと電流制限の詳細な説明
Redis の概要
Redis (英語の正式名は Remote Dictionary Server (リモート辞書サービス)) は、ANSI C 言語で書かれたオープン ソースで、ネットワークをサポートし、メモリまたは永続的なログ タイプ、Key-Value データベースに基づいて、複数の API を提供します。言語。
memcached と同様に、データは効率を確保するためにメモリにキャッシュされます。違いは、redis が定期的に更新されたデータをディスクに書き込むか、追加のレコード ファイルに変更操作を書き込むことであり、これに基づいてマスターとスレーブ (マスターとスレーブ) の同期が実現されます。
MySQL データベースとは異なり、Redis データはメモリに保存されます。読み取りおよび書き込み速度は非常に速く、1 秒あたり 100,000 回を超える読み取りおよび書き込み操作を処理できます。したがって、Redis はキャッシュに広く使用されており、さらに分散ロックとしてもよく使用されます。さらに、Redis はトランザクション、永続性、LUA スクリプト、LRU 駆動のイベント、および複数のクラスター ソリューションをサポートします。
Redis は、高性能のキーと値のデータベースです。Redis の登場により、memcached などのキー/値ストレージの不足が大幅に補われ、場合によってはリレーショナル データベースで非常に優れた補完的な役割を果たすことができます。
Redis はマスター/スレーブ同期をサポートしています。データはマスター サーバーから任意の数のスレーブ サーバーに同期でき、スレーブ サーバーは他のスレーブ サーバーに関連付けられたマスター サーバーになることもできます。
1. Redis クラスターモデル
サービス開発では、単一のマシンでは単一障害点の問題が発生し、サービスはサーバー上にデプロイされますが、サーバーがダウンするとサービスが利用できなくなるため、サービスの可用性を高めるために、分散型サービスが必要になります。同じサービスを複数のマシンに展開すると、複数のサーバーがダウンした場合でも、1 台のサーバーが利用可能であればサービスを利用できます。
Redisも同様で、スタンドアロン障害を解決するためにマスタースレーブモードが導入されていますが、マスタースレーブモードではマスターノード障害発生後、手動でサービスを切り替える必要があるという問題があります。サービスが復元される前に、スレーブ ノードからマスター ノードに転送されます。この問題を解決するために、redis は Sentinel モードを導入し、マスター ノードに障害が発生した後にスレーブ ノードを自動的にマスター ノードに昇格させ、手動介入なしでサービスを復元できます。
しかし、マスタースレーブモードでもセンチネルモードでもリアルデータシャーディングストレージは実現しておらず、各redisインスタンスが全量のデータを格納するため、リアルデータシャーディングストレージを実現するredisクラスターが誕生しました。ただし、redis クラスターのリリースが比較的遅かったため (正式バージョンは 2015 年にリリースされました)、大手メーカーは待ちきれず、Twemproxy、Codis などの独自の Redis データ断片化クラスター モデルを次々と開発しました。
1.1. マスタースレーブモード
Redis 単一ノードは、RDB および AOF 永続化メカニズムを通じてデータをハードディスクに永続化できますが、データはサーバーに保存され、サーバーにハードディスク障害などの問題が発生した場合、データは利用できなくなり、読み取ることができなくなります。分離、読み取り、書き込みがすべて同じサーバー上で行われるため、リクエスト量が多い場合には I/O ボトルネックが発生します。
単一障害点や読み取りと書き込みの非分離を回避するために、Redis はマスター データベースのデータが更新された後、更新されたデータが他のスレーブ データベースに自動的に同期されることを実現するレプリケーション機能を提供します。
上記の redis のマスター/スレーブ構造の特徴: マスターは複数のスレーブ ノードを持つことができ、スレーブ ノードはスレーブ ノードを持つことができ、スレーブ ノードはカスケード構造になります。
1.1.1 マスタースレーブモードの長所と短所
-
利点: マスター/スレーブ構造には、読み取りと書き込みの分離、効率の向上、データのバックアップ、および複数のコピーという利点があります。
-
短所: 最大の短所は、マスター/スレーブ モードには自動フォールト トレランスおよび回復機能がないことです。マスター ノードに障害が発生すると、クラスターは動作できなくなり、可用性が比較的低くなります。スレーブ ノードを次の状態にアップグレードするには手動介入が必要です。マスターノード。
通常のマスター/スレーブ モードでは、マスター データベースがクラッシュした場合、スレーブ データベースを手動で切り替えてマスター データベースにする必要があります。
-
スレーブ データベースのコマンドを使用して
SLAVE NO ONE
、スレーブ データベースをマスター データに昇格させ、サービスを継続します。 -
以前にクラッシュしたマスター データベースを起動し、SLAVEOF コマンドを使用してそれを新しいマスター データベースのスレーブ データベースとして設定し、データを同期します。
1.2. セントリーモード
最初のマスター/スレーブ同期/レプリケーション モードでは、マスター サーバーがダウンしている場合、スレーブ サーバーをマスター サーバーに手動で切り替える必要があります。これには手動による介入が必要で、手間がかかり、サービスが利用できなくなります。そこでセントリーモードの出番です。
Sentinel モードは Redis バージョン 2.6 から提供されましたが、当時このバージョンのモードは不安定であり、Redis バージョン 2.8 までセンチネル モードは安定しませんでした。
センチネル モードの中核は依然としてマスター/スレーブ レプリケーションですが、マスター/スレーブ モードと比較すると、マスター ノードがダウンして書き込みできない場合、追加の選出メカニズムがあります。つまり、新しいマスター ノードがすべてのスレーブ ノードから選出されます。 。選出メカニズムの実装は、システム内のセンチネル プロセスの開始に依存します。
上図に示すように、Sentry 自体に単一障害点の問題があるため、1 つのマスターと複数のスレーブを持つ Redis システムでは、複数の Sentinel を監視に使用できます。Sentinel はマスター データベースとスレーブ データベースを監視するだけでなく、お互いも監視し合う。各センチネルは独立したプロセスであり、プロセスとしては独立して実行されます。
1.2.1 センチネル モードの役割:
すべてのサーバーが正常に実行されているかどうかを監視します。監視サーバーの実行ステータスを返すコマンドを送信し、マスター サーバー、スレーブ サーバー、センチネルを処理および監視し、相互監視も行います。
フェイルオーバー: センチネルはマスターがダウンしていることを検出すると、自動的にスレーブをマスターに切り替え、パブリッシュ/サブスクライブ モードを通じて他のスレーブ サーバーに通知し、設定ファイルを変更してマスターに切り替えます。同時に、問題のある古いマスターも新しいマスターのスレーブになります。つまり、古いマスターが復元されたとしても、元のマスターの状態には戻りませんが、新しいマスターのスレーブになります。 。
1.2.2 セントリーの実装原則
Sentinel はプロセスを開始すると、構成ファイルの内容を読み取り、次の構成を通じて監視対象のメイン データベースを見つけます。
sentinel monitor master-name ip port quorum
#master-name是主数据库的名字
#ip和port 是当前主数据库地址和端口号
#quorum表示在执行故障切换操作前,需要多少哨兵节点同意。
ここでマスターノードのみ接続する必要があるのは、マスターノードのinfoコマンドを使用してスレーブノードの情報を取得することでスレーブノードとの接続を確立し、同時に新たなノードの情報を知ることができるためです。マスターノードの情報情報を通じてスレーブノードを追加しました。
センチネル ノードは複数のマスター ノードを監視できますが、センチネル ノードがクラッシュすると複数のクラスターのスイッチオーバーが同時に失敗するため、これはお勧めできません。Sentinel が起動すると、メイン データベースに対して 2 つの接続が確立されます。
-
マスター データベース
_sentinel_:hello
チャネルにサブスクライブして、そのデータベースも監視するセンチネルに関する情報を取得します。 -
定期的に info コマンドを master データベースに送信して、master データベース自体に関する情報を取得します。
メイン データベースとの接続を確立した後、次の 3 つの操作が定期的に実行されます。
(1) 10 秒ごとに情報コマンドをマスターとスレーブに送信します。現在のデータベース情報を取得する機能で、例えば新たなスレーブノードが見つかった場合には接続を確立して監視リストに追加し、マスタ・スレーブデータベースの役割が変更された場合には情報を更新します。
_sentinel_:hello
(2) 2秒ごとに自分の情報をマスターデータとスレーブデータベースのチャネルに送信します。役割は、独自の監視データを Sentry と共有することです。_sentinel:hello
各センチネルはデータベースのチャネルに登録し、他のセンチネルがメッセージを受信すると、そのセンチネルが新しいセンチネルであるかどうかを判断し、新しいセンチネルであればセンチネル リストに追加され、接続が確立されます。
(3) すべてのマスター/スレーブ ノードおよびすべてのセンチネル ノードに 1 秒ごとに ping コマンドを送信し、ノードが生存しているかどうかを監視します。
1.2.3 主観的オフラインと客観的オフライン
センチネル ノードが ping コマンドを送信したときに、ノードが一定時間 ( down-after-millisecond
) 経過しても応答しない場合、センチネルは主観的にオフラインであるとみなします。主観的オフラインとは、現在のセンチネルがノードがすでにダウンしていると信じていることを意味します。ノードがマスター データベースの場合、センチネルはフェイルオーバーが必要かどうかをさらに判断します。このとき、コマンド ( ) を送信して他のノードに問い合わせます。 SentrySENTINEL is-master-down-by-addr
ノードは、マスター ノードが主観的オフラインであると考えるかどうかに関係なく、指定された数 (クォーラム) に達すると、Sentry はマスター ノードを客観的オフラインであるとみなします。
マスター ノードが客観的にオフラインになった場合、マスター/スレーブ切り替えが必要になります。マスター/スレーブ切り替えの手順は次のとおりです。
-
先頭のセンチネルを選出します。
-
リーダーセンチネルのすべてのスレーブは、最高の優先順位でスレーブ データベースを選択します。
slave-priority
優先順位はオプションで設定できます。 -
優先順位が同じ場合、コピーされたコマンドからのオフセットが大きいほど (つまり、より多くのデータがコピーおよび同期され、データが新しいほど)、優先順位は高くなります。
-
上記の条件が同じ場合は、実行IDの小さいスレーブデータベースを選択してください。
スレーブ データベースが選択されると、センチネルはslave no one
マスター データベースにアップグレードするコマンドを送信し、slaveof コマンドを送信して他のスレーブ ノードのマスター データベースを新しいマスター データベースとして設定します。
1.2.4 セントリーモードの長所と短所
1. 利点
-
センチネル モードはマスター スレーブ モードに基づいており、マスター スレーブ モードでマスター障害が発生した場合に自動的に障害を切り替えることができないという問題を解決します。
2. 不足 - 問題
-
これは集中型のクラスター実装スキームです。書き込みリクエストを受信して処理する Redis ホストは常に 1 つだけであり、書き込み操作は単一マシンのボトルネックの影響を受けます。
-
クラスター内のすべてのノードは全量のデータを保存しますが、これはメモリースペースを無駄にし、真の分散ストレージを実現しません。データの量が大きすぎる場合、マスターとスレーブの同期はマスターのパフォーマンスに重大な影響を与えます。
-
Redis ホストがダウンした後は、投票が終了するまではホストとスレーブが誰であるか誰も分からないため、センチネル モードは投票の場合ではありません。このとき、Redis は保護メカニズムも開き、書き込み操作を禁止します。選択が完了しました 新しい Redis ホスト。
マスタースレーブモードやセンチネルモードで各ノードに保存されるデータは全量のデータですが、データ量が多すぎる場合には保存データを分割して複数のredisインスタンスに保存する必要があります。現時点では、Redis Sharding テクノロジーが使用されます。
1.3. 大手メーカーのRedisクラスタソリューション
Redis は、バージョン 3.0 より前のシングル インスタンス モードのみをサポートしています。Redis 開発者 Antirez 氏は、自身のブログで早くも Redis バージョン 3.0 にクラスター機能を追加することを提案していましたが、バージョン 3.0 は 2015 年まで正式バージョンをリリースしていませんでした。大手企業はそれを待ちきれず、バージョン 3.0 のリリース前に、Redis のストレージ ボトルネックを解決するために、独自の Redis クラスター ソリューションを次々と立ち上げました。これらのソリューションの中心的なアイデアは、データのシャーディング (シャーディング) を複数の Redis インスタンスに保存することであり、各シャードは Redis インスタンスです。
1.3.1 クライアントの断片化
クライアント側のシャーディングは、Redis クライアントの事前定義されたルーティング ルール (一貫性のあるハッシュを使用) を通じて、Redis クライアントにシャーディングのロジックを配置することによって実装されます (例: jedis はすでに Redis シャーディング機能、つまり ShardedJedis をサポートしています)。 、キーへのアクセスは別の Redis インスタンスに転送され、データのクエリ時に返された結果が収集されます。このシナリオのスキーマを図に示します。
クライアント側シャーディングの長所と短所:
利点: シャーディングにハッシュ コンセンサス アルゴリズムを使用するクライアント側シャーディング テクノロジの利点は、すべてのロジックが制御可能であり、サードパーティの分散ミドルウェアに依存しないことです。サーバー側の Redis インスタンスは互いに独立しており、関連性がありません。各 Redis インスタンスは 1 つのサーバーのように動作し、直線的に拡張することが非常に簡単で、システムは非常に柔軟です。開発者はシャーディングとルーティングのルールを実装する方法を知っているため、穴を踏むことを心配する必要はありません。
1. 一貫したハッシュ アルゴリズム:
これは分散システムで一般的に使用されるアルゴリズムです。たとえば、分散ストレージ システムは特定のノードにデータを保存する必要があります。mod(key,d) などの共通のハッシュ方式を使用してデータを特定のノードにマッピングする場合、キーはデータのキーになります。 d マシン ノードの数です。マシンがクラスタに参加またはクラスタから離脱すると、すべてのデータ マッピングが無効になります。
一貫性のあるハッシュ アルゴリズムは、通常の剰余ハッシュ アルゴリズムの拡張性の低さの問題を解決し、サーバーがオンラインまたはオフラインのときに、できるだけ多くのリクエストが元のルーティングされたサーバーにヒットすることを保証できます。
2. 実装方法: MURMUR_HASH ハッシュ アルゴリズム、ketamahash アルゴリズムなどの一貫したハッシュ アルゴリズム
たとえば、Jedis の Redis Sharding 実装では、一貫性のあるハッシュ アルゴリズム (一貫性のあるハッシュ) を使用して、キーとノード名を同時にハッシュし、マッピングの一致を実行します。使用されるアルゴリズムは MURMUR_HASH です。
単純なハッシュのようなモジュロ マッピングではなく一貫したハッシュを使用する主な理由は、ノードが追加または削除されるときに、再マッチングによる再ハッシュが発生しないことです。一貫性のあるハッシュは隣接ノードのキー配布にのみ影響し、影響は小さいです。
不十分:
-
これは静的シャーディング スキームであり、Redis インスタンスの数を増減し、シャーディング プログラムを手動で調整する必要があります。
-
運用保守コストが比較的高く、クラスタデータに問題が発生した場合は運用保守担当者と開発者の協力が必要となるため、問題解決のスピードが遅くなり、部門間のコミュニケーションコストも増加します。
-
異なるクライアント プログラムで、同じルート シャーディング ロジックを維持するコストは膨大です。たとえば、Java プロジェクトと PHP プロジェクトは Redis クラスターのセットを共有しており、ルーティング断片化ロジックは同じロジックを 2 セット記述する必要があり、将来的には 2 セットのメンテナンスが必要になります。
クライアント シャーディングに関する最大の問題の 1 つは、サーバー側 Redis インスタンス グループのトポロジ構造が変更されると、各クライアントを更新して調整する必要があることです。クライアントフラグメンテーションモジュールを個別に取り出して別モジュール(ミドルウェア)を形成できれば、クライアントとサーバーを繋ぐブリッジとしてこの問題は解決でき、その際にプロキシフラグメンテーションが発生します。
1.3.2 プロキシの断片化
Twemproxy は最も広く使用されている Redis エージェントのフラグメンテーションであり、Twitter によるオープンソース Redis エージェントです。その基本原理は次のとおりです: ミドルウェアの形式を通じて、Redis クライアントはリクエストを Twemproxy に送信し、Twemproxy はそれを正しい Redis インスタンスに送信します最後に、Twemproxy は結果を集約してクライアントに返します。
Twemproxy は、複数の Redis インスタンスを統合的に管理するプロキシ層を導入することで、Redis クライアントは Twemproxy 上で動作するだけでよく、背後にある Redis インスタンスの数を気にする必要がなく、Redis クラスターを実現します。
Twemproxy の利点:
-
クライアントは、コード ロジックを変更せずに、Redis インスタンスと同様に Twemproxy に接続します。
-
無効な Redis インスタンスの自動削除がサポートされています。
-
Twemproxy は Redis インスタンスとの接続を維持し、クライアントと Redis インスタンス間の接続の数を減らします。
Twemproxy の欠点:
-
Redis クライアントからの各リクエストは Twemproxy プロキシを経由して Redis サーバーに到達するため、このプロセスでパフォーマンスが低下します。
-
使いやすい監視および管理のバックグラウンド インターフェイスがないため、運用および保守の監視には役立ちません。
-
Twemproxy の最大の問題点は、スムーズに拡張/縮小できないことです。運用保守担当者にとって、ビジネスニーズにより Redis インスタンスを追加する際の作業負荷は非常に大きくなります。
Twemproxy は、最も広く使用され、実績があり、安定した Redis プロキシとして、業界で広く使用されています。
1.3.3 コード
TwemproxyではRedisインスタンスをスムーズに増やすことができないという問題が大きな不便をもたらしていたため、PeapodではGo言語とC言語をベースにRedisインスタンスのスムーズな増加を支援するRedisプロキシソフトウェア「Codis」を独自に開発し、2014年11月に提供を開始しました。 GitHub 上のソース。
Codis のアーキテクチャ図では、Redis Server Group
マスター CodisRedis と 1 つ以上のスレーブ CodisRedis を指定することで Redis クラスターの高可用性を実現する Codis が導入されています。プライマリ CodisRedis がハングアップすると、Codis はセカンダリ CodisRedis をプライマリ CodisRedis に自動的に昇格させません。これにはデータの整合性の問題が伴います (Redis 自体は、データ同期にマスター/スレーブの非同期レプリケーションを使用します。データがプライマリ CodisRedis に正常に書き込まれると、スレーブ CodisRedis がこのデータを読み取ったかどうかは保証されません)、管理者は管理インターフェイス上でスレーブ CodisRedis をマスター CodisRedis に手動で昇格させる必要があります。
Codis-ha
手動処理が面倒な場合、エンドウ豆ポッドは、プライマリ CodisRedis がダウンしていることを検出したときに、オフラインにしてセカンダリ CodisRedis をマスター CodisRedis に昇格させるツールも提供します。
CodisはPre-shardingの形式を採用しており、起動時に1024個のスロットが作成され、1スロットが1ボックスに相当し、各ボックスは1から1024までの固定番号を持ちます。スロット ボックスは Key を格納するために使用されます。Key がどのボックスに格納されるかについては、アルゴリズム「 」によって数値が取得されます。crc32(key)%1024
この数値の範囲は 1 ~ 1024 でなければならず、Key はこの番号に対応するスロット。
たとえば、crc32(key)%1024
アルゴリズム " " を通じてキーによって取得された数値が 5 の場合、それを 5 とコード化されたスロット (ボックス) に置きます。1 つのスロットには 1 つのスロットのみを配置できRedis Server Group
、1 つのスロットをRedis Server Group
複数のスロットに配置することはできません。1 つのスロットには最小1Redis Server Group
スロット、最大 1024 スロットを格納できます。したがって、 Codis には最大 1024 を指定できますRedis Server Group
。
Codis の最大の利点は、スムーズな増加 (減少) Redis Server Group
(Redis インスタンス) をサポートし、安全かつ透過的にデータを移行できることであり、この点も Codis が Twemproxy などの静的分散 Redis ソリューションと異なる点です。Codis の追加後はRedis Server Group
、スロットの移行が必要になります。
例えば、2系統ありRedis Server Group
、Redis Server Group
スロットとの対応関係は以下の通りである。
Redis サーバー グループが追加されると、スロットが再割り当てされます。Codis がスロットを割り当てる方法は 2 つあります。
1 つ目の方法: Codis 管理ツール Codisconfig を使用して手動で再配布し、各 Redis サーバー グループに対応するスロットの範囲を指定します。たとえば、次のように Redis サーバー グループとスロットの新しい対応関係を指定できます。
2 番目の方法: Codis 管理ツール Codisconfig のリバランス機能を通じて、各 Redis サーバー グループのメモリに応じてスロットが自動的に移行され、データ バランスが実現されます。
1.4、Redisクラスター
Redis のセンチネル モードは高可用性と読み取り/書き込み分離を実現できますが、いくつかの欠点があります。
-
Sentinel モードでは、各 Redis サーバーが同じデータを保存するため、メモリ領域が無駄になり、データ量が多すぎて、マスターとスレーブの同期がマスターのパフォーマンスに重大な影響を与えます。
-
Sentinel モードは集中クラスタ実装スキームであり、各スレーブ マシンはホスト マシンと高度に結合されており、マスターのダウンタイムからスレーブ選択マスターの回復までの期間はサービスが利用できなくなります。
-
Sentinel モードでは、書き込みリクエストを受信して処理する Redis ホストは常に 1 つだけですが、書き込み操作は依然として単一マシンのボトルネックの影響を受けており、真の分散アーキテクチャは実装されていません。
Redis は、Redis の分散ストレージ、つまり、各 Redis ノードに異なるデータが保存されることを実現するために、3.0 で Cluster クラスター モードを追加しました。単一マシンの Redis 容量が限られているという問題を解決するために、クラスター モードでは、特定のルールに従ってデータを複数のマシンに分散します。メモリ/QPS は単一マシンに限定されず、分散クラスターの高い拡張性の恩恵を受けることができます。 。
Redis Cluster は、複数のマスターと複数のスレーブを使用するサーバー シャーディング テクノロジー (シャーディングとルーティングはサーバー側で実装されます) であり、各パーティションは Redis ホストと複数のスレーブで構成されます。Redis Cluster クラスターは P2P モデルを採用しており、完全に分散化されています。
上の図に示すように、クラスターの展開には少なくとも 3 つのマスター ノードが必要であることが公式に推奨されており、6 つのノードで 3 つのマスターと 3 つのスレーブのモードを使用するのが最適です。Redis Cluster クラスターには次の特徴があります。
-
クラスターは完全に分散化されており、複数のマスターと複数のスレーブを採用しており、すべての Redis ノードは相互接続され (PING-PONG メカニズム)、バイナリ プロトコルが内部で使用されて伝送速度と帯域幅が最適化されます。
-
クライアントは、中間プロキシ層を介さずに Redis ノードに直接接続されます。クライアントはクラスター内のすべてのノードに接続する必要はありませんが、クラスター内の使用可能な任意のノードに接続できます。
-
各パーティションは Redis ホストと複数のスレーブで構成され、シャードとシャードは相互に並列されます。
-
各マスター ノードは、スロットの一部と、スロットにマッピングされたキーと値のデータを維持する責任を負います。クラスター内の各ノードは、完全な量のスロット情報を持ち、スロットを通じて、各ノードは特定のデータがどのノードであるかを認識します。に保存されています。
Redis クラスターは主に大規模データ + 高同時実行 + 高可用性のシナリオに適しています。大規模なデータがある場合は Redis クラスターを使用することをお勧めします。データの量がそれほど多くない場合は、sentinel を使用するだけで十分です。Redis クラスターのパフォーマンスと高可用性は、センチネル モードよりも優れています。
Redis Cluster は一貫したハッシュ アルゴリズムの代わりに仮想ハッシュ スロット パーティショニングを採用し、いくつかのカード スロットを事前に割り当てます。すべてのキーはハッシュ関数に従ってこれらのスロットにマッピングされます。各パーティションのマスター ノードはスロットの一部を維持する責任を負い、マップされたスロット、キーと値のデータ。
2. RDBの永続化
2.1 RDBフルライト
2.1.1 RDBの原理
RDB
永続化は、現在のプロセス データのスナップショットを生成し、ハードディスクに保存するプロセスです。RDB
永続化をトリガーするプロセスは、手動トリガーと自動トリガーに分けられます。
プロセス:
- 1) bgsave コマンドを実行すると、Redis 親プロセスは現在実行中の子プロセス (RDB/AOF 子プロセスなど) があるかどうかを判断し、bgsave コマンドがあればそのままリターンします。
- 2) 親プロセスは、子プロセスを作成するためにフォーク操作を実行します。フォーク操作中、親プロセスはブロックされます。info stats コマンドでlatest_fork_usec オプションを表示し、最新のフォーク操作にかかる時間をマイクロ秒単位で取得します。 。
- 3) 親プロセスのフォークが完了すると、bgsave コマンドは「バックグラウンド保存が開始されました」というメッセージを返し、親プロセスをブロックしなくなり、他のコマンドに応答し続けることができます。
- 4) 子プロセスは RDB ファイルを作成し、親プロセスのメモリに基づいて一時スナップショット ファイルを生成し、完了後に lastsave コマンドを実行して元のファイルをアトミックに置き換えて、現在の RDB 生成時刻に対応する最後の RDB 生成時刻を取得します。情報統計の rdb_last_save_time オプション。
- 5) プロセスは親プロセスに完了を示すシグナルを送信し、親プロセスは統計情報を更新します。詳細については、info Persistence の rdb_* 関連オプションを参照してください。
2.1.2 RDBモード
SAVE は RDB の永続性をブロックしています。このコマンドが実行されると、rdis のメイン プロセスはメモリ内のデータベースの状態を rdb ファイルに書き込みます。ファイルが作成されるまで、Redis はコマンド リクエストを処理できません。
BGSAVE ノンブロッキング永続性では、メモリ内のデータベースの状態を RDB ファイルに書き込む子プロセスが作成され、メインプロセスもクライアントからのリクエストを処理できますが、子プロセスは基本的に親プロセスをコピーします。これは、システム上で実行されている同じサイズの 2 つの Redis プロセスに相当し、メモリ使用量が大幅に増加します。
2.1.3 rdbトリガーの状況
1. bgsave または save コマンドを手動で実行します。 2. 設定ファイルの保存オプションに従って自動的にトリガーします。 3. マスター/スレーブ構造では、スレーブ ノードがフル コピー操作を実行し、マスター ノードがそれを自動的に実行し、送信します。生成された RDB ファイルをスレーブに送信します。 4. コマンドが Redis をリロードするときに、デバッグ リロードを実行します。 5. デフォルトでは、Shutdown コマンドを実行して Redis を閉じるときに、AOF 永続化機能が有効になっていない場合、自動的に実行されます。
2.1.4 rdb の長所と短所
アドバンテージ:
- この方法を採用すると、Redis データベース全体に含まれるファイルは 1 つだけになり、このペアではデータ ファイル全体を毎日定期的にバックアップできます。
- 災害復旧には、RDB が非常に良い選択です。なぜなら、単一のファイルを簡単に圧縮して、他の記憶メディアに転送できるからです。
- AOF機構と比較して、データセットが大きい場合にはRDBの起動効率が高くなります。
短所:
- RDB はフォーク子プロセスを通じてデータ永続化の完了を支援するため、データ セットが大きい場合、サーバー全体が数百ミリ秒、場合によっては 1 秒間サービスを停止する可能性があります。
- RDB ファイルは特定のバイナリ形式で保存されるため、Redis のバージョンが進化する過程で複数の形式の RDB バージョンが存在し、古いバージョンの Redis サービスが新しいバージョンの RDB 形式と互換性がないという問題があります。
2.1.5 rdbファイルの構成
redis.confファイル
#注释所有save行则停止rdb持久化
#900秒(15分钟)内至少1个key值改变(则进行数据库保存--持久化)
save 900 1
#300秒(5分钟)内至少10个key值改变(则进行数据库保存--持久化)
save 300 10
#60秒(1分钟)内至少10000个key值改变(则进行数据库保存--持久化)
save 60 10000
#当RDB持久化出现错误后,再写入数据会报错,用于提示用户出问题了。
#yes是开启,no是关闭,默认开启
stop-writes-on-bgsave-error yes
#是否压缩rdb文件,rdb文件压缩使用LZF压缩算法,压缩会消耗一些cpu,不压缩文件会很大
#yes开启,no关闭,默认开启
rdbcompression yes
#使用CRC64算法来进行数据校验,防止RDB是错误的,但是这样做会增加大约10%的性能消耗
#yes开启,no关闭,默认开启
rdbchecksum yes
コピー
2.1.6 rdbコマンドの設定
RDB プロセスが完了するまで現在の Redis サーバーをブロックします。比較的大きなメモリを備えたインスタンスの場合、長期的なブロックが発生するため、オンライン環境での使用はお勧めできません。save
Redis プロセスは fork 操作を実行して子プロセスを作成し、RDB 永続化プロセスは子プロセスを担当し、完了後に自動的に終了します。ブロッキングはフォークフェーズ中にのみ発生し、通常は短時間発生します。bgsave
最新のフォーク操作にかかる時間をマイクロ秒単位で取得するには、latest_fork_usec オプションを表示します。info stats
2.1.7 RDBデータの復旧
1. RDBのバックアップを設定ファイルで指定したデータディレクトリに置き、redisを起動すると自動で復元されます。ロード中にブロックされ、他の操作は実行できません。
2. 上記の方法は機能しません。または、復元されたクラスターは redis-merge-tool ツールを使用して復元できます。
2.2 AOF 永続性: 増分書き込み
2.2.1 Aof 原則
各書き込みコマンドを独立したログに記録し、AOF ファイルでコマンドを再実行して、再起動時にデータを復元します。AOF の主な機能は、現在 Redis 永続化の主流の方法であるデータ永続化のリアルタイム性を解決することです。
書き込まれたデータは読み取り可能であり、同期時には、まずバッファに書き込まれ、次にハードディスクに書き込まれます。ハードディスクに直接書き込む場合、パフォーマンスはディスクの負荷に依存し、さまざまな同期戦略を提供できるバッファに配置されます。
プロセス:
- 1) すべての書き込みコマンドは aof_buf (バッファ) に追加されます。
- 2) AOF バッファは、対応する戦略に従ってハードディスクに同期されます。
- 3) AOF ファイルはますます大きくなるため、圧縮の目的を達成するには定期的に AOF ファイルを書き換える必要があります。
- 4) Redis サーバーが再起動すると、データ回復のために AOF ファイルをロードできます。
2.2.2 aof トリガーの状況
1. 設定ファイルに従って自動的にトリガーします
2.2.3 利点と欠点
アドバンテージ:
- このメカニズムにより、より高いデータ セキュリティ、つまりデータの永続性が実現されます。ポリシーに応じてデータ セキュリティが異なり、パフォーマンスとセキュリティの領域で選択できます。
- この仕組みでは、ログファイルの書き込み処理に追記モードを採用しているため、書き込み処理中にダウンタイムが発生した場合でも、ログファイルの既存の内容が破壊されることはありません。
- ログが大きすぎる場合、書き換えメカニズムが自動的に有効になります。追加モードでは、変更されたデータは古いディスク ファイルに継続的に書き込まれ、セキュリティを確保するために、この期間中にどの変更コマンドが実行されたかを記録する新しいファイルが作成されます。
- AOF には、すべての変更操作を記録するための、明確にフォーマットされた理解しやすいログ ファイルが含まれています。実際、このファイルを通じてデータの再構築を完了することもできます。
短所:
- 同じ量のデータ セットの場合、通常、AOF ファイルの方が RDB ファイルよりも大きくなります。RDB は、AOF よりも高速に大規模なデータセットを復元します。
- さまざまな同期戦略によれば、AOF は動作効率の点で RDB よりも遅いことがよくあります。つまり、同期戦略の 1 秒あたりの効率は比較的高く、同期無効化戦略の効率は RDB と同等です。
2.2.4 aofファイルの構成
Redis 構成ファイルには、次の 3 つの同期方法があります。
#是否开启aof持久化。默认no,要打开
appendonly yes
#位置
appendfilename "appendonly.aof"
#每次有数据修改发生时都会写入AOF文件
#命令写入aof_buf后调用系统fsync操作同步AOF文件,fsync完成后线程返回
appendfsync always
#每秒钟同步一次,该策略为AOF的缺省策略
#命令写入aof_buf后调用系统write操作,write完成后线程返回。fsync同步文件操作由专门线程每秒调用一次
#这个模式兼顾了效率的同时也保证了数据的完整性,即使在服务器宕机也只会丢失一秒内对redis数据库做的修改
appendfsync everysec
#不加入缓冲区,直接写到硬盘,速度最快,不安全
#命令写入aof_buf后调用系统write操作,不对aof文件做fsync同步,同步硬盘操作由操作系统负责,通常同步周期最长30秒
#这种模式下效率是最快的,但对数据来说也是最不安全的,如果redis里的数据都是从后台数据库如mysql中取出来的,属于随时可以找回或者不重要的数据,那么可以考虑设置成这种模式。
appendfsync no
コピー
2.2.5 aofコマンドの設定
aof ファイル書き換えトリガーを手動で実行するbgrewriteaof
Aof ファイルの書き換えが自動的にトリガーされ、設定ファイル
#新的aof文件大小是上次的aof文件的大小2倍(100)时,进行重写
auto-aof-rewrite-percentage 100
#表示运行AOF重写时文件最小体积, 默认为64MB
auto-aof-rewrite-min-size 64mb
コピー
2.2.6 データ復旧
- AOF バックアップを構成ファイルで指定されたデータ ディレクトリに配置すると、redis の起動時に自動的に復元されます。ロード中にブロックされ、他の操作は実行できません。
- 上記の方法が機能しない場合、または復元されたクラスターは redis-merge-tool ツールを使用して復元できます。
- パイプライン方式を使用してハード書き込みをバッチ処理できますが、効率は低くなります。
2.3.RDBとAOFの比較
この 2 つのどちらかを選択する基準は、システムがキャッシュ一貫性 (aof) を高める代わりにパフォーマンスをある程度犠牲にするか、書き込み操作が頻繁に行われる場合はパフォーマンスを高める代わりにバックアップを無効にするかどうかを確認し、その結果が得られるまで待つことです。 save は手動で実行され、バックアップ (rdb) が作成されます。
読み込みプロセスを開始します。
- AOF 永続性が有効で、AOF ファイルが存在する場合、AOF ファイルが最初にロードされます。
- AOFが閉じている場合、またはAOFファイルが存在しない場合は、RDBファイルをロードします
- AOF/RDB ファイルが正常にロードされた後、Redis が正常に起動します
- AOF/RDB ファイルにエラーがある場合、Redis は起動に失敗し、エラー メッセージが出力されます。
3. Redis の概要
3.1 Redis の高レベル キャッシュの内訳
3.1.1 キャッシュブレークダウンの定義
缓存击穿
, は缓存中没有但数据库中有的数据
、 、 を某一个key非常热点
意味し、常に大きな同時実行数を保持している間、大きな同時実行数はこのポイントへのアクセスに集中します。キーの有効期限が切れると (通常はキャッシュ時間の期限が切れたとき)、継続的な大きな同時実行数はキャッシュを突破します。データベースを直接リクエストすることは、障壁に穴を開けるようなもの。
キャッシュ ブレークダウンは少し似ていますが、この 2 つの違いは、キャッシュ パンクチャはデータベースに過大な負荷がかかるか、場合によってはダウンすることを意味するのに対し、キャッシュ ブレークダウンは DB データベース レベルへの同時リクエストの数が単なる多数であることです。この内訳は、キャッシュされた Xueben のサブセットであると考えることができます。一部の記事では、この 2 つの違いは、内訳が特定のホット キー キャッシュに関するものであるのに対し、Xueben は多くのキーに関するものであると考えられています。
3.1.2 キャッシュ故障の原因
これは、キャッシュ雪崩の特別なサブセットと見なすことができます。
たとえば、xxx 住宅崩壊や xxx 製品活動などです。現時点では、このホット イベントには多数のユーザーがアクセスしていますが、何らかの理由でより良い可能性があります。redis のホット キーの有効期限が切れているため、現時点では、大規模なこのキーに対する同時実行性の高いリクエストの数は、redis からの応答がない場合、リクエストが DB サーバーに直接送信され、DB 全体が麻痺する原因となります。
3.1.3 キャッシュブレークダウンソリューション
- ミューテックス スキームを使用します。キャッシュが失敗した場合は、DB データをすぐにロードするのではなく、(Redis の setnx) など、正常に返されるアトミック操作コマンドを使用して操作し、DB データベース データをロードして、成功したときにキャッシュを設定します。それ以外の場合は、キャッシュの取得を再試行します。
- 「期限切れにならない」とは、有効期限が設定されていないことを意味しますが、ホットスポット データの有効期限が近づくと、非同期スレッドが更新されて有効期限を設定します。
3.1.4 キャッシュブレークダウンソリューションにおけるミューテックスの詳細説明
業界ではミューテックスを使用するのが一般的です。簡単に言うと、キャッシュが失敗した場合(取り出した値が空であると判断した場合)、すぐにDBをロードするのではなく、まず成功した操作戻り値を持つキャッシュツールのいくつかの操作(RedisのSETNXやMemcache ADDなど)を使用します。ミューテックス キーを設定するには、操作が正常に返されたら、load db 操作を実行してキャッシュをリセットします。それ以外の場合は、キャッシュ取得メソッド全体を再試行します。
SETNX は「SET if Not eXists」の略で、存在しない場合にのみ設定され、ロック効果を実現するために使用できます。
public String get(key) {
String value = redis.get(key);
if (value == null) { //代表缓存值过期
//设置3min的超时,防止del操作失败的时候,下次缓存过期一直不能load db
if (redis.setnx(key_mutex, 1, 3 * 60) == 1) { //代表设置成功
value = db.get(key);
redis.set(key, value, expire_secs);
redis.del(key_mutex);
} else { //这个时候代表同时候的其他线程已经load db并回设到缓存了,这时候重试获取缓存值即可
sleep(50);
get(key); //重试
}
} else {
return value;
}
}
3.2 Redis の高レベルのキャッシュの浸透
3.2.1 キャッシュペネトレーションの定義
缓存穿透
クエリ 1 を指します数据库一定不存在的数据
。キャッシュを使用する通常のプロセスは、大まかに言うと、最初にデータ クエリがキャッシュされ、キーが存在しないかキーの有効期限が切れている場合は、データベースがクエリされ、クエリされたオブジェクトがキャッシュに入れられます。データベース クエリ オブジェクトが空の場合、キャッシュには入れられません。
ここで注意が必要な違いは缓存击穿
、キャッシュ ブレークダウンです。キャッシュ ブレークダウン缓存中没有但数据库中有的数据
とは某一个key非常热点
、キーが失敗した瞬間 (通常はキャッシュ時間の期限切れ時) にある場合、連続した大規模な同時実行がキャッシュを突破し、バリアに穴を掘るように、データベースに直接リクエストします。
平たく言えば、読み取りリクエストがアクセスされるとき、キャッシュにもデータベースにも特定の値がないため、この値に対するすべてのクエリリクエストがデータベースに浸透します。これがキャッシュ浸透です。
3.2.2 キャッシュ侵入の原因
- ビジネスの不合理な設計。たとえば、ほとんどのユーザーはガードを有効にしていませんが、特定のユーザー ID がガードされているかどうかを確認するために各リクエストがキャッシュされます。
- キャッシュやデータベースのデータなど、業務・運用や保守・開発のミスにより誤って削除されてしまう。
- ハッカーは違法に攻撃を要求します。たとえば、ハッカーは、存在しないビジネス データを読み取るための多数の違法な要求を意図的にでっち上げます。
3.2.3 キャッシュ侵入のための3 つのソリューション
- 不正なリクエストの場合は、API エントリのパラメータを検証し、不正な値をフィルタリングします。
- クエリ データベースが空の場合は、キャッシュに null 値またはデフォルト値を設定できます。ただし、書き込み要求が来た場合は、キャッシュの整合性を確保するためにキャッシュを更新する必要があり、同時に、最終的にキャッシュに適切な有効期限が設定されます。(ビジネスでよく使われる、シンプルで効果的)
- ブルーム フィルターを使用して、データが存在するかどうかをすばやく判断します。つまり、クエリリクエストが来ると、まずブルームフィルターで値が存在するかどうかを判断し、その後、値が存在するかどうかを確認し続けます。
ブルーム フィルターの原理: 初期値 0 のビットマップ配列と N 個のハッシュ関数で構成されます。キーに対して N 個のハッシュ アルゴリズムを実行して N 個の値を取得し、ビット配列内の N 個の値をハッシュして 1 に設定し、特定の位置がすべて 1 であるかどうかを確認して、ブルーム フィルター デバイスがキーが存在すると判断します。 。
3.2.4 キャッシュペネトレーションソリューション用ブルームフィルタの詳細説明
布隆过滤器
ビット ベクトルまたはビットです。値をブルーム フィルターにマッピングする場合は、複数の異なるハッシュ関数を使用して複数のハッシュ値を生成し、生成された各ハッシュ値が指すビットを 1 に設定します。次の単語は baidu です。 3 つの位置を 1 として設定します。
原理: キーに対して k 個のハッシュ アルゴリズムを実行して k 値を取得し、ビット配列でハッシュした後に k 値を 1 に設定し、特定の位置がすべて 1 であるかどうかを確認して、ブルーム フィルターによってキーが存在すると判断します。
「テンセント」という言葉とそれに相当する状況
異なる単語に対応するビット位置は同じである可能性があることがわかります。単語が多い場合、ほとんどのビット位置は 1 になる可能性があります。このとき、クエリ タオバオの対応する位置は 1 になる可能性がありますが、これは単に示しているだけですタオバオという単語が存在する可能性があり、必ずしも存在するとは限らない場合、1 がカバーされます。これは、ブルーム フィルターの誤判定です。如果它说不存在那肯定不存在,如果它说存在,那数据有可能实际不存在。
Redis のビットマップは、512MB のメモリに相当する 2^32 のサイズのみをサポートしており、誤判定率は 1/10,000 であり、高性能で占有スペースが小さいため、約 2 億のデータを保存でき、大幅な節約が可能です。無効なデータベース接続です。
したがって、ブルーム フィルターを使用して、Redis キャッシュの侵入を許容範囲内に制御できます。
ブルーム フィルターの使用:
依存関係をインポートする
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
</dependency>
コード:
public class Test {
private static int size = 1000000;//预计要插入多少数据
private static double fpp = 0.01;//期望的误判率
private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), size, fpp);
public static void main(String[] args) {
//插入数据
for (int i = 0; i < 1000000; i++) {
bloomFilter.put(i);
}
int count = 0;
for (int i = 1000000; i < 2000000; i++) {
if (bloomFilter.mightContain(i)) {
count++;
System.out.println(i + "误判了");
}
}
System.out.println("总共的误判数:" + count);
}
}
応用:
@Cacheable(value="key1")
public String get(String key) {
String value = redis.get(key);
// redis中不存在该缓存
if (value == null) {
//布隆过滤器也没有,直接返回
if(!bloomfilter.mightContain(key)){
return null;
}else{
//布隆过滤器中能查到,不代表一定有,查出来放入redis,同样也可以避免缓存穿透
value = db.get(key);
redis.set(key, value);
}
}
return value;
}
(2) 空のオブジェクトをキャッシュする
ストレージ層がミスした場合、返された空のオブジェクトもキャッシュし、同時に有効期限を設定し、後のアクセス時にキャッシュからデータを取得することでバックグラウンドを保護します。データソースを終了します。
しかし、このアプローチには 2 つの問題があります。
● null 値をキャッシュできる場合は、缓存需要更多的空间存储更多的键
null 値を持つキーが多数存在する可能性があることを意味します。
● NULL 値に有効期限を設定しても、一定期間はキャッシュ層とストレージ層のデータに不整合が残り、整合性を維持する必要がある業務に影響を与える
3.3 Redis の高レベルキャッシュ雪崩
3.3.1 キャッシュスケジュールの定義
これは、有効期限までにキャッシュ内に大量のデータが存在することを指しますが、クエリ データの量が膨大であり、すべてのリクエストがデータベースに直接アクセスするため、データベースに過剰な負荷がかかり、場合によってはマシンがダウンしてしまいます。
- Xueben のキャッシュは、一般に大量のデータの有効期限が同時に切れることによって発生するため、有効期限を均等に設定する、つまり有効期限を比較的離散的に設定することで解決できます。たとえば、より大きな固定値 + より小さなランダム値、5 時間 + 0 ~ 1800 秒を使用します。
- Redis のダウンタイムもキャッシュのスノーランニングを引き起こす可能性があります。これには、Redis 高可用性クラスターの構築が必要です。
3.3.2 雪崩の原因
ダブルイレブンの午前0時に到着しようとしている場合、すぐにパニック買いの波が起こり、この商品の波は、キャッシュが1時間であると仮定すると、比較的集中した時間にキャッシュに入れられます。その後、午前 1 時に、この製品バッチのキャッシュの有効期限が切れます。このバッチの商品に対するアクセス クエリはすべてデータベースに反映され、データベースでは定期的に圧力のピークが発生します。
3.3.3 キャッシュアバランシェに対する 4 つの解決策
- さまざまなカテゴリの製品を使用し、さまざまなサイクルをキャッシュします。同じカテゴリのアイテムにランダム要素を加えたもの。これにより、キャッシュの有効期限を可能な限り分散することができ、また、人気のあるカテゴリの商品のキャッシュ時間が長くなり、人気のないカテゴリの商品のキャッシュ時間が短くなり、キャッシュのリソースを節約することもできます。サービス。
- キャッシュ データベースが分散方式で展開されている場合は、ホットスポット データを異なるキャッシュ データベースに均等に分散します。
- ホットスポット データが期限切れにならないように設定します。
- ロックおよび電流制限方式を使用してください。
3.3.4 キャッシュアバランシェソリューションにおけるロックと電流制限の詳細な説明
Redis のよくある面接の質問
Redisの特徴は何ですか?
- 読み取り速度10万回/秒、書き込み速度8万回/秒の高性能。
- データの永続性、RDB、AOF のサポート。
- トランザクションをサポートします。MULTI 命令と EXEC 命令によってラップされます。
- 複数のデータ構造タイプ。
- マスター/スレーブ レプリケーション。
- その他の機能: パブリッシュ/サブスクライブ、通知、キーの有効期限など。
Redis はなぜそれほど速いのでしょうか?
- 完全にメモリに基づいているため、非同期永続性を除き、ディスク IO にオーバーヘッドはありません。
- シングルスレッド、複数スレッドの切り替えによるパフォーマンスの低下を回避
- ノンブロッキングIO多重化メカニズム
- 基礎となるデータ ストレージ構造が最適化され、ネイティブ データ構造を使用してパフォーマンスが向上します。
Redis の基礎となるデータ構造は何ですか?
- 弦。C言語の伝統的な文字列を使用する代わりに、単純な動的文字列SDSの抽象型を独自に実装し、長さを節約します。
- 情報。
- リンクされたリスト (リンクリスト)。双方向非巡回リンク リスト構造。リンク リストの各ノードは listNode 構造で表され、各ノードにはプレフィックスと
- 次のノードへのポインタ
- 辞書(ハッシュテーブル)。キーと値のペアを格納する抽象データ構造。最下層はハッシュ テーブルを使用します。各ディクショナリには、通常使用のために 2 つのハッシュ テーブルがあります。
- 使用時や再ハッシュ時に使用します。
- ジャンプテーブル(スキップリスト)。スキップ リストは、ソートされたセットの基礎となる実装の 1 つです。Redis スキップ テーブルは zskiplist と zskiplistNode で構成されます。
- zskiplist はスキップ リスト情報 (ヘッダー、末尾ノード、長さなど) を保存するために使用され、zskiplistNode はテーブル スキップ ノード、各スキップ リストを表すために使用されます。
- レイヤーの高さは 1 ~ 32 の乱数です。同じジャンプ テーブル内では、複数のノードに同じスコアを含めることができますが、各ノードのメンバー オブジェクトは同じスコアを含む必要があります。
- が一意である場合、ノードはスコアのサイズに従ってソートされ、スコアが同じ場合は、メンバー オブジェクトのサイズに従ってソートされます。
- 整数のセット (intset)。整数値を格納するために使用されるコレクション抽象データ構造には繰り返しの要素はなく、基礎となる実装は配列です。
- 圧縮されたリスト (ziplist)。メモリを節約するために開発されたシーケンシャル データ構造。複数のノードを含めることができ、各ノードは 1 バイトを保持できます。
- 配列または整数値。
Redis はどのようなデータ型をサポートしていますか?
- よく使用される 5 つのデータ型: String、Hash、Set、List、SortedSet。
- 3 つの特別なデータ型: Bitmap、HyperLogLog、Geospatial。Bitmap と HyperLogLog の最下層は String データ型で、Geospatial の最下層は Sorted Set データ型です。
- 文字列オブジェクト文字列: int 整数、embstr エンコードされた単純な動的文字列、生の単純な動的文字列
- リストオブジェクトリスト: ziplist、linkedlist
- ハッシュ オブジェクトのハッシュ: ziplist、hashtable
- コレクションオブジェクトセット: intset、hashtable
- 順序付けされたコレクション オブジェクト zset: ziplist、skiplist
Redis の一般的に使用される 5 つのデータ構造とアプリケーション シナリオ?
- 文字列: キャッシュ、カウンター、分散ロックなど。
- リスト: リンクされたリスト、キュー、Weibo フォロワーのタイムライン リストなど。
- ハッシュ: ユーザー情報、ハッシュテーブルなど。
- 設定: 重複排除、好き嫌い、共通の友人など。
- Zset: リーダーボードにアクセスする、リーダーボードにヒットするなど。
Redis がシングルスレッドを使用するのはなぜですか?
公式回答によれば、CPU が Redis のボトルネックになることはなく、Redis の制限は主にメモリとネットワークであるとのことです。
たとえば、平均的な Linux システムでは、パイプライン処理を使用して 1 秒あたり 100 万のリクエストを処理できるため、アプリケーションが主に O(N) または O(log(N)) のオーダーを使用する場合、IO である CPU はほとんど使用されません。 -集中的なシステム。
Redis 6.0以降はマルチスレッドに切り替わりましたが、
Redisのマルチスレッドは主にデータの読み書きとプロトコル解析を扱います。実行コマンドは依然としてシングルスレッドの順序で実行されます。
主な理由は、redis のパフォーマンスのボトルネックが CPU ではなくネットワーク IO にあるためです。マルチスレッドを使用して周辺機器の前処理を実行することで、IO の読み取りおよび書き込み効率が向上し、全体のスループットが向上します。antirez が RedisConf 2019 で共有したとき、Redis 6 によって導入されたマルチスレッド IO によってパフォーマンスが少なくとも 2 倍になったと述べました。
Redis の期限切れキーの削除戦略は何ですか?
有効期限切れの削除戦略は 3 つあります。遅延削除、定期削除、時限削除
- 遅延削除: キーが使用されている場合のみチェックし、期限切れの場合は削除します 欠点 : 期限切れのキーにアクセスしないと削除できず、常にメモリを占有し、スペースの無駄になります。
- 定期的な削除: 時々チェックし、期限切れのキーを削除し、毎回チェックするキーをランダムに選択します。
- 時間指定削除: 各キーの有効期限を設定し、同時にタイマーを作成します。削除は有効期限が切れるとすぐに実行されます。短所: 期限切れのキーが多数ある場合、より多くの CPU を使用し、サービスのパフォーマンスに大きな影響を与えます。
Redisのメモリ容量が不足した場合、どのような仕組みで解消されるのでしょうか?
- volatile-lru: 削除のために設定された有効期限を使用して、最も最近使用されていないキーをキーから削除します。
- allkeys-lru: メモリが新しく書き込まれたデータを収容するのに十分でない場合、キー空間で、最も最近使用されていないキー (これが最も一般的に使用されます) を削除します。
- volatile-ttl: 有効期限が設定されているキーから期限切れが近づいているキーを削除します
- volatile-random: 有効期限が設定されているキーの中から削除するキーをランダムに選択します
- allkeys-random: 除外するキーからランダムにキーを選択します
- no-eviction: データのエビクションを無効にします。メモリがしきい値に達すると、新しい書き込み操作でエラーが報告されます。
- volatile-lfu: 有効期限が設定されたデータ セット (server.db[i].expires) から最も使用頻度の低いデータを選択します (LFU(Least)
- Frequently Used) アルゴリズム、つまり、最も頻繁にアクセスされるデータは、将来アクセスされる可能性が最も高くなります)
- allkeys-lfu: メモリが新しく書き込まれたデータを収容するのに十分でない場合、キー空間で最も使用頻度の低いキーを削除します。
Redis が突然ハングアップした場合はどうすればよいですか?
- システム可用性の観点から、Redis Cluster にはマスター/スタンバイ メカニズムが導入されており、マスター ノードがハングアップすると、自動的にバックアップ ノードに切り替わってサービスを提供し続けます。
- クライアント側はローカル キャッシュを導入し、それを切り替えて、Redis が突然ハングアップしたり、大量の同時トラフィックによってデータベースがハングアップしたりするのを防ぎます。
Redis の永続化にはどのような方法がありますか?
- スナップショット RDB。特定の時点でのデータベースの状態を RDB ファイルに保存します。RDB ファイルは圧縮されたバイナリ ファイルであり、ディスク上に保存されます。Redis がクラッシュした場合にデータを回復するために使用できます。SAVEまたはBGSAVEによりRDBファイルを生成します。
- SAVE: RDB ファイルが作成されるまで、redis プロセスはブロックされます。プロセスのブロック期間中、redis はコマンド リクエストを処理できません。
- BGSAVE: 子プロセスがフォークされ、子プロセスが RDB ファイルの生成を担当します。親プロセスはプロセスをブロックせずにコマンド リクエストの処理を続行できます。
- ファイル AOF のみを追加します。すべての書き込み操作をログに記録します (読み取り操作ではありません)。異なるノードがデータを同期する場合、ログ ファイルの内容を読み取り、書き込みコマンドを前から後ろに 1 回実行して、データの回復を完了します。
Redis の一般的なシナリオ
- キャッシュには「性能が足りない、キャッシュで補える」といういい言葉があります。
- Redis の setnx を使用した分散ロック
- 分散セッション
- カウンタ、incr コマンド経由
- Leaderboard、Redis の順序付けされたコレクション
- 他の
Redis キャッシュで注意すべき 7 つの典型的な問題?
リストされた 10 億レベルのシステムでは、高トラフィック条件下で Redis キャッシュにどのような問題が発生する可能性がありますか? および対応するソリューション。
- キャッシュセットの無効化
- キャッシュの侵入
- キャッシュ雪崩
- キャッシュホットスポット
- ビッグキーをキャッシュする
- キャッシュデータの一貫性
- データ同時実行性の競争を促進する
Redis クラスター ソリューションとは何ですか?
- マスター/スレーブ レプリケーション モード
- センチネルモード
- Redis クラスターモード
Redis のマスター/スレーブ データ同期 (マスター/スレーブ レプリケーション) プロセス?
- スレーブが起動したら、同期コマンドをマスターに送信します。
- マスターは同期を受信した後、bgsave を実行してスナップショットを保存し、完全な RDB ファイルを生成します。
- マスターはスレーブの書き込みコマンドをキャッシュに記録します
- bgsave の実行後、RDB ファイルをスレーブに送信し、スレーブが実行します。
- マスターはバッファの書き込みコマンドをスレーブに送信し、スレーブはコマンドを受信して実行してレプリケーションの初期化を完了します。
- その後、マスターが書き込みコマンドを実行するたびに、そのコマンドはスレーブに同期して送信され、マスターとスレーブ間のデータの一貫性が維持されます。
Redis マスター/スレーブ レプリケーションの長所と短所は何ですか?
- 1. 利点: マスターはデータをスレーブに自動的に同期でき、マスターの読み取り圧力を共有するために読み書き分離を実行できます。マスターとスレーブ間の同期はノンブロッキング方式で実行されます。 、クライアントは引き続きクエリを送信したり、リクエストを更新したりできます
- 短所: 自動フォールト トレランスおよび回復機能はありません。マスター ノードがダウンした後、手動で新しいマスターを指定する必要があります。マスター ノードがダウンした場合、ダウンタイム前にデータが同期されていない場合、データの不整合が発生します。 IPを切り替えた後、オンライン拡張をサポートするのは困難で、Redisの容量はスタンドアロン構成によって制限されます
Redis Sentinel (センチネル) モードの長所と短所は?
Sentinel モードはマスター/スレーブ レプリケーション モードに基づいており、障害を監視して自動的に処理するための Sentinel を追加します。
- 利点: センチネル モードはマスター/スレーブ レプリケーション モードに基づいているため、マスター/スレーブ レプリケーション モードにはいくつかの利点があり、センチネル モードではマスターがハングアップするため、自動的に切り替えることができ、システムの可用性が高くなります。
- 欠点: Redis の容量はスタンドアロン構成によって制限されるため、センチネル プロセスを開始するには追加のリソースが必要になります。
Redis クラスター モードの長所と短所は何ですか?
Redis の分散ストレージを実現します。つまり、各ノードに異なるコンテンツを格納することで、オンライン拡張の問題を解決します。
- アドバンテージ:
- 集中型アーキテクチャ、データはスロットに従って複数のノードに分散されます。
- クラスター内の各ノードは同等であり、各ノードは独自のデータとクラスター全体の状態を保存します。
- 各ノードは他のすべてのノードに接続されており、これらの接続はアクティブに保たれるため、他のノードからデータを取得するためにクラスター内の任意のノードに接続するだけで済みます。
- 1000 ノードを超えるまで線形に拡張でき、ノードを動的に追加または削除できます。
- 自動フェイルオーバーを実現し、ゴシッププロトコルを通じてノード間でステータス情報を交換し、投票メカニズムを使用してスレーブからマスターへの役割変換を完了できます。
- 欠点:
- データは非同期的にレプリケートされるため、データの強力な一貫性は保証されません。
- スレーブは「コールド スタンバイ」として機能し、外部の読み取りおよび書き込みサービスを提供せず、フェイルオーバーのみに使用されます。
- バッチ操作の制限。現在、同じスロット値を持つキーのバッチ操作のみがサポートされており、mset、mget、sunion などの操作には適していません。
- キートランザクション操作のサポートは制限されており、同一ノード上の複数キーのトランザクション操作のみサポートされており、複数のキーが異なるノードに分散している場合、トランザクション機能は使用できません。
- 複数のデータベース スペースはサポートされていません。1 つの Redis は 16 db をサポートできますが、クラスター モードで使用できるのは 1 つだけ (つまり db0) です。
- Redis クラスター モードでは、最大リダイレクトによって生成されるシナリオを減らすためにパイプライン操作とマルチキー操作を使用することはお勧めできません。
Redis はどのようにスケールアップしますか?
データ移行の失敗を回避するために、通常は一貫性のあるハッシュを使用して動的な拡張と縮小を実現し、移行する必要があるキーの数を効果的に削減します。
ただし、クラスター モードでは、固定スロット (16384) を使用して各キーの CRC16 値を計算し、16384 の係数を取得し、スロット値に従ってターゲット マシンを見つけます。スロットの一部を新しいノードに移行するだけです。
Redis クラスターの原理
Redis クラスターは複数のノードで構成され、複数のノードがクラスターミートコマンドを介して接続されてクラスターを形成します。
データはシャーディング形式で保存され、クラスタ全体が 16384 個のスロットに分割され、各ノードがスロットの一部を担当します。スロット全体の情報がすべてのノードに同期されます。
キーとスロット間のマッピング関係: キー値はキーとペアになり、CRC16 計算が実行されて 16 ビット値が計算されます。16 ビット値は 16384 を法とする 0 から 16383 までの数値です。キーに対応するハッシュ スロットを示すために取得されます。
Redis はどのようにして高可用性を実現しますか?
センチネル機構。自動フェイルオーバー、クラスター監視、メッセージ通知などの機能を備えています。
Sentinel はすべてのマスター サーバーとスレーブ サーバーを同時に監視でき、マスターがオフラインになると、対応するスレーブを自動的にマスターに昇格させ、新しいマスターが外部サービスを提供します。
Redis トランザクションとは何ですか?
Redis トランザクションはコマンドの集合であり、複数のコマンドをパッケージ化して、これらのコマンドを順番にキューに追加し、これらのコマンドを順番に実行します。
Redis トランザクションには、Mysql リレーショナル データベース トランザクションのようなトランザクション分離レベルの概念がなく、アトミックな操作は保証できません。また、Mysql のようにトランザクションの実行に失敗するロールバック操作もありません。
Redisトランザクション実行プロセス?
トランザクションの仕組みは、MULTI、EXEC、WATCHなどのコマンドによって実現されます。トランザクション実行プロセスは、複数のコマンドを順番に一度に実行します。実行中にトランザクションが中断されることはなく、トランザクションからの他のリクエストも実行されません。コマンドが実行されるまでクライアント。
具体的な処理: サーバーはクライアントリクエストを受信し、MULTIでトランザクションが開始されます。トランザクション状態であれば後続のコマンドをキューに入れてクライアントにQUEUEDに返します。それ以外の場合はこのコマンドを直接実行します。クライアントから EXEC コマンドを受信したとき
のみ、キュー内のコマンドが取り出され、順番に実行されます。実行後、現在の状態はトランザクション状態から非トランザクション状態に変更されます。DISCARD コマンドを受信し
、キュー内のコマンドの実行は放棄され、Mysql のロールバック操作として理解できます。 現在の状態をトランザクション状態から非トランザクション状態に変更します。 WATCH はキーを監視します。このコマンドは MULTI コマンドの前にのみ実行できます
。監視対象のキーが他のクライアントによって変更された場合、EXEC はキュー内のすべてのコマンドの実行を中止します。UNWATCH 以前に WATCH コマンドによって監視されていたキーの監視を解除します。EXEC コマンドおよび DISCARD コマンドを実行する前に監視されていたキーも監視されなくなります。
Redis、Guava、カフェインの違いは何ですか?
キャッシュはローカルキャッシュと分散キャッシュに分かれます。
- カフェイン、グアバはローカル キャッシュに属し、次のような特徴があります。
- メモリへの直接アクセス、高速、メモリによる制限があり、大きなデータを保存できません。
- ネットワーク通信のオーバーヘッドがなく、パフォーマンスが向上します。
- ローカル アプリケーション プロセス アクセスのみをサポートしており、すべてのノードのローカル キャッシュ データを同期して更新するコストは高くなります。
- アプリケーションプロセスを再起動すると、データが失われます。
- したがって、ローカル キャッシュは、変更が容易ではない、または変更頻度が低い、ホットなデータを格納するのに適しています。
- Redis は分散キャッシュに属し、次のような特徴があります。
- クラスターモード、大容量データストレージをサポート
- データの一貫性を確保するための一元的なデータストレージ
- データはネットワーク経由で転送されるため、パフォーマンスはローカル キャッシュよりも低くなります。しかし、同じコンピューター室では、2 つのサーバー間でリクエストが往復するのに 500 マイクロ秒かかります。
- その利点を利用すると、この損失はまったく無視できるため、分散キャッシュが人気があります。
- 高可用性を効果的に保証するコピー メカニズムをサポートします。
分散ロックを実装するにはどうすればよいですか?
- データベーステーブル、パフォーマンスが悪い
- Lua スクリプトを使用する (SETNX + EXPIRE の 2 つの命令を含む)
- SET拡張コマンド(SETキー値[EX][PX][NX|XX])
- レッドロックフレームワーク
- Zookeeper Curator フレームワークは、すぐに使える分散型の