redis クラスター 1: Li Dai Tao Zong——センチネル

これまで説明してきた Redis は、結果整合性を備えたマスター/スレーブ ソリューションにすぎません。読者は考えたことがあるでしょう。マスター ノードが午前 3 時に突然ダウンしたらどうなるでしょうか? 運用と保守担当者がベッドから起き上がるのを待ってから手動でマスターから切り替え、すべてのプログラムにアドレスを変更して再びオンラインになるように通知するだけですか? このような人手による運用・保守は非効率であることは間違いなく、事故が発生すると復旧までに少なくとも1時間はかかると試算されています。大企業であれば、このような事故が起きれば十分ニュースになるでしょう。

画像
画像

したがって、ノード障害に耐える高可用性ソリューションが必要であり、障害発生時にマスターから自動的に切り替わり、プログラムを再起動する必要がなく、何事もなかったかのように運用と保守がスリープ状態を継続できるようにする必要があります。 。Redis は、そのようなソリューションである Redis Sentinel を公式に提供しています。

画像
画像

Redis Sentinel クラスターは、クラスターの高可用性の中心となる ZooKeeper クラスターと考えることができ、通常は 3 ~ 5 個のノードで構成されているため、個々のノードがダウンしてもクラスターは正常に動作できます。

マスター ノードとスレーブ ノードの健全性を継続的に監視する役割を担っており、マスター ノードがハングアップすると、最適なスレーブ ノードを自動的に選択し、マスター ノードに切り替えます。クライアントがクラスターに接続するときは、まずセンチネルに接続し、センチネルを通じてマスター ノードのアドレスをクエリし、次にデータ対話のためにマスター ノードに接続します。マスター ノードに障害が発生すると、クライアントは Sentinel に再度アドレスを要求し、Sentinel はクライアントに最新のマスター ノード アドレスを通知します。このようにして、アプリケーションは再起動せずにノードの切り替えを自動的に完了します。たとえば、上図のマスター ノードがハングアップした後、クラスターは下図に示す構造に自動的に調整される場合があります。

画像
画像

この図から、マスター ノードがダウンし、元のマスター/スレーブ レプリケーションも切断され、クライアントも損傷したマスター ノードから切断されていることがわかります。スレーブ ノードは新しいマスター ノードに昇格し、他のスレーブ ノードは新しいマスター ノードとのレプリケーション関係の確立を開始します。クライアントは、新しいマスター ノードを介して対話を続けます。Sentinel は障害が発生したマスター ノードの監視を継続し、回復するとクラスターは下の図のように調整されます。

画像
画像

この時点で、障害が発生した元のマスター ノードはスレーブ ノードになり、新しいマスター ノードからレプリケーション関係が確立されます。

メッセージが失われました

Redis マスター/スレーブは非同期レプリケーションを使用します。つまり、マスター ノードがハングアップすると、スレーブ ノードはすべての同期メッセージを受信できない可能性があり、非同期メッセージのこの部分は失われます。マスターとスレーブ間の遅延が特に大きい場合、大量のデータが失われる可能性があります。Sentinel はメッセージがまったく失われないことを保証できませんが、メッセージの損失を最小限に抑えることはできます。過度のマスター/スレーブ遅延を制限する 2 つのオプションがあります。

arduino复制代码min-slaves-to-write 1
min-slaves-max-lag 10

最初のパラメータは、マスター ノードに通常のレプリケーションを実行するスレーブ ノードが少なくとも 1 つ必要であることを示します。そうでないと、外部書き込みサービスが停止し、可用性が失われます。

正常なレプリケーションとは何ですか?異常なレプリケーションとは何ですか? これは 2 番目のパラメータで制御され、単位は秒で、10 秒以内にスレーブ ノードからフィードバックが受信されない場合は、スレーブ ノードの同期が正常でないか、ネットワークが切断されているか、フィードバックがないことを意味します。与えられた。

センチネルの基本的な使い方

次に、クライアントが Sentinel を使用する方法を見てみましょう。標準的なプロセスでは、クライアントは Sentinel を通じてマスター ノードとスレーブ ノードのアドレスを検出し、これらのアドレスを通じて対応する接続​​を確立してデータ アクセス操作を実行できます。Python クライアントがどのように行うかを見てみましょう。

python复制代码>>> from redis.sentinel import Sentinel
>>> sentinel = Sentinel([('localhost'26379)], socket_timeout=0.1)
>>> sentinel.discover_master('mymaster')
('127.0.0.1'6379)
>>> sentinel.discover_slaves('mymaster')
[('127.0.0.1'6380)]

Sentinel のデフォルト ポートは 26379 であり、Redis 6379 のデフォルト ポートとは異なります。マスター アドレスとスレーブ アドレスは、Sentinel オブジェクトの Discover_xxx メソッドを通じて検出できます。マスター アドレスは 1 つだけあり、スレーブ アドレスは複数存在する可能性があります。

python复制代码>>> master = sentinel.master_for('mymaster', socket_timeout=0.1)
>>> slave = sentinel.slave_for('mymaster', socket_timeout=0.1)
>>> master.set('foo''bar')
>>> slave.get('foo')
'bar'

xxx_for メソッドにより、コネクションプールからコネクションを取り出して利用することができますが、スレーブアドレスが複数存在するため、Redis クライアントはスレーブアドレスに対してポーリング方式、つまりラウンドロビンを順番に採用します。

1 つの問題は、sentinel がマスターとスレーブの切り替えを実行するときに、クライアントはアドレスが変更されたことをどのようにして知るのでしょうか? ソース コードを分析したところ、接続を確立するときに redis-py がメイン ライブラリのアドレス変更を決定していることがわかりました。

接続プールは新しい接続を確立するときに、メイン ライブラリのアドレスを照会し、メモリ内のメイン ライブラリのアドレスと比較します。変更された場合は、すべての接続を切断し、新しいアドレスを再利用して新しい接続を確立します。古いメイン ライブラリがハングアップすると、使用中のすべての接続が閉じられ、再接続時に新しいアドレスが使用されます。

しかし、これだけでは十分ではありません。sentinel が積極的にマスター/スレーブ切り替えを実行し、メイン ライブラリがハングアップせず、以前のメイン ライブラリ接続が確立されて使用されており、確立される新しい接続がない場合、この接続は安定して切り替えることはできませんか?

ソース コードをさらに詳しく調べていくと、redis-py が別の点も制御していることがわかりました。つまり、コマンドの処理時に特別な例外がキャッチされReadOnlyError、古い接続はすべて閉じられ、後続の命令が再接続されます。

マスターとスレーブの切り替え後、以前のマスター ライブラリはスレーブ ライブラリにダウングレードされ、すべての変更命令がスローされますReadonlyError変更指示がない場合は、接続は切り替わりませんが、データは破壊されませんので、切り替わらなくても問題ありません。

この記事はmdniceマルチプラットフォームによって公開されています

おすすめ

転載: blog.csdn.net/qq_35030548/article/details/132095094