【体験投稿】分散システムにRedisが必須なのはなぜでしょうか?

【体験投稿】分散システムにRedisが必須なのはなぜでしょうか?

ビジネスアプリケーションを作成するプログラマーのほとんどは、実際の開発で Redis を使用する際に Set Value と Get Value の 2 つの操作の使用方法しか知らないため、Redis の全体的な理解が不足しています。

そこで、あえてRedisを題材にして、Redisのよくある問題点をまとめて、皆さんの知識の盲点を補ってみたいと思います。

この記事では、以下の点に焦点を当てます。

  • Redisを使用する理由
  • Redis を使用することの欠点は何ですか?
  • シングルスレッドの Redis がなぜこんなに高速なのでしょうか?
  • Redis のデータ型と各データ型の使用シナリオ
  • Redis の有効期限戦略とメモリ削除メカニズム
  • Redis とデータベースの二重書き込みの一貫性の問題
  • キャッシュ侵入とキャッシュアバランシェの問題に対処する方法
  • Redisの同時競合キー問題を解決する方法

Redisを使用する理由

プロジェクトで Redis を使用する場合は、パフォーマンスと同時実行性の 2 つの側面を考慮する必要があると思います。

もちろん、Redis には分散ロックなどの他の機能もありますが、分散ロックなどの他の機能だけが必要な場合は、Redis の代わりに Zookeeper などの他のミドルウェアがあります。したがって、この質問には、主にパフォーマンスと同時実行性の 2 つの観点から答える必要があります。

パフォーマンス

下の図に示すように、実行に特に長い時間がかかり、結果が頻繁に変更されない SQL に遭遇した場合は、実行結果をキャッシュに入れることが特に適しています。このようにして、後続のリクエストはキャッシュから読み取られ、リクエストに迅速に応答できるようになります。

話はそれますが、突然ですが、迅速な対応の基準についてお話ししたいと思います。この応答時間には、相互作用効果に応じて固定された標準はありません。

しかし、かつて誰かが私にこう言いました。「理想的には、ページジャンプは瞬時に解決される必要があり、ページ内の操作も瞬時に解決される必要があります。」

さらに、複数の指を必要とする時間のかかる操作では、ユーザーに最高のエクスペリエンスを提供するために、進行状況のプロンプトを表示し、いつでも一時停止またはキャンセルできるようにする必要があります。 「

では、一瞬、一瞬、あるいは指をパチンと鳴らすのにはどれくらいの時間がかかるのでしょうか?

『マハサンギカ・ヴィナヤ』には次のように書かれています。

一つの瞬間は一つの考えであり、二十の考えは一つの瞬間であり、二十の瞬間は一つの指パッチンであり、二十の指パッチンは一つのルユであり、二十のルユは一つの瞬間であり、一日と一夜には三十の瞬間がある。

したがって、注意深く計算すると、瞬間は 0.36 秒、一瞬は 0.018 秒、指をパチンと鳴らす時間は 7.2 秒になります。

同時

下の図に示すように、同時実行性が高い場合、すべてのリクエストがデータベースに直接アクセスし、データベースに接続例外が発生します。

このとき、リクエストがデータベースに直接アクセスするのではなく、まず Redis にアクセスするように、Redis を使用してバッファリング操作を行う必要があります。

Redis を使用することの欠点は何ですか?

誰もが長い間 Redis を使用してきたので、この問題は理解されている必要があります。基本的に、Redis を使用する際にはいくつかの問題が発生しますが、一般的な問題はごくわずかです。

答えるべき主な質問は 4 つあります。

キャッシュとデータベースの二重書き込みの一貫性の問題

  • キャッシュアバランシェ問題
  • キャッシュ故障問題
  • キャッシュの同時実行競合問題
  • 個人的には、プロジェクトではこれら 4 つの問題がよく発生すると思います。具体的な解決策については後述します。

シングルスレッドの Redis がなぜこんなに高速なのでしょうか?

この問題は、Redis の内部メカニズムの調査です。私のインタビュー経験によれば、Redis がシングルスレッドの動作モデルであることを知らない人が多いようです。したがって、この質問はまだ検討されるべきです。

答えは主に以下の3点です。

  • 純粋なメモリ操作
  • シングルスレッド操作により頻繁なコンテキスト切り替えを回避
  • ノンブロッキングI/O多重化メカニズムを採用

余談: ここで、I/O 多重化メカニズムについて注意深く説明する必要があります。この用語は非常に一般的なので、ほとんどの人がその意味を理解していないからです。

例: Xiaoqu は S 市に宅配店をオープンし、市内の宅配サービスを担当しています。資金の制約のため、Xiaoqu は配達員のグループを雇いました。その後、シャオクさんは資金が足りず、配達用の車を買うのに足る金額しか残っていないことに気づいた。

ビジネスモデル1

顧客が荷物を送るたびに、Xiaoqu は宅配業者に荷物を預け、その後宅配業者が車で荷物を配達に向かいます。

徐々に、Xiaoqu はこの動作モードに次のような問題があることを発見しました。

  • 基本的に、何十人もの配達員が車両を入手することに時間を費やしており、そのほとんどは暇な状態です。車を入手できる人なら誰でも荷物を配達できます。
  • 速達便が増えるにつれて、宅配便業者の数も増加しました。 Xiao Qu さんは、宅配店がどんどん混雑してきて、新しい配達員を雇う方法がないことに気付きました。
  • 宅配業者間の調整には時間がかかります。

上記の欠点を考慮して、Xiaoqu は自分の失敗から教訓を得て、次のビジネス モデルを提案しました。

ビジネスモード2

Xiaoqu は配達人を 1 人だけ雇いました。その後、小区は顧客から送られた速達便を配達先ごとに印を付け、一か所に一つずつ置いていった。

***、宅配業者は荷物を一つずつ受け取り、配達に行き、次の荷物を受取るために戻ってきます。

上記の 2 つのビジネス方法を比較すると、2 番目の方法の方が効率的で優れていると思いませんか?

上記の例えでは、

  • 各宅配便 → 各スレッド
  • 各宅配便 → 各ソケット(I/Oフロー)
  • 配送先→ソケットの状態が異なる
  • クライアントがエクスプレスリクエストを送信 → クライアントからのリクエスト
  • Xiaoquのビジネスモデル → サーバー上で実行されるコード
  • 車1台 → CPUコア数

したがって、次のような結論に達します。

  • 最初の動作モードは従来の同時実行モデルであり、各 I/O ストリーム (express) は新しいスレッド (courier) によって管理されます。
  • 2 番目の動作モードは I/O 多重化です。各 I/O ストリームの状態 (各クーリエが配信されている場所) を追跡することで、複数の I/O ストリームを管理するスレッド (クーリエ) は 1 つだけです。

次の図は、実際の Redis スレッド モデルに類似しています。

簡単に言えば、redis クライアントが動作しているときに、さまざまなイベント タイプのソケットが生成されます。

サーバー側には、それをキューに入れる I/O 多重化プログラムがあります。次に、ファイル イベント ディスパッチャーはキューからファイルを順番に取得し、さまざまなイベント ハンドラーに転送します。

この I/O 多重化メカニズムのために、Redis は select、epoll、evport、kqueue などの多重化関数ライブラリも提供していることに注意してください。これらについては自分で学習することができます。

Redis のデータ型と各データ型の使用シナリオ

この質問は非常に基本的なものだと思われますか?私もそう思います。しかし、面接経験に基づくと、少なくとも 80% の人がこの質問に答えることができません。

暗記するのではなく、プロジェクトで使用した後、類推して覚えることでより深い理解が得られるようにすることをお勧めします。基本的に、有能なプログラマーは 5 つのタイプすべてを使用します。

これについては特に言うことはありません。これは最も一般的な set/get 操作です。値は文字列または数値にすることができます。一般的に、いくつかの複雑なカウント関数をキャッシュします。

ハッシュ

ここで、Value は構造化されたオブジェクトを格納し、その中で特定のフィールドを操作する方が便利です。

シングル サインオンを実行していたとき、CookieId をキーとして使用し、キャッシュの有効期限を 30 分に設定して、このデータ構造を使用してユーザー情報を保存しました。これにより、セッションのような効果を非常にうまくシミュレートできます。

リスト

リスト データ構造を使用すると、単純なメッセージ キュー機能を実行できます。もう 1 つは、lrange コマンドを使用して Redis ベースのページングを実行できることです。これは、優れたパフォーマンスと優れたユーザー エクスペリエンスを実現します。

セット

Set は繰り返されない値のコレクションであるためです。したがって、グローバル重複排除機能を実行できます。重複排除に JVM 独自のセットを使用しないのはなぜですか?

当社のシステムは一般的にクラスターで展開されるため、JVM に付属するセットを使用するのは面倒です。グローバル重複排除を行うためだけにパブリックサービスを開始するのは面倒すぎます。

さらに、積、和、差などの演算を使用することで、共通の好み、すべての好み、独自の好み、その他の関数を計算することができます。

ソートセット

Sorted Set には追加の重みパラメータ Score があり、セット内の要素はスコアに従ってソートできます。

アプリケーションのランキングや TOP N 操作に使用できます。ソート セットは遅延タスクに使用できます。 *** 1 つのアプリケーションは範囲検索を行うことです。

Redis の有効期限戦略とメモリ削除メカニズム

この質問は非常に重要です。 Redis が効果的に使用されているかどうかを表示できます。

たとえば、Redis が 5G のデータしか保存できないのに、10G を書き込むと、5G のデータが削除されます。削除するにはどうすればいいですか?この質問について考えたことはありますか?

また、データの有効期限が設定されていますが、有効期限が来てもメモリ使用量は依然として高いままです。その理由について考えたことはありますか?

回答: Redis は、定期的な削除 + 遅延削除の戦略を採用しています。

スケジュールされた削除戦略を使用しないのはなぜですか?

スケジュールされた削除: タイマーを使用してキーを監視し、有効期限が切れると自動的に削除します。メモリは時間内に解放されますが、CPU リソースを大量に消費します。

大量の同時リクエストがある場合、CPU はキーを削除するのではなく、リクエストの処理に時間を使う必要があるため、この戦略は採用されません。

スケジュールされた削除 + 遅延削除はどのように機能しますか?

定期的な削除。 Redis は、期限切れのキーがあるかどうかをデフォルトで 100 ミリ秒ごとにチェックします。期限切れのキーがある場合は削除されます。

Redis は 100 ミリ秒ごとにすべてのキーをチェックするのではなく、チェックするキーをランダムに選択することに注意してください (100 ミリ秒ごとにすべてのキーをチェックすると、Redis が停止します)。

したがって、定期的な削除戦略のみを採用した場合、多くのキーが時間どおりに削除されません。そこで、遅延削除が役に立ちます。

つまり、キーを取得すると、有効期限が設定されていれば、Redis はキーの有効期限が切れているかどうかを確認します。期限が切れた場合は、この時点で削除されます。

定期削除+遅延削除で他に問題はないでしょうか?

いいえ、定期削除時にキーが削除されない場合は、そうではありません。次に、キーをすぐに要求しなかったため、遅延削除は有効になりませんでした。このように、Redis のメモリはどんどん高くなっていきます。次に、メモリ削除メカニズムを採用する必要があります。

redis.conf には次の設定行があります:

  1. # 最大メモリポリシー揮発性LRU

この設定は、メモリ削除戦略を設定するためのものです (え、これまで一度も設定したことがなかったのですか? 自分を振り返ってみてください):

  • noeviction: 新しく書き込まれたデータを収容するのに十分なメモリがない場合、新しい書き込み操作でエラーが報告されます。誰も使ってないと思います。
  • allkeys-lru: 新しく書き込まれたデータを収容するのに十分なメモリがない場合は、キー空間内で最も最近使用されていないキーを削除します。この方法を使用することが推奨されており、現在のプロジェクトでもこの方法が使用されています。
  • allkeys-random: 新しく書き込まれたデータを収容するのに十分なメモリがない場合、キーはキー空間からランダムに削除されます。おそらく誰も使わないでしょう。最も使用頻度の低いキーを削除しない場合は、ランダムに削除します。
  • volatile-lru: 新しく書き込まれたデータを収容するのに十分なメモリがない場合、有効期限が設定されたキー空間内で最も最近使用されていないキーを削除します。この状況は通常、Redis がキャッシュと永続ストレージの両方として使用される場合に発生します。推奨されません。
  • 揮発性ランダム: 新しく書き込まれたデータを収容するのに十分なメモリがない場合、有効期限が設定されたキーがキー空間からランダムに削除されます。それでもお勧めできません。
  • volatile-ttl: 新しく書き込まれたデータを格納するためのメモリが不足している場合、有効期限が設定されたキー空間では、有効期限が早いキーが最初に削除されます。推奨されません。

PS: キーに有効期限が設定されていない場合、前提条件は満たされません。すると、volatile-lru、volatile-random、および volatile-ttl ポリシーの動作は、基本的に noeviction (削除なし) と同じになります。

Redis とデータベースの二重書き込みの一貫性の問題

一貫性の問題は一般的な分散問題であり、さらに結果的一貫性と強い一貫性に分けることができます。データベースとキャッシュが二重に書き込まれると、必然的に不整合が生じます。

この質問に答えるには、まず前提を理解する必要があります。つまり、データの一貫性が強く求められる場合、キャッシュを配置することはできません。私たちにできるのは、最終的な一貫性を確保することだけです。

さらに、私たちが実装したソリューションは、不整合の可能性を根本的に減らすことはできますが、完全に回避することはできません。したがって、強い一貫性要件を持つデータはキャッシュできません。

回答: まず、正しい更新戦略を採用し、最初にデータベースを更新してから、キャッシュを削除します。第二に、キャッシュ削除に失敗する問題が発生する可能性があるため、メッセージキューを使用するなどの補償策を提供することができる。

キャッシュ侵入とキャッシュアバランシェの問題に対処する方法

正直に言うと、これら 2 つの問題は、一般的な中小規模の従来のソフトウェア企業が遭遇する可能性は低いです。大規模な同時プロジェクトがある場合、トラフィックは数百万程度になります。これら二つの問題について深く検討する必要があります。

キャッシュ侵入とは、ハッカーがキャッシュに存在しないデータを故意に要求し、すべての要求がデータベースに送信され、データベース接続に異常が発生することを意味します。

キャッシュ侵入ソリューション:

  • ミューテックス ロックを使用すると、キャッシュが無効な場合に、まずロックを取得してからデータベースを要求します。ロックが取得されない場合は、しばらくスリープしてから再試行してください。
  • 非同期更新戦略を採用すると、キーに値があるかどうかに関係なく、キーが直接返されます。 Value 値はキャッシュの有効期限を維持します。キャッシュの有効期限が切れると、スレッドが非同期的に開始され、データベースを読み取ってキャッシュを更新します。キャッシュの事前加熱(プロジェクトを開始する前にキャッシュをロードすること)が必要です。
  • リクエストが有効かどうかを迅速に判断できるインターセプト メカニズムを提供します。たとえば、ブルーム フィルターを使用して、一連の有効なキーを内部的に維持します。リクエストに含まれるキーが合法かつ有効かどうかを素早く判断します。違法な場合は、直接返品してください。

キャッシュアバランシェとは、キャッシュの広い範囲が同時に障害を起こすことを意味します。このとき、別のリクエストの波が来て、リクエストがすべてデータベースにプッシュされ、データベース接続異常が発生します。

キャッシュアバランチソリューション:

  • 一括有効期限切れを回避するために、キャッシュ有効期限にランダムな値を追加します。
  • ミューテックス ロックを使用しますが、このソリューションのスループットは大幅に低下します。
  • ダブルバッファリング。 CacheA と CacheB という 2 つのキャッシュがあります。キャッシュ A の有効期限は 20 分ですが、キャッシュ B には有効期限がありません。キャッシュウォーミング操作を自分で実行します。

次に、次の点に分解します。キャッシュ A からデータベースを読み取り、データがある場合は直接返します。 A にデータがない場合、B から直接データを読み取り、直接戻り、更新スレッドを非同期的に開始します。これにより、キャッシュ A とキャッシュ B が同時に更新されます。

Redisの同時競合キー問題を解決する方法

基本的に問題は、複数のサブシステムが同時にキーを設定することです。この時に何に注意すればいいのか考えたことはありますか?

事前に Baidu で検索したところ、ほとんどの回答で Redis トランザクション メカニズムの使用が推奨されていることがわかったことを説明する必要があります。

Redis のトランザクション メカニズムの使用はお勧めしません。当社の本番環境は基本的に Redis クラスター環境であるため、データ シャーディング操作が実行されます。

トランザクションに複数のキー操作が含まれる場合、これらの複数のキーは必ずしも同じ redis サーバーに保存されるわけではありません。したがって、Redis のトランザクション メカニズムはまったく役に立ちません。

このキーを操作した場合、注文は必要ありません

この場合、分散ロックを用意し、全員がそのロックを取得しようとします。ロックを取得したら、set 操作を実行するだけです。比較的簡単です。

このキー操作が必要な場合、注文

key1 があると仮定します。システム A は key1 を valueA に設定する必要があり、システム B は key1 を valueB に設定する必要があり、システム C は key1 を valueC に設定する必要があります。

key1 の値は valueA > valueB > valueC の順に変化することが予想されます。この場合、データベースにデータを書き込むときにタイムスタンプを保存する必要があります。

タイムスタンプが次のとおりであると仮定します。

  • システムA キー1 {valueA 3:00}
  • システム B キー 1 {valueB 3:05}
  • システム C キー 1 {値 C 3:10}

したがって、システム B が最初にロックを取得し、key1 を {valueB 3:05} に設定するとします。次に、システム A はロックを取得し、その valueA のタイムスタンプがキャッシュ内のタイムスタンプよりも早いことを検出し、設定操作を実行しません。

キューを使用してセット メソッドをシリアル アクセスに変換するなどの他の方法も可能です。つまり、柔軟であることです。

要約する

この記事では、Redis の一般的な問題をまとめます。それらのほとんどは私が仕事で遭遇した質問であり、いくつかは他の人を面接するときに聞きたい質問です。

また、直前に詰め込むことはお勧めできません。実際に経験豊富なエンジニアに会ったら、彼らの質問で簡単に混乱させられるかもしれません。 ***、皆さんが何か得られることを願っています。

<<:  データ重力がクラウドコンピューティングの導入にどのように影響し、役立つか

>>:  クラウド コンピューティングが転換点に到達。レノボのIT管理クラウドサービスはMSP戦争の突破を目指す

推薦する

Pacificrack: 中秋節フラッシュセール、複数の高構成 VPS が年間 13.15 ドルから

中秋節期間中、Pacificrack は VPS フラッシュセールを開始しました。多くの高構成 VP...

教育用分類情報ウェブサイトを促進するための代替思考

この記事は、黄家朗による教育インターネット マーケティング シリーズの 2 回目です。分類情報 We...

#12.12# onetechcloud: すべての VPS が 20% オフ、香港 cn2、米国トリプルネットワーク cn2、米国 cn2 高防御

onetechcloudは香港に新しいデータセンターを追加し、中国電信はCN2を行き来し、中国聯通と...

ソフトウェア製品を迅速にリリースするのに役立つ 13 のクラウドネイティブ ツール

過去 10 年間でクラウド コンピューティングは大きく成長しました。ガートナー社によると、世界のパブ...

企業はクラウドコンピューティングのためのIT戦略を再考する必要がある

クラウド コンピューティング戦略は、クラウド コンピューティング リソースにコミットするだけではあり...

星を選んでください! Mobvistaが「2021 Cloud Native Pioneer Award」を受賞

クラウド コンピューティングの時代を迎えるにつれ、クラウドに移行し、大きな進歩を遂げる企業がますます...

SEOmoz CEO ランド・フィッシュキンが検索最適化について語る

5月25日、厦門でグローバル検索エンジン戦略会議が開催されました。SEOmoz CEO の Rand...

草の根ウェブマスターがウェブサイトを構築して利益を上げる方法: ウェブサイトの収益構造の分析

現在、中国には、各業界のウェブサイト、ニュースや情報サイト、ブログサイトなど、大小さまざまなウェブサ...

Baidu アップデート: リンク取引は行き止まりか?

11月5日、百度はプレスリリースを発表し、リンクアルゴリズムを更新する予定であることを皆に知らせまし...

Spring の組み込み分散ロックを使用したことがありますか?

環境: SpringBoot2.7.12この記事では、Spring Integrationが提供する...

Emissary Ingress を OPA と統合する方法

翻訳者 |李睿校正:孫淑娟API ゲートウェイは、マイクロサービスを公開する上で重要な役割を果たしま...

在庫: クラウド コンピューティングは製造業界にどのようなメリットをもたらしますか?

クラウド コンピューティングは現在、製品の設計方法や顧客による使用方法から、製造業者の運営方法やサプ...

[クラウドネイティブ] Containerd ctr と crictl クライアントコマンドの紹介と実践的な操作 (nerdctl)

1. 概要Docker ランタイムの後継である Containerd は、Kubernetes 1....

ウェブサイトのキーワードランキングが不安定になる理由

SEO 自体はゲームなので、誰と対戦しているかに注意してください。すでにいくつかの人気キーワードで上...