この記事では、Redis で頻繁に聞かれる面接の質問をまとめて共有します。これは、一定の参考価値があります。困っている友人は参考にしてください。皆さんのお役に立てれば幸いです。
面接官の観点から見ると、この質問の目的は、キャッシュに関するあなたの知識レベルをテストすることであり、キャッシュ機能と組み合わせることで、ビジネスを処理し、アーキテクチャを改善します。この質問は明らかにあなたが自由に自分の意見を表現することができ、面接官をあなたが最もよく知っている知識ポイントに導く機会を与えるものであるため、この機会を可能な限り捉えて面接官に良い印象を与える必要があります。この質問はうまく話せれば数時間は深くコミュニケーションできますが、1回のセッションであれば基本的には簡単に解決できます。 [関連する推奨事項: Redis ビデオ チュートリアル ]
ただし、死ぬほどチャットを始めないでください。チャットは浅すぎるため、 その後は基本的に戻って通知を待ちます。 ……
たとえば、次のような答えです。
多くの人が、この答えが正しいと言うでしょう。そうです、その通りですが、与えられた機会が無駄であるという感覚が常にあります。
現時点で、面接官は次のようなことを考えています:
面接官の「十八龍討伐掌」に抵抗したくないなら、自ら率先して面接官の興味をそそり、自らのパターン(横の広さと深さ)を率先して改善すべきです。そして、あなたが知っていることについてできるだけ話してください。
たとえば、次のような回答方法:
私の理解は、このインタビュアーとほぼ同じです! !
高性能: 高性能の大きな基準は、応答時間が速いことです。 Redis はメモリ ストレージをベースにしており、CPU アクセス速度が速いことに加え、データ構造、内部スレッド モデル、ネットワーク I/O モデルの設計が極端に最適化されているため、Redis は高性能のストレージ データベースです。唯一の欠点は、メモリが比較的高価であり、リソースが通常は限られていることです。したがって、非常に大きなデータのキャッシュ アーキテクチャは合理的に設計する必要があります。通常、過度に大きなデータを Redis に保存することはありません。これは、Redis のパフォーマンスが低下するためです。
高い同時実行性: 高い同時実行性の一般的な指標には、応答時間 (Response Time)、スループット (Throughput)、1 秒あたりのクエリ レート QPS (Query Per Second)、および同時ユーザー数が含まれます。 -スレッド モデルですが、Redis は同時実行性の高いビジネス シナリオでは確かに強力なツールです。現在、Redis の QPS は 100,000、さらには 100 万レベルに達する可能性があります。これは完全に同時実行性が高いです。
高可用性: Redis の高可用性は主にマスター/スレーブ レプリケーション、センチネル (センチネル モード)、およびクラスター (クラスター モード) に反映されます
私の理解は大体このインタビュアーと同じです! !
Redis のシングル スレッドとは、Redis6 のリリース以降、コマンド操作を実行するために単一のスレッドを使用することを指します。
私の理解は、このインタビュアーとほぼ同じです。 !
Redis には、String、List、Hash、Set、ZSet の 5 つの基本データ型があり、さらに、Bitmaps、Geospatial、および HyperLogLog という 3 つの特別なデータ型があります。
データ型 | 簡単な説明 | 使用シナリオ |
---|---|---|
文字列 | String (文字列) は、Redis の最も単純で最も広く使用されているデータ構造であり、その内部は文字配列です。 String (文字列) は、変更を許可する動的文字列です。その構造的な実装は、Java の ArrayList に似ています (サイズ 10 の初期配列がデフォルトで構築されます)。これは、メモリの冗長割り当てのアイデアであり、プレとしても知られています。 - 割り当て。このアイデアにより、拡張によるパフォーマンスの消費を削減できます。文字列 (string) のサイズが拡張しきい値に達すると、文字列 (string) が拡張されます。文字列 (string) の拡張には主に 3 つの状況があります: 1. 長さが 1MB 未満で、拡張は 2 倍になります。元のサイズ; length = length * 2 2. 長さは 1MB より大きく、拡張後は 1MB ずつ増加します; length = length 1MB 3. 文字列の最大長は 512MBです | キャッシュ、カウンター、分散ロック、など。 |
List | Redis のリストは Java 言語の LinkedList に相当し、二重にリンクされたリストのデータ構造です (ただし、この構造設計はより賢明です。後で紹介します)。順次トラバーサルをサポートします。リンクされたリスト構造の挿入および削除操作は、時間計算量が O(1) で高速ですが、クエリは時間計算量が O(n) で遅くなります。 Redisのリスト(リスト)は単純なものではありません。 LinkedList ですが、クイックリスト - 「クイック リスト」、クイックリストは複数のジップリスト (圧縮リスト) で構成される双方向リストです; | リンク リスト、非同期キュー、Weibo フォロワー タイムライン リスト... |
Hash | Redis のハッシュ (辞書) は、Java 言語の HashMap に相当します。ハッシュ値に従って分散される順序付けされていない辞書です。内部要素はキーと値のペアに基づいています。保管する。ハッシュ(ディクショナリ)の実装もJavaのHashMap(JDK1.7)の構造と一致しており、そのデータ構造も配列のリンクリストから構成される2次元構造となっており、ノード要素は配列上でハッシュ化されています。ハッシュの衝突が発生した場合は、リンク リストが使用され、配列ノードで連結されます。 Redisのハッシュ(辞書)に格納される値は文字列値のみであり、またJavaのHashMapとは展開が異なります。 Java の HashMap は容量拡張時に一度で完了しますが、Redis はコアアクセスがシングルスレッドのパフォーマンス問題であることを考慮し、高いパフォーマンスを追求するためにプログレッシブリハッシュ戦略を採用しています。プログレッシブリハッシュとは、一度ではなく複数回実行することを意味するため、古いハッシュ構造を保持する必要があるため、Redis のハッシュ (辞書) は新旧 2 つのハッシュ構造を持つことになります。すべての値が新しいハッシュに移動された後にのみ、新しいハッシュは機能内の以前のハッシュを完全に置き換えます。 | ユーザー情報、ハッシュテーブル... |
Set | Redisの集合(セット)は、Java言語のHashSetに相当し、とその内部キー 値のペアは順序付けされておらず、一意です。すべての値が null である特殊な辞書を内部的に実装します。コレクション内の最後の要素が削除された後、データ構造は自動的に削除され、メモリが再利用されます。 | 重複削除機能、好き嫌い、共通の友人... |
ZSet | zset (順序セット) は、 Redisのデータ構造。 Java 言語の SortedSet と HashMap の組み合わせに似ており、set を使用して内部値の一意性を保証する一方で、値のスコア (重み) でソートします。この並べ替え機能は、スキップ リストによって実装されます。 zset (順序付きセット) の最後の要素値が削除された後、データ構造は自動的に削除され、メモリがリサイクルされます。 | ファン リスト、生徒のパフォーマンスの並べ替え、トラフィック ランキング、クリック ランキング... |
ビットマップ | ビットマップはビットマップと呼ばれますが、厳密にはビットマップではありません。データ・タイプ。ビットマップの最下層は文字列 (キーと値) のバイト配列です。通常の get/set を使用してビットマップの内容を直接取得および設定することも、Redis が提供するビットマップ操作 getbit/setbit を通じてバイト配列を「ビット配列」として扱うこともできます。ビットマップの「ビット配列」の各セルは、0 と 1 のみを格納できます。配列の添え字は、ビットマップではオフセットと呼ばれます。ビットマップを設定するとき、キーが存在しない場合は新しい文字列が自動的に生成されます。設定されたオフセットが既存のコンテンツの範囲を超える場合、ビット配列は自動的にゼロ拡張されます。 | 従業員パンチイン... |
Geospatial | Geospatial は、バージョン 3.2 以降に Redis によって追加された地理的位置 GEO モジュールです。 | 近くの人と WeChat をして、「近くのレストラン」をオンラインで注文します"... … |
HyperLogLog | HyperLogLog は、カーディナリティ統計を行うために使用されるアルゴリズムです。不正確な重複排除とカウント スキームを提供します (この不正確さはそれほど不正確ではありません) , 標準誤差は 0.81% で、これは UV 統計の許容誤差範囲です。 HyperLogLog の利点は、入力要素の数または量が非常に大きい場合でも、カーディナリティ計算のための記憶領域が固定されることです。 Redis では、各 HyperLogLog キーに必要なメモリは 12KB のみで、ほぼ 2^64 の異なる基数を計算できます。ただし、HyperLogLog がカウントできるのはカーディナリティのサイズ (つまり、データ セットのサイズとセットの数) だけであり、要素自体を保存することはできず、要素自体をセット コレクションのように保存することもできません。要素を返します。 | UV などの基本統計量 |
#私の理解は、おおよそこのインタビュアーと同じです! !
Redis のデータ構造では、EXPIRE キーの秒数を通じてキーの有効期限 (TTL) を設定できます。また、私たちは Redis キーが期限切れになると自動的に削除されると考えがちですが、この考えが正しくないことは明らかです。 Redis の設計では、パフォーマンスやメモリなどの包括的な要素が考慮され、一連の有効期限戦略が設計されます。##高パフォーマンスのサービスを保証するために、Redis は期限切れのキーを受動的に削除し、貪欲な戦略/確率的アルゴリズムを採用しています。デフォルトでは、10 秒ごとにスキャンします。具体的な戦略は次のとおりです:
3. 削除された期限切れキーの数が 25% を超えている場合は、手順 1
#私の理解は、おおよそこのインタビュアーと同じです! !
分散シナリオでは、一般的な分散ロック ソリューションには次のものが含まれます (方法を知っている場合は、ここで他の 2 つのタイプを使用できますが、知らない場合でも失敗しないでください) ! ):
データベース ロック メカニズムに基づいて実装された分散ロックRedis が分散ロックを実装するためのソリューションは次のとおりです。
set key value [EX 秒] [PX ミリ秒] ] [NX | ロック解除は許可されていますが、Redis にはそのような機能はありません。Lua スクリプトは複数の命令をアトミックに実行できるため、Lua スクリプトを介してのみ処理できます。最後に、ロック タイムアウトの問題を考慮する必要があります。クライアントがロックを解放しないと、間違いなく機能しません。したがって、ロックは、指定されたタイムアウト時間の範囲内に他のクライアントによってロックが解除されないことを保証することしかできません。タイムアウト後に自動的に解放される このような状況は難しいですが、次のように最適化できます:
Redis 分散ロック内で長いタスクを実行しないようにして、コードを実行します単一の JVM ロックと同じように、できるだけロック間隔内でロック範囲を最適化することを検討できます。
実環境のストレス テストとオンライン シミュレーション テストをさらに実行します。適切なロック タイムアウト時間を見積もるためのシナリオ
が増加します。 Sentinel の 1 マスターと複数のスレーブ環境などの新たな問題は、クライアントがマスター ノードのロックを申請するものの、同期が完了せず、マスター ノードがロックされてしまう可能性があります。現時点では、新しく選択されたマスター ノードのロックは無効です。
レッドロックはマスターとスレーブの同期の問題を解決しますが、新たな複雑な問題を引き起こします: したがって、RedLock では、要求されたロックの最小有効期間を計算する必要があります。クライアントがロックの申請に成功し、最初のキーが正常に設定された時刻が TF、最後のキーが正常に設定された時刻が TL、ロックのタイムアウトが TTL、異なるプロセス間のクロックの差が CLOCK_DIFF であると仮定します。ロックの最小有効期間は次のとおりです: TIME = TTL - (TF- TL) - CLOCK_DIFF Redis を使用して分散ロックを実装すると、分離できなくなります。サーバーのダウンタイムやその他の可用性の問題から、RedLock についても同様です。複数のサーバーがロックを申請した場合でも、サーバーがダウンした後の処理も考慮する必要があります。公式は AOF 永続化処理を使用することを推奨しています。 ただし、AOF 永続性は、通常の SHUTDOWN 命令でのみ再起動および復元できます。ただし、停電が発生した場合、最後の永続性から停電までのロック データが失われる可能性があります。サーバーが再起動すると、分散ロックのセマンティック エラーが発生する可能性があります。したがって、この状況を回避するために、Redis サービスの再起動後、最大クライアント TTL 以内に Redis サービスを利用できなくなる (ロック アプリケーション サービスは提供されない) ことが公式に推奨されています。これにより問題は確かに解決できますが、これが Redis サーバーのパフォーマンスに確実に影響を与えることは明らかであり、これがほとんどのノードで発生すると、システムは全体的に使用できなくなります。 #私の理解は、おおよそこのインタビュアーと同じです! ! Redis は非常に高速です。その主な理由は、Redis データがメモリに保存されることです。データはメモリ内にあるため、サーバーがダウンするか電源がオフになると、データはすべてが失われるため、Redis には障害によってすべての Redis データが失われないようにするための 2 つのメカニズムが用意されており、このメカニズムは Redis の永続化メカニズムと呼ばれます。 Redis には 2 つの永続化メカニズムがあります: #RDB(Redis DataBase) は、指定された時間間隔内にメモリ内のデータ セットのスナップショットをディスクに書き込むことを指します。RDB はメモリ スナップショット (メモリ データのバイナリ シーケンス) です。永続化の形式)、Redis からスナップショットが生成されるたびに、データを完全にバックアップします。 #コンパクトなストレージ、メモリ領域の節約 データは失われやすく、2 つのスナップショットの間に Redis サーバーで変更されたデータも失われやすくなります。 設定トリガー ルール シャットダウン トリガー 保存 bgsave #利点: データのバックアップがより完全になり、データ損失の可能性が低くなり、高いデータ整合性が必要なシナリオに適していますログ ファイルは読み取り可能であり、AOF は操作性が高く、ログ ファイルを操作することで修復できます AOF ログ長期間運用すると徐々にサイズが大きくなり、リストアに非常に時間がかかります。AOF ログは定期的にスリム化する必要があります (詳細は後述)リストア バックアップ速度が比較的遅い appendfsync always すべての Redis 書き込み操作は AOF ログに書き込まれます。Redis の同時実行数が、たとえ Redis が比較的少ない場合でも、Linux オペレーティング システムが提供する最大更新頻度をはるかに超えているため、理論上、Linux オペレーティング システムはこの構成を処理できません。この場合、この構成には IO 操作が含まれるため、パフォーマンスが非常に重視されるため、この構成は基本的に 1 秒に 1 回更新されません。バッファ内のデータは AOF ファイルに転送されます。この構成のデフォルトの戦略は、 Redis 構成ファイルは、パフォーマンスとデータの整合性の間の妥協と互換性があります。この構成では、理論的には、データは約 1 秒で失われます。 appendfsync no Redis プロセスは、バッファー内のデータを AOF ファイルに積極的に更新せず、オペレーティング システムの判断に直接任せます。この操作はお勧めできません。データが失われる可能性が非常に高くなります。 以前に AOF の欠点について述べたとき、AOF は Redis 書き込み命令を保存するためのログ追加形式であると述べましたが、これにより、多数の冗長な命令ストレージが発生し、AOF ログ ファイルが非常に大きくなりますこの場合、メモリを占有するだけでなく、回復が非常に遅くなる原因となるため、Redis はこの問題を解決するための書き換えメカニズムを提供します。 Redis の AOF 永続化メカニズムが再書き込みを実行した後、データを復元するための最小限の命令セットのみが保存されます。手動でトリガーしたい場合は、次の手順を使用できます。 AOF ファイルの書き換えは Redis のパフォーマンスに一定の影響を与えるため、気軽に自動書き換えを行うことはできません。Redis には自動 AOF 書き換え用の 2 つの構成インジケーターが用意されています。これら 2 つのインジケーターが満たされた場合にのみ書き換えが行われます。同時に: #auto-aof-rewrite-percentage 100: ファイルのメモリが元のメモリの 2 倍に達したときを指します auto-aof- rewrite-min-size 64mb: ファイル再書き込みの最小メモリ サイズを指します さらに、Redis 4.0 以降のほとんどの使用シナリオでは、永続化メカニズムとして RDB または AOF を単独で使用しませんが、次のことを考慮に入れてください。両方の利点を活かして組み合わせて使用してください。 両方を有効にすることをお勧めします。 データに敏感でない場合は、RDB のみを使用することもできます。 Redis は、メモリ ストレージに基づいたキーと値のデータベースです。メモリは高速ですが、スペースが小さいことがわかっています。物理メモリが上限に達すると、システムの実行が非常に遅くなります。 , そこで、Redis の最大メモリを設定します。Redis メモリが設定されたしきい値に達すると、メモリのリサイクルがトリガーされます。Redis は多くのメモリ削除戦略を提供します: noeviction: メモリ制限に達したため、クライアントが試行します。 より多くのメモリが使用される可能性があるコマンドを実行すると、エラーが返されます。簡単に言えば、読み取り操作は引き続き許可されますが、新しいデータの書き込みは許可されません。 できます。 Redis 3.0 で maxmemory_samples が 10 に設定されている場合、Redis の近似 LRU アルゴリズムは実際の LRU アルゴリズムに非常に近くなりますが、明らかに maxmemory_samples を 10 に設定すると、各サンプルがサンプルとして使用されるため、maxmemory_samples を 5 に設定するよりも多くの CPU 計算時間が消費されます。データが増加すると、計算時間も増加します。 Redis3.0 では maxmemory_samples と同じサイズのエリミネーション プールが追加されるため、Redis3.0 の LRU アルゴリズムは Redis2.8 の LRU アルゴリズムよりも正確です。最初に削除プールで削除を待っているキーと比較され、最後に最も古いキーが削除されます。実際には、削除対象に選択されたキーをまとめて比較し、最も古いキーが削除されます。 LRU には明らかな欠点があります。キーの人気を正確に表すことができません。キーがアクセスされたことがない場合、メモリの削除が発生する直前にユーザーによってアクセスされただけです。LRU アルゴリズムでは、これはホットキーとみなされます。 LFU (Least Frequently Used) は、Redis 4.0 で導入された除外アルゴリズムで、キーのアクセス頻度を比較してキーを除外します。 LRU と LFU の違い: LFU モードでは、Redis オブジェクト ヘッダーの 24 ビット lru フィールドが 2 つのセグメントに分割され、上位 16 ビットが格納されます。 - ldt (最終減分時間) と下位 8 ビットの logc (ロジスティック カウンター) を保存するビット。上位 16 ビットは、カウンタが最後に減少した時刻を記録するために使用されます。8 ビットしかないため、 は Unix の分のタイムスタンプを 2^16 で割って格納します。16 ビットで表現できる最大値は 65535 (65535) /24/60≒45.5)、約45.5日で戻ります(戻るとはモジュロ値が再び0から始まることを意味します)。 下位 8 ビットは、アクセス頻度の記録に使用されます。8 ビットが表すことができる最大値は 255 です。Logc は、実際の Rediskey アクセス数を記録することはできません。実際、名前からわかるように、アクセス数の対数を格納します。新しく追加された各キーの logc の初期値は 5 (LFU_INITI_VAL) であり、新しく追加された値が最初に選択されて削除されることはなく、logc が更新されます。キーにアクセスするたびに、さらに logc は時間の経過とともに減衰します。 ロジスティック カウンターは増加するだけでなく、減衰することもあります。増加と減衰のルールは、redis.conf を通じて構成することもできます。 #私の理解は、おおよそこのインタビュアーと同じです! ! キャッシュの内訳: 解決策: キャッシュ侵入: 解決策: キャッシュなだれ: この時点で、面接官の顔には長い間忘れていた笑顔が浮かんでいましたが、このコツさえつかめば、この面接は成功するはずです。 もちろん、この知識ポイントは数文で明確に説明することはできません。そのため、この記事を読んで簡単に理解できるようにすることをお勧めします。 Redis Distributed—— Completeマスター/スレーブ レプリケーション、Sentinel、およびクラスタリング>> この記事は、https://juejin.cn/post/7019088999792934926 から転載されました。著者: Li Ziba プログラミング関連の知識については、プログラミング入門をご覧ください。 !
回復速度が非常に速い
RDB トリガー ルールは、手動トリガーと自動トリガーの 2 つのカテゴリに分類されます。
AOF ログはファイルの形式で存在します。プログラムが AOF ログ ファイルに書き込むとき、実際の内容はカーネルによって割り当てられたファイル記述子に書き込まれ、メモリ バッファでは、カーネルはバッファ内のデータを非同期的にディスクにフラッシュします。バッファ内のデータがディスクにフラッシュされる前にサーバーがクラッシュすると、データは失われます。
Redis 構成ファイルにはバッファーを更新するための 3 つの構成があります:
bgrewriteaof
Redis 4.0 以降の再書き込みでは、RDB スナップショットが使用され、 AOF 命令の結合方法により、AOF ファイルの先頭は RDB スナップショットのデータのバイナリ形式であり、末尾はスナップショットの生成後に発生した書き込み操作の命令です。 AOF を単独で使用することは推奨されません。バグが発生する可能性があるためです。
volatile-lru: 有効期限が設定されているすべてのキーから、lru (最も最近使用されていない使用法 - 最も最近使用されていない使用法) を使用します。削除のためのアルゴリズム。有効期限がなく、永続化する必要があるデータが削除対象として選択されないようにします。
volatile-ttl: 、TTL が小さいほど、早く削除されます
allkeys-lfu: すべてのキーに対して LFU 削除アルゴリズムを使用する
キャッシュされたデータが比較的固定されている場合は、ホットスポット データを期限切れにしないように設定してみてください。
キャッシュされたデータが頻繁に更新される場合、またはキャッシュの更新プロセスに時間がかかる場合は、タイミング スレッドを使用してキャッシュをアクティブに再構築するか、キャッシュの有効期限が切れる前にキャッシュを遅らせることができます。すべてのリクエストが対応するキャッシュに常にアクセスできるようにするための時間。
データベースがクエリされない場合は、キャッシュに null 値を設定します。
以上が2023 年の Redis の高頻度面接の質問の共有 (回答分析付き)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。