Redis アーキテクチャの進化を理解するための 1 つの記事

昨今、Redisの普及が進み、多くのプロジェクトで利用されています.Redisを利用する際、Redisがいかに安定して高性能なサービスを提供できるかを考えたことはありますか?

  • Redisを使うシナリオは非常にシンプルですが、スタンドアローン版のRedisだけを使っても問題はありませんか?

  • Redis がクラッシュしてデータが失われた場合はどうすればよいですか? ビジネス アプリケーションが影響を受けないようにするにはどうすればよいですか?

  • なぜマスター/スレーブ クラスタが必要なのですか? その利点は何ですか?

  • シャードクラスターとは何ですか? 分割クラスターは本当に必要ですか?

  • ...

Redis についてある程度の知識がある場合は、「データの永続性、マスター/スレーブ レプリケーション、センチネル、およびシャード クラスター」の概念について聞いたことがあるはずです。それらの違いと接続は何ですか?

このような疑問がある場合は、この記事で 0 から 1、次に 1 から N に進み、安定した高パフォーマンスの Redis クラスターを構築するための手順を順を追って説明します。

このプロセスでは、安定性と高いパフォーマンスを実現するために Redis が採用した最適化ソリューションとその理由を知ることができます。

これらの原則を習得すると、Redis を使用するときに「簡単に」実行できるようになります。

最も単純なものから始めます: スタンドアロンの Redis

まず、最も単純なシナリオから始めます。

ビジネス アプリケーションがあり、アプリケーションのパフォーマンスを向上させるために Redis を導入する必要がある場合、この時点で、次のようにスタンドアロン バージョンの Redis をデプロイすることを選択できます。

このアーキテクチャは非常に単純です. ビジネス アプリケーションは Redis をキャッシュとして使用し、MySQL からデータをクエリしてから、それを Redis に書き込み、ビジネス アプリケーションは Redis からデータを読み取ることができます。速いです。

ビジネスの規模が大きくない場合は、基本的にこのようなアーキテクチャ モデルでニーズを満たすことができます。シンプルじゃないですか?

時間が経つにつれて、ビジネス ボリュームが徐々に増加し、ますます多くのデータが Redis に保存されます. この時点で、ビジネス アプリケーションはますます Redis に依存しています.

ある日突然、何らかの理由で Redis がダウンする. このとき、すべてのビジネス トラフィックがバックエンドの MySQL にヒットし、MySQL への圧力が急激に高まります. 深刻な場合には、MySQL を圧倒することさえあります.

この時、あなたは何をすべきですか?

あなたの解決策は、サービスを提供し続けることができるように、Redis をすばやく再起動することであるに違いないと思います。

ただし、Redis のデータは以前はメモリにあったため、ここで Redis を再起動しても、以前のデータは失われます (永続化が有効になっていない場合)。再起動後、Redis は正常に動作しますが、Redis にはデータがないため、ビジネス トラフィックは引き続きバックエンドの MySQL にヒットし、MySQL へのプレッシャーは依然として大きくなります。

この問題を解決する良い方法はありますか?

Redis はデータをメモリに保存するだけなので、このデータのコピーをディスクに書き込むこともできますか?

この方法を使用すると、Redis の再起動時に、ディスク内のデータをメモリにすばやく "復元" して、サービスを正常に提供し続けることができます。

はい、これは良い解決策です. メモリ データをディスクに書き込むプロセスは、「データの永続化」です。

データの永続性: 備えておく

ここで、想定される Redis データの永続性は次のようになります。

しかし、データの永続化のために具体的に何をすべきでしょうか?

考えられる最も簡単な解決策は、Redis が書き込み操作を実行するたびに、メモリの書き込みに加えて、次のようにコピーをディスクに書き込むことだと思います。

はい、これが最も簡単で直接的な解決策です。

しかし、よく考えてみると、このソリューションには問題があります。クライアントのすべての書き込み操作は、メモリとディスクの両方に書き込む必要があり、ディスクへの書き込みにかかる時間は、メモリへの書き込みよりもはるかに遅いことは間違いありません! これは、Redis のパフォーマンスに必然的に影響します。

この問題を回避するには?

この時点で、ディスクへの書き込みの詳細を分析する必要があります。

メモリ データをディスクに書き込むには、実際には次の 2 つの手順があることは誰もが知っています。

  1. プログラムがファイルを書き込むための PageCache (書き込み)

  2. PageCache をディスクにフラッシュする (fsync)

具体的には、次のようになります。

データ永続化の最も大雑把な考え方は前述のとおり.Redisメモリに書き込んだ後、PageCache + fsyncディスクに同期して書き込む.もちろん、ディスクは全体の書き込み速度を遅くするため.

最適化する方法は?これも非常に簡単です。Redisはメイン スレッドによってメモリを書き込み、メモリが書き込まれた後に結果をクライアントに返します。次に、Redis は「別のスレッド」を使用してディスクに書き込みます。メイン スレッドは、ディスクへの書き込みを回避できます。パフォーマンスへの影響。

この永続化スキームは、実際にはよく耳にする Redis AOF (Append Only File) です。

Redis AOF 永続性は、次の 3 つのブラッシング メカニズムを提供します。

  1. appendfsync always: メインスレッドが fsync を同期します

  2. appendfsync いいえ: OS fsync による

  3. appendfsync everysec: 1 秒ごとのバックグラウンド スレッド fsync

データのリアルタイム永続性を解決した後、別の問題に直面します. データはリアルタイムでAOFに書き込まれます. 時間が経つにつれて、AOFファイルはますます大きくなるため、AOFを使用して復元すると非常に遅くなります. 。 私は何をすべきか?

Redis が提供する AOF 書き換えソリューションは、通称 AOF の「スリミング」と呼ばれ、名前が示すとおり、AOF のボリュームを圧縮することです。

AOF はすべての書き込みコマンド (set k1 v1、set k1 v2 の実行など) を記録するため、実際には、データの最終バージョン v2 のみを気にします。AOF 書き換えはこの機能を利用します. AOF のボリュームがどんどん大きくなる (設定されたしきい値を超える) と, Redis は定期的に新しい AOF を書き換えます. この新しい AOF はデータの最終バージョンのみを記録します.

これにより、AOF ボリュームが圧縮されます。

さらに、角度を変えて、データを永続化する他の方法を考えることができますか?

この時点で、Redis の使用シナリオを考慮する必要があります。

Redis を使用するとき、通常どのようなシナリオで使用するかを思い出してください。

はい、キャッシュします。

Redis をキャッシュとして使用するということは、すべてのデータが Redis に保存されていなくても、キャッシュにないデータについては、ビジネス アプリケーションがバックエンド データベースにクエリを実行して結果を取得できることを意味しますが、バックエンド データベースにクエリを実行する速度が低下します。 -end データは遅くなりますが、業績への影響はありません。

この機能に基づいて、Redis データの永続化を「データ スナップショット」の方法で行うこともできます

では、データ スナップショットとは何でしょうか。

簡単に言えば、次のように理解できます。

  1. Redis を水の入ったカップと想像してください。Redis にデータを書き込むことは、このカップに水を注ぐことと同じです。

  2. このとき、カメラでウォーターカップの写真を撮ります.写真を撮った瞬間に、ウォーターカップの水容量が写真に記録されます.これは、ウォーターカップのデータスナップショットです.

つまり、Redis のデータ スナップショットは、特定の瞬間に Redis にデータを記録し、このデータ スナップショットをディスクに書き込むだけで済みます。

その利点は、永続性が必要なときに「一度」だけディスクにデータを書き込み、それ以外のときにディスクを操作する必要がないことです。

このソリューションに基づいて、「定期的に」Redis のデータ スナップショットを作成し、データをディスクに永続化できます。

このソリューションは、私たちがよく耳にする Redis RDB です. RDB は、データの永続性のために「スケジュールされたスナップショット」を使用します. その利点は次のとおりです:

  1. 永続ファイルが小さい (バイナリ + 圧縮)

  2. ディスクへの書き込み頻度が低い (スケジュール書き込み)

Redis がキャッシュとしてのみ使用され、失われたデータ (バックエンド データベースからのクエリ)、この永続化方法は非常に適しています。

持続性ソリューションの選択を求められた場合は、次のように選択できます。

  1. ビジネスがデータ損失に敏感でない場合は、RDB を選択してください

  2. このビジネスには、データの整合性に対する要件が比較的高いため、AOF を選択してください

RDB と AOF を理解したら、さらに考えてみましょう.データの整合性を確保するだけでなく、永続ファイルを小さくして復元を高速化する方法はありますか?

前述の RDB と AOF の特性を確認してみましょう。

  1. RDBはバイナリ+データ圧縮モードで格納され、ファイルサイズが小さい

  2. AOF はすべての書き込みコマンド、最も完全なデータを記録します

それぞれの強みを活かせるか?

もちろん、これはRedis の「ハイブリッド永続化」です。

データの整合性を高めたい場合は、RDB を使用するだけでなく、AOF の最適化に注目する必要があります。

具体的には、AOF が書き換えを行う場合、Redis はまずデータ スナップショットを AOF ファイルに RDB 形式で書き込み、その間に生成された各書き込みコマンドを AOF ファイルに追加します。

RDB はバイナリ圧縮で記述されるため、AOF ファイルのサイズは小さくなります。

AOF ボリュームはさらに圧縮されるため、AOF を使用してデータを復元すると、復元時間が短縮されます。

Redis バージョン 4.0 以降では、ハイブリッド永続性のみがサポートされます。

注: ハイブリッド永続性は AOF 書き換えの最適化です。つまり、AOF + AOF 書き換えに基づく必要があります。

このような最適化により、Redis はインスタンスのダウンタイムを心配する必要がなくなり、ダウンタイムが発生した場合、永続ファイルを使用して Redis のデータをすばやく復元できます。

しかし、それは大丈夫ですか?

よく考えてみてください.永続ファイルを最小限に最適化しましたが、データの復元にはまだ時間がかかります.この間、ビジネスアプリケーションはサービスを提供できません.私たちは何をすべきですか?

インスタンスがダウンした場合、データを復元することによってのみ解決できます.複数の Redis インスタンスをデプロイし、これらのインスタンスのデータをリアルタイムで同期させて、1 つのインスタンスがダウンしたときに残りのインスタンスの 1 つを選択できるようにすることはできますか?継続するインスタンス サービスを提供するだけです。

そうです、これが次に説明する「主従複製:複数コピー」です。

マスター/スレーブ レプリケーション: 複数のコピー

複数の Redis インスタンスをデプロイでき、アーキテクチャ モデルは次のようになります。

ここでは、リアルタイムで読み書きを行うノードをマスター、リアルタイムでデータを同期するもう一方のノードをスレーブと呼びます。

マルチコピー方式を採用する利点は次のとおりです。

  1. 利用できない時間を短縮する: マスターがダウンしている場合、手動でスレーブをマスターに昇格させてサービスを提供し続けることができます

  2. 読み取りパフォーマンスの向上: スレーブに読み取り要求の一部を共有させて、アプリケーションの全体的なパフォーマンスを向上させます

このソリューションは優れており、データの回復時間を節約するだけでなく、パフォーマンスも向上させます。

しかし、その問題は、マスターがダウンしたときに、スレーブを「手動で」マスターに昇格させる必要があり、このプロセスにも時間がかかることです。

データの復元よりもはるかに高速ですが、それでも人間の介入が必要です。手動による介入が必要になったら、人間の反応時間と操作時間をカウントする必要があるため、この期間中もビジネス アプリケーションは影響を受けます。

この切り替えプロセスを自動化できますか?

Sentinel: フェイルオーバー

自動的に切り替えたい場合は、人に頼ってはいけません。

ここで、マスターの健康状態をリアルタイムで監視する「オブザーバー」を導入できます.このオブザーバーは「センチネル」です.

どうやってするの?

  1. センチネルは定期的にマスターに正常かどうかを尋ねます

  2. マスターは正常に応答し、ステータスが正常であることを示し、応答タイムアウトは異常を示します

  3. センチネルが例外を検出し、マスターとスレーブの切り替えを開始します

このソリューションを使えば、プロセスに人間が介入する必要がなくなり、すべてが自動化されます。すばらしいと思いませんか。

しかし、ここで別の問題があり、マスターの状態が正常であるにもかかわらず、センチネルがマスターに問い合わせたときに、それらの間のネットワークに問題がある場合、センチネルは「判断を誤る」可能性があります

この問題を解決するには?

1 つのセンチネルが判断を誤るので、複数のセントリーを配置して、それらを異なるマシンに分散し、一緒にマスターの状態を監視できるようにすることができます。プロセスは次のようになります。

  1. 複数の歩哨が定期的にマスターに正常かどうかを尋ねます

  2. マスターは正常に応答し、ステータスが正常であることを示し、応答タイムアウトは異常を示します

  3. セントリーは、マスターが異常であると判断すると(ネットワークの問題かどうか)、他のセントリーに問い合わせます.複数のセントリー(しきい値を設定)がマスターに異常であると判断した場合、マスターが本当に異常であると判断されます.失敗した。

  4. 複数のセンチネルがネゴシエートされた後、マスターに障害があると判断され、マスターとスレーブの切り替えが開始されます

そこで、複数のセンチネルを使ってお互いに交渉してマスターのステータスを判断することで、誤判断の確率を大幅に下げることができます。

センチネル ネゴシエーションでマスターが異常であると判断された後、別の問題があります。どのセンチネルがマスター/スレーブ スイッチオーバーを開始するのでしょうか?

答えは、マスターとスレーブを切り替えるセンチネル「リーダー」を選択することです。

このリーダーをどのように選ぶかという質問が再び来ます。

実生活で選挙がどのように行われるか想像してみてください。

はい、投票してください。

センチネル リーダーを選出する場合、次のような選出ルールを作成できます。

  1. 各歩哨は他の歩哨に投票するように依頼します

  2. 各歩哨は、最初に投票を要求した歩哨にのみ投票し、1 回だけ投票できます。

  3. 最初に半数以上の票を獲得したセンチネルがリーダーとして選出され、マスター/スレーブの切り替えを開始します

この選挙プロセスは、分散システムの分野でよく耳にする「コンセンサス アルゴリズム」です。

コンセンサスアルゴリズムとは?

歩哨は複数のマシンに配置され、タスクを完了するために連携する必要があるため、「分散システム」を形成します。

分散システムの分野では、複数のノードが問題について合意に達する方法のアルゴリズムを合意アルゴリズムと呼びます。

このシナリオでは、複数のセンチネルが一緒に交渉して、全員が認識するリーダーを選出します。これは、コンセンサス アルゴリズムを使用して行われます。

このアルゴリズムでは、ノードの数が奇数でなければならないことも規定されているため、システム内のノードに障害が発生した場合でも、残りのノードの「半分」以上が正常な状態にあり、正しい結果を提供できることが保証されます。つまり、このアルゴリズムも互換性があり、ノードが失敗する場合があります。

分散システムの分野には、Paxos、Raft、およびセンチネルがリーダーを選出するシナリオなど、多くのコンセンサス アルゴリズムがあります. Raft コンセンサス アルゴリズムは、十分にシンプルで実装が容易であるため、使用されます.

よし、ここでまとめよう。

Redis は、最も単純なスタンドアロン バージョンから、データの永続性、マスター/スレーブ マルチコピー、センチネル クラスターを通じて最適化されています. Redis のパフォーマンスと安定性はますます高くなっています. 心配はいりません.

このようなアーキテクチャ モードでデプロイされた Redis は、基本的に長期にわたって安定して動作します。

...

時間の経過とともに、ビジネス ボリュームは爆発的な成長を遂げ始めていますが、この時点で、アーキテクチャ モデルはこれほど大きなトラフィックに耐えることができますか?

一緒に分析しましょう:

  1. データ損失の恐れ: 永続性 (RDB/AOF)

  2. 長い復旧時間: マスタースレーブ コピー (コピーはいつでもカット可能)

  3. 手動切り替え時間が長い:センチネルクラスタ(自動切り替え)

  4. リードプレッシャー:拡大コピー(リードとライトの分離)

  5. 執筆はプレッシャーにさらされています:教師がそれを処理できない場合はどうすればよいですか?

現在残っている問題は、書き込み要求の量が増加すると、マスター インスタンスがそのような大量の書き込みトラフィックに耐えられなくなる可能性があることです。

この問題を完全に解決するには、現時点で「シャード クラスター」の使用を検討する必要があります。

シャード クラスター: スケール アウト

「シャード クラスタ」とは何ですか?

簡単に言えば、1 つのインスタンスでは執筆のプレッシャーに耐えられないため、複数のインスタンスを展開し、これらのインスタンスを特定のルールに従って整理し、それらを全体として扱い、外の世界にサービスを提供して、問題を解決できるようにすることができます。 1 つのインスタンスの集中書き込みの問題 ボトルネックの問題ですか?

したがって、現在のアーキテクチャ モデルは次のようになります。

ここで再び問題が発生します。これほど多くのインスタンスをどのように整理するのでしょうか?

次のようにルールを定式化します。

  1. 各ノードはデータの一部を別々に保存し、すべてのノード データの合計がデータの全量になります。

  2. ルーティング ルールを作成し、さまざまなキーに対して、読み取りと書き込みのために固定インスタンスにルーティングします

データは複数のインスタンスに保存され、キーを見つけるためのルーティング ルールは、具体的には次のようにクライアント側で実行する必要があります。

このソリューションは、「クライアント シャーディング」とも呼ばれます。このソリューションの欠点は、クライアントがルーティング ルールを維持する必要があることです。つまり、ルーティング ルールをビジネス コードに記述する必要があります。

ルーティング ルールをクライアント ビジネス コードに結び付けないようにするにはどうすればよいですか?

最適化を続けるために、クライアントとサーバーの間に「中間プロキシ層」を追加することができます. このプロキシは、私たちがよく耳にするプロキシであり、ルーティングおよび転送ルールは、メンテナンスのためにこのプロキシ層に配置されます.

このように、クライアントはサーバー上の Redis ノードの数を気にする必要はなく、プロキシと対話するだけで済みます。

Proxy はルーティング ルールに従ってリクエストを対応する Redis ノードに転送します. さらに, クラスタ インスタンスがより大きなトラフィック リクエストをサポートするのに十分でない場合, 水平方向に拡張し、新しい Redis インスタンスを追加してパフォーマンスを向上させることもできます. これらはすべてあなたのためです.クライアントにとって、それは透明で目立たないものです。

Twemproxy や Codis など、業界のオープン ソース Redis シャーディング クラスター ソリューションは、このソリューションを採用しています。

このソリューションの利点は、クライアントがデータ転送ルールを気にする必要がなく、プロキシを処理するだけでよいことです. クライアントは、スタンドアロンの Redis のように後続のクラスターを操作するため、使いやすいです.

アーキテクチャの進化これまでのところ、ルーティング ルールがクライアントによって実装されるか、プロキシによって実装されるかにかかわらず、それらはすべて「コミュニティ」によって進化されたシャーディング ソリューションであり、その特徴は、クラスター内の Redis ノードが互いの存在を知らないことだけです。クライアントまたはプロキシは、データがどこから書き込まれ、どこから読み取られるかを調整し、それらはすべてセンチネル クラスターに依存して自動フェイルオーバーを担当します。

つまり、実際には複数の分離された Redis ノードを組み合わせて使用​​しています。

Redis は実際に 3.0 で「公式」の Redis クラスター シャーディング ソリューションをローンチしましたが、ローンチの初期段階で不安定なため、それを使用する人はほとんどいないため、Twemproxy や Codis シャーディングが言及されているなど、さまざまなオープン ソース ソリューションが業界に登場しました。このような背景から、映画プログラムが誕生しました。

しかし、Redis Cluster ソリューションが徐々に成熟するにつれて、業界内でますます多くの企業が公式ソリューションを採用し始めています (結局、公式は継続的なメンテナンスを保証しており、Twemproxy と Codis は徐々にメンテナンスを断念しています)。そのスキーマは次のとおりです。

Redis Cluster does not need to deploy Sentinel clusters. クラスター内の Redis ノードは、Gossip プロトコルを介して互いのヘルス ステータスを検出し、障害が発生した場合に自動切り替えを開始できます。

さらに, ルーティングと転送ルールに関して, クライアントがそれを自分で書く必要はありません. Redis Clusterは「サポートする」SDKを提供します. クライアントがSDKをアップグレードする限り, Redis Clusterと統合することができます. SDKは、キーに対応するRedisノードを見つけるのに役立ちます.読み取りと書き込み、さらにRedisノードの追加と削除に自動的に適応でき、ビジネス側は認識しません.

Sentinel クラスターのデプロイが省略されているため、メンテナンス コストは大幅に削減されていますが、クライアントが SDK をアップグレードする場合、新しいビジネス アプリケーションの場合はコストが高くない可能性がありますが、古いビジネスの場合は「アップグレード コスト」が高くなります。まだ比較的高く、公式の Redis Cluster ソリューションを切り替えることに抵抗があります。

その結果、クライアントのアップグレードのコストを削減するために、さまざまな企業が Redis クラスター用の独自のプロキシを開発し始め、アーキテクチャは次のようになりました。

このように、クライアントは変更を行う必要はなく、接続アドレスをプロキシに切り替えるだけでよく、プロキシはデータを転送し、後続のクラスタでノードを追加または削除することによって発生するルーティングの変更を処理します。

これまでのところ、業界の主流の Redis シャーディング アーキテクチャが形成されています. シャーディング クラスタを使用すると、将来のトラフィック プレッシャーの増大に冷静に対処できます!

要約する

要約すると、安定した高性能の Redis クラスターを 0 から 1 へ、次に 1 から N へと構築した方法であり、そこから Redis アーキテクチャの進化の全プロセスを明確に見ることができます。

  1. データ損失の恐れ -> 永続性 (RDB/AOF)

  2. リカバリ時間が長い → 主従コピー (コピーはいつでもカット可能)

  3. 遅い手動フェールオーバー -> センチネル クラスタ (自動切り替え)

  4. 読み圧あり →拡大コピー(読み書き分離)

  5. 書き込み圧力/容量のボトルネック -> シャード クラスタ

  6. 断片化されたクラスター コミュニティ ソリューション -> Twemproxy、Codis (Redis ノード間の通信なし、Sentry のデプロイが必要、水平方向に拡張可能)

  7. シャード クラスターの公式ソリューション -> Redis クラスター (Redis ノード間の Gossip プロトコル、センチネルをデプロイする必要はなく、水平方向にスケーリングできます)

  8. ビジネスサイドのアップグレードが難しい → Proxy + Redis Cluster (ビジネスサイドに侵入しない)

これまでのところ、当社の Redis クラスターは、長期的な安定性と高いパフォーマンスを備えたサービスを当社のビジネスに提供することができました。

この記事が、Redis アーキテクチャの進化について理解を深めるのに役立つことを願っています。

おすすめ

転載: blog.csdn.net/m0_72650596/article/details/126182244