メモリベースの Redis は、さまざまな Web 開発ビジネスで最も一般的に使用されるキーと値のデータベースです。私たちのビジネスでは、ユーザーのログイン ステータス (セッション ストレージ) を保存するためによく使用されます。いくつかのホット データ クエリ (mysql と比較して、速度が桁違いに向上します)、単純なメッセージ キュー (LPUSH および BRPOP) の構築、サブスクリプション パブリッシング (PUB/SUB) システムなど。一般に、大規模なインターネット企業には、さまざまなビジネス コールに対する基本サービスとして Redis ストレージを提供する専門のチームが存在します。
ただし、基本サービスのプロバイダーは、発信者から「あなたのサービスは高可用性ですか?」と尋ねられるでしょう。貴社のサービスで頻繁に問題が発生して、私のビジネスに支障をきたさないことが最善です。最近、自分のプロジェクトで小規模な「高可用性」Redis サービスも構築しました。ここではその概要と考察を述べます。
まず、Redis サービスの高可用性とは何か、つまり、さまざまな異常な状況下でもサービスを正常に提供できることを定義する必要があります。異常が発生した場合でも、短時間で通常のサービスを復旧できます。いわゆる例外には、少なくとも次の可能性が含まれている必要があります:
[例外 1] 特定のノード サーバーのプロセスが突然ダウンしました (たとえば、開発者がハンディキャップを負い、サーバーの redis-server プロセスが停止したなど)
[例外 2] 特定のノード サーバーがダウンしています。これは、このノード上のすべてのプロセスが停止していることに相当します (たとえば、運用とメンテナンスの障害によりサーバーの電源が切断されます。例: 古いマシンにハードウェア障害が発生した場合)
[例外 3] 2 つのノード サーバー間の通信が中断された場合 (例: 手の不自由な派遣社員が、ノード サーバー間の通信に使用されている光ケーブルを掘り出した場合)コンピューター室が 2 つ)
実際、上記の例外はどれも小さな確率のイベントであり、高可用性を実現するための基本的な指針は、複数の小さな確率のイベントが同時に発生する確率は無視できるということです。短期間の単一障害点を許容するようにシステムを設計する限り、高可用性を実現できます。
インターネット上には、Keepalived、Codis、Twemproxy、Redis Sentinel など、高可用性 Redis サービスを構築するためのソリューションが多数あります。このうち、Codis と Twemproxy は主に大規模な Redis クラスターで使用されており、Redis が Redis Sentinel を正式にリリースする前は twitter や Wandoujia によって提供されていたオープンソース ソリューションでもありました。私のビジネスのデータ量はそれほど多くないため、クラスター サービスはマシンの無駄です。最終的に、Keepalived と Redis Sentinel のどちらかを選択し、公式ソリューションである Redis Sentinel を選択しました。
Redis Sentinel は、Redis Server サービスが正常かどうかを監視するプロセスとして理解でき、異常が検出されると、バックアップ (スレーブ) Redis Server が自動的に有効になり、外部ユーザーが異常を検出できるようになります。 Redis サービス内で発生しますが、認識されません。単純な手順から複雑な手順に従って、最小限で可用性の高い Redis サービスを構築します。
オプション 1: Sentinel なしのスタンドアロン バージョンの Redis Server
通常の状況では、個人の Web サイトの場合、または日常の開発中に、Redis Server の単一インスタンスがセットアップされます。呼び出し元は Redis サービスに直接接続でき、クライアントと Redis 自体も同じサーバー上にあります。この組み合わせは個人的な学習や娯楽にのみ適しており、結局のところ、この構成には解決できない単一障害点が常に存在します。 Redis サービス プロセスがハングするか、サーバー 1 がシャットダウンされると、サービスは利用できなくなります。また、Redis データの永続性が構成されていない場合、Redis に既に保存されているデータも失われます。
オプション 2: マスター/スレーブ同期 Redis サーバー、単一インスタンス Sentinel
達成するには高可用性、解決策 1 で説明した単一障害点の問題については、バックアップ サービスを追加する必要があります。つまり、2 つのサーバーのそれぞれで Redis サーバー プロセスを開始する必要があります。通常、マスターはサービスを提供し、スレーブは責任のみを負います同期とバックアップ用。同時に、追加の Sentinel プロセスが開始されて 2 つの Redis Server インスタンスの可用性を監視し、マスターがハングアップしたときにスレーブをマスターの役割に昇格させてサービスを提供し続けることができます。 Redis サーバーの可用性。これは高可用性サービス設計の基礎に基づいています。つまり、単一点障害自体は確率の低いイベントであり、同時に複数の単一点障害が発生します (つまり、マスターとスレーブが同時にハングアップします)。時間)は(基本的に)不可能な出来事と考えることができます。
Redis サービスの呼び出し元にとって、今接続する必要があるのは Redis Server ではなく Redis Sentinel サービスです。一般的な呼び出しプロセスでは、クライアントは最初に Redis Sentinel に接続し、現在の Redis サーバーのどのサービスがマスターでどのサービスがスレーブであるかを尋ね、その後、対応する Redis サーバーに接続して操作します。もちろん、現在のサードパーティ ライブラリは一般的にこの呼び出しプロセスを実装しており、手動で実装する必要はなくなりました (Nodejs の ioredis、PHP の predis、Golang の go-redis/redis、JAVA の jedis など)。
しかし、Redis Server サービスのマスター/スレーブ切り替えを実装した後、Redis Sentinel 自体もシングルポイント サービスであるという新しい問題が発生しました。Sentinel プロセスがハングすると、クライアントはSentinel にリンクされています。したがって、オプション 2 の構成では高可用性を実現できません。
解決策 3: マスター/スレーブ同期 Redis サーバー、デュアル インスタンス Sentinel
解決策 2 の質問について, また、追加の Redis Sentinel プロセスも開始します。2 つの Sentinel プロセスは、クライアントにサービス検出機能を同時に提供します。クライアントの場合、任意の Redis Sentinel サービスに接続して、現在の Redis Server インスタンスに関する基本情報を取得できます。通常、クライアント側で複数の Redis Sentinel リンク アドレスを設定します。クライアントは、特定のアドレスに接続できないことを検出すると、他の Sentinel インスタンスへの接続を試みます。もちろん、これを手動で実装する必要はありません。さまざまな開発言語 より一般的な Redis 接続ライブラリが、この機能の実現に役立ちました。私たちの期待は、Redis Sentinel の 1 つが電話を切ったとしても、サービスを提供できる別の Sentinel が存在することです。
しかし、ビジョンは美しいですが、現実は非常に残酷です。このようなアーキテクチャでは、Redis サービスの高可用性を実現することは依然として不可能です。オプション 3 の概略図では、赤い線が 2 つのサーバー間の通信であり、私たちが想定する異常シナリオ ([例外 2]) は、特定のサーバーが全体としてダウンしていることです。現時点では、サーバー 2 では Redis Sentinel とスレーブ Redis Server のみが処理します。現時点では、Sentinel はサービスを継続するために実際に残りのスレーブをマスターに切り替えることはありません。これにより、Redis サービスが利用できなくなります。これは、Redis の設定では、Sentinel プロセスの 50% 以上が接続および接続できる場合のみであるためです。新しいマスターに投票すると、マスターとスレーブの切り替えが実際に行われます。この例では、2 つの Sentinel のうち 1 つだけを接続できます。これは 50% に相当し、マスター/スレーブの切り替えが可能なシナリオではありません。
なぜ Redis にこの 50% 設定があるのかと疑問に思われるかもしれません。 Sentinel 接続の 50% 以下を許可すると仮定すると、マスター/スレーブ切り替えも実行できます。 [例外 3] を想像してください。つまり、サーバー 1 とサーバー 2 の間のネットワークは中断されていますが、サーバー自体は動作しています。以下の図に示すように:
実際、サーバー 2 の場合、サーバー 1 が直接ダウンしている場合、サーバー 1 が接続できないのと同じ影響があります。いずれにせよ、突然ネットワークが利用できなくなります。ネットワークが中断されたときに、サーバー 2 の Sentinel がスレーブからマスターに切り替わることを許可すると、その結果、外部にサービスを提供できる 2 つの Redis サーバーが存在することになります。クライアントによって実行される追加、削除、および変更操作は、(クライアントが接続している Sentinel に応じて) サーバー 1 の Redis またはサーバー 2 の Redis に影響を与える可能性があり、データの混乱を引き起こす可能性があります。たとえ後でサーバー 1 とサーバー 2 の間のネットワークが復旧したとしても、データを統合することはできず (2 つの異なるデータ、誰を信頼すればよいでしょうか?)、データの整合性は完全に破壊されます。
オプション 4: マスター/スレーブ同期 Redis Server、Sentinel の 3 つのインスタンス
オプション 3 はそうではないという事実 高可用性を実現するための最終バージョンは、上の図に示すソリューション 4 です。実際、これが私たちが最終的に構築したアーキテクチャです。サーバー 3 を導入し、その上に Redis Sentinel プロセスを構築しました。現在、3 つの Sentinel プロセスが 2 つの Redis Server インスタンスを管理しています。このシナリオでは、単一プロセスの障害、単一マシンの障害、または 2 台のマシン間のネットワーク通信障害のいずれであっても、Redis サービスを外部に提供し続けることができます。
実際には、マシンが比較的アイドル状態の場合は、サーバー 3 で Redis サーバーを開いて 1 マスター 2 スレーブ アーキテクチャを形成することもできます。各データには 2 つのバックアップがあり、可用性が向上します。 。もちろんスレーブの数は多ければ多いほど良いのですが、やはりマスターとスレーブの同期にも時間がかかります。
シナリオ 4 では、サーバー 1 と他のサーバー間の通信が完全に中断されると、サーバー 2 と 3 はスレーブからマスターに切り替わります。クライアントの場合、現時点ではサービスを提供するマスターが 2 つあり、ネットワークが復旧すると、停止中にサーバー 1 に落ちた新しいデータはすべて失われます。この問題を部分的に解決したい場合は、Redis サーバー プロセスを構成して、自身のネットワークに問題が検出されたときにサービスを直ちに停止して、ネットワーク障害中に新しいデータが受信されるのを避けることができます (Redis の「最小の」を参照してください)。 slaves-to-write と min-slaves-max-lag の 2 つの構成項目)。
これまでに、3 台のマシンを使用して可用性の高い Redis サービスを構築してきました。実際、インターネットには、サービス プロバイダーのマシンではなくクライアント マシンに Sentinel プロセスを配置する、よりマシンを節約する方法があります。ただ、社内では一般的なサービスの提供者と発信者が同じチームから所属しているわけではありません。 2つのチームが同じマシンを一緒に操作する場合、通信の問題による誤操作が発生しやすいため、人的要因を考慮してオプション4のアーキテクチャを採用しました。また、サーバー 3 では Sentinel プロセスが 1 つだけ実行されているため、サーバー リソースをあまり消費せず、サーバー 3 を使用して他のサービスを実行することもできます。
使いやすさ: Redis Sentinel を Redis のスタンドアロン バージョンのように使用します
サービス プロバイダーとして、私たちは常にユーザー エクスペリエンスについて話します。問題。上記の解決策の中には、クライアントにとって使いにくいものは常にあります。 Redis のスタンドアロン バージョンの場合、クライアントは Redis サーバーに直接接続し、IP とポートを指定するだけで、クライアントはサービスを使用できます。 Sentinel モードに変換した後、クライアントは Sentinel モードをサポートするいくつかの外部依存パッケージを使用する必要があり、また独自の Redis 接続構成も変更する必要がありますが、これは明らかに「見栄っ張りな」ユーザーには受け入れられません。スタンドアロン版の Redis を使用する場合のように、クライアントに固定 IP とポートを与えるだけでサービスを提供する方法はありますか?
#答えはもちろん「はい」です。これには、上の図に示すように、仮想 IP (仮想 IP、VIP) の導入が必要になる場合があります。 Redis サーバーのマスターが配置されているサーバーに仮想 IP を指定できます。Redis マスター/スレーブの切り替えが発生すると、コールバック スクリプトがトリガーされます。コールバック スクリプトは、VIP をスレーブが配置されているサーバーに切り替えます。このように、クライアントにとっては、高可用性 Redis サービスのスタンドアロン バージョンをまだ使用しているように見えます。結論
スタンドアロン バージョンを実行するのと同じように、サービスを構築して「使用可能」にするのは実際には非常に簡単です。レディス。しかし、「高可用性」を実現しようとすると、事態は複雑になります。ビジネスでは、2 つの追加サーバー (3 つの Sentinel プロセスと 1 つのスレーブ プロセス) が使用されており、万が一の事故が発生した場合でもサービスを確実に利用できるようにします。実際の業務ではプロセス監視用のスーパーバイザーも有効にしており、プロセスが予期せず終了した場合には自動的に再起動を試みます。 推奨される学習:以上が高可用性 Redis サービス アーキテクチャの分析と構築の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。