この記事では、Redis におけるマスター/スレーブ同期について理解し、Redis マスター/スレーブの 2 つの構造モデル、マスター/スレーブ関係の確立、マスター/スレーブ レプリケーションについて紹介します。攻略法など、皆様のお役に立てれば幸いです。
#前回の記事では、redis の特徴と中心原理を詳細に分析しましたが、今回からは、redis のデプロイ構造と動作モードを分析して解釈していきます。レディス。実際の本番環境では、基本的に単一ノード Redis を使用してサービスを提供することはありません。少なくとも、Redis サービスの信頼性を確保するために、マスター/スレーブ構造のセンチネルまたはクラスター モードを使用します。この記事ではredisのマスター・スレーブ同期の仕組みについて詳しく解説します。 [関連する推奨事項: Redis ビデオ チュートリアル ]
1 つのマスターと N つのスレーブのレプリケーション構造には、レプリケーション関係が 1 レベルしかありません。これは、最も一般的に使用される形式でもあります。通常、セントリーまたはクラスター構造を構築する Redis は、このレプリケーション構造を採用します。レベルとスレーブのノード間のレプリケーション関係により、サービスの可用性が保証され、異常な状況下でもマスターとスレーブの切り替えが可能になります。
カスケード レプリケーション構造のレプリケーション関係は複数のレベルを持つことができ、マスター ノードのスレーブ ノードが下位のスレーブ ノードのマスター ノードになることができます。カスケードレプリケーション構造の適用は比較的まれであり、複数のスレーブノードを持つ構成において、マスターノードのレプリケーション圧力をある程度軽減することができます。
Redis の主従同期は、SLAVEOF host port コマンドによって開始され、このコマンドにより主従関係を確立できます。 SLAVEOF コマンドは、Redis のコピー機能の動作を動的に変更するために使用されます。 SLAVEOFホストポートコマンドを実行すると、現在のサーバを指定したサーバのスレーブサーバにすることができます。現在のサーバーがすでにマスターサーバーのスレーブサーバーである場合、SLAVEOF ホストポートを実行すると、現在のサーバーは古いマスターサーバーとの同期を停止し、古いデータセットを破棄し、新しいマスターサーバーとの同期を開始します。また、スレーブサーバー上でコマンド SLAVEOF NO ONE を実行すると、スレーブサーバーはレプリケーション機能をオフにし、スレーブサーバーからマスターサーバーに戻りますが、元の同期データセットは破棄されません。同期したデータセットが破棄されないSLAVEOF NO ONEの特徴を活かし、センチネルやクラスタを構築することなく、マスターサーバーに障害が発生した場合にスレーブサーバーを新たなマスターサーバーとして利用することができ、無停止運用を実現します。
次の図は、マスター/スレーブ関係を確立するプロセスを示しています。
注:
上記の実行手順によると注意点があり、すでに主従関係が確立されているノードに対してslaveofコマンドを実行すると、既存の主従関係が終了し、配下にあるすべてのデータが削除されます。実稼働環境では、これは比較的脅威となる操作です。より安全な方法はありますか?上記のslaveofコマンドを紹介するときに、NO ONEパラメータを渡すことができる、つまりSLAVEOF NO ONEコマンドを実行できると述べました。このコマンドはマスター/スレーブのレプリケーション関係を終了するだけであり、データはクリアされません。比較的安全です。 。
マスターとスレーブの関係が確立された後、マスターとスレーブのデータ同期プロセスが開始されます。ここには主に 3 つの状況があります。マスターとスレーブの関係が確立された後のデータ確立されたばかりの完全同期 ; 初期同期完了後のコマンド伝播段階; マスター/スレーブ関係が異常に中断され再接続された後の同期方法の選択 完全同期と増分同期の 2 つのシナリオがあります。
スレーブ ノードが起動されるか、切断されて再接続されるとき (再接続が増分同期条件を満たさない場合)、SYNC コマンドが次のノードに送信されます。マスターデータベース。
マスター ノードは SYNC コマンドを受信すると、バックグラウンドでスナップショットの保存を開始し (つまり、RDB の永続性、マスター/スレーブ レプリケーション中に RDB が無条件にトリガーされます)、コマンドはキャッシュされます。
マスター ノードは RDB の永続化を完了すると、スナップショット RDB ファイルをすべてのスレーブ ノードに送信し、スナップショットの送信中に実行された書き込みコマンドを記録し続けます。
スレーブ ノードはスナップショット ファイルを受信した後、古いデータをすべて破棄し (すべてのデータがクリアされます)、受信したスナップショットをロードします。
マスター ノードのスナップショットが送信され、スレーブ ノードがスナップショットをロードした後、マスター ノードはバッファ内の書き込みコマンドをスレーブ ノードに送信し始めます。
スレーブ ノードはスナップショットのロードを完了し、コマンド リクエストの受信を開始し、メイン データベース バッファから書き込みコマンドを実行します。 (データベースから初期化完了)
マスターノードは書き込みコマンドを実行するたびに、同じ書き込みコマンドをスレーブノードに送信し、スレーブノードは受信した書き込みコマンドを受信して実行します。 (コマンド伝播操作、スレーブノードの初期化完了後の操作)
完全な同期プロセスは次のとおりです:
redis2 .8 以前は、スレーブ ノードは、初期化された場合でも、切断されて再接続された場合でも完全同期を使用していましたが、2.8 以降のバージョンでは、スレーブ ノードが切断されて再接続された後に増分同期を使用するかどうかを決定する PSYNC コマンドが導入されました。
PSYNC には、完全データ再同期モードと増分同期モードがあります。
完全再同期: 基本的に古いバージョンのレプリケーションと同じであり、「完全な」レプリケーションとして理解できます。
部分再同期: コマンド伝播フェーズ中にスレーブが切断されて再接続される場合、切断中に実行されたコマンドをマスターからスレーブに送信するだけで済みます。 「増分」コピーの場合。
PSYNC の実行プロセスには、runid、オフセット (コピー オフセット)、およびコピー バックログ バッファーという 3 つの重要な概念があります。
1.runid
各 Redis サーバーには、その ID を示す ID があります。 PSYNC で送信される ID は、以前に接続したマスターの ID を参照します。この ID が保存されていない場合、PSYNC コマンドは「PSYNC? -1」形式を使用してマスターに送信し、完全なコピーが必要であることを示します。
2.offset (レプリケーション オフセット)
マスター/スレーブ レプリケーションのマスターとスレーブの両方が、それぞれオフセットを維持します。マスターが N バイト コマンドの送信に成功すると、マスター内のオフセットが N だけ増加します。スレーブが N バイト コマンドを受信した後、スレーブもスレーブ内のオフセットを N だけ増加します。マスターとスレーブのステータスが一貫している場合、それらのオフセットも一貫している必要があります。
3. コピー バックログ バッファ
コピー バックログ バッファは、マスターによって維持される固定長の循環バックログ キュー (FIFO キュー) であり、その機能は、コマンドを伝播します。マスターがコマンドを伝播するとき、コマンドをすべてのスレーブに送信するだけでなく、コマンドをレプリケーション バックログ バッファーにも書き込みます。 PSYNC と SYNC の実行処理の違いは、スレーブ接続時に完全同期が必要かどうかを判断する点であり、完全同期の論理的な処理は SYNC と同じです。 PSYNC の実行手順は次のとおりです。
クライアントは、SLAVEOF コマンドをサーバーに送信します。つまり、スレーブがマスターへの接続要求を開始すると、スレーブは、マスターへの接続要求が開始されるかどうかを判断します。マスター runid を保存するかどうかに基づく最初の接続です。
最初の同期の場合は、同期を完了するために PSYNC ? -1 コマンドがマスターに送信され、再接続の場合は PSYNC runid offset コマンドがマスターに送信されます。マスター (runid はマスターの ID、オフセットはスレーブ ノード同期コマンドのグローバル移行量)。
マスターは PSYNC コマンドを受信すると、まず runid がローカル マシンの ID と一致するかどうかを判断します。一致する場合は、オフセット offset が正しいかどうかを再度判断します。ローカル マシンのオフセットとは異なります。レプリケーション バックログ バッファ サイズを超えています。超えていない場合は、CONTINUE がスレーブに送信されます。この時点で、スレーブは、接続の喪失中に失われたコマンドがマスターから返されるのを待つだけで済みます。 。 runid がローカル ID と一致しない場合、またはオフセット ギャップがコピー バックログ バッファ サイズを超えている場合、FULLRESYNC runid オフセットが返され、スレーブは runid を保存して完全同期を実行します。
マスター ノードがコマンドを伝播すると、マスター データベースは各書き込みコマンドをスレーブ データベースに渡し、同時に書き込みコマンドをバックログ キューに保存して記録します。バックログ キュー内の現在のストレージ コマンドのグローバル オフセット。スレーブが再接続すると、マスターはスレーブ ノードから渡されたオフセットに基づいて、リング バックログ キュー内の切断期間中に実行されたコマンドを見つけ、それらをスレーブ ノードに同期して増分同期結果を実現します。
PSYNC 実行プロセスは次のとおりです。
# 上記の PSYNC 実行プロセスから、スレーブ ノードが切断され、再接続されると、インクリメンタル同期を使用するかどうかは、スレーブのオフセット offset とマスターのオフセットの差がコピー バックログ バッファ サイズを超えるかどうかで判断され、このサイズは以下のパラメータで設定されます。レプリケーション バックログ バッファは、基本的に固定長の循環キューです。デフォルトでは、バックログ キューのサイズは 1MB です。キュー サイズは、構成ファイルで設定できます: レプリケーション バックログ バッファ サイズを設定します。バックログ キューが大きくなるほど、マスター/スレーブ データベースの切断が許可される時間が長くなるほど、時間が長くなるほど
repl-backlog-size 1mb
Redis は、同期する必要のないスレーブが存在しない場合にリング キューを解放するのにかかる時間も提供します。デフォルトは 1 時間です。スレーブ接続はありません。レプリケーション バックログ バッファーが解放される頻度
repl-backlog-ttl 3600
Redis采用了乐观复制的策略,也就是在一定程度内容忍主从数据库的内容不一致,但是保持主从数据库数据的最终一致性。具体来说,Redis在主从复制的过程中,本身就是异步的,在主从数据库执行完客户端请求后会立即将结果返回给客户端,并异步的将命令同步给从数据库,但是这里并不会等待从数据库完全同步之后,再返回客户端。这一特性虽然保证了主从复制期间性能不受影响,但是也会产生一个数据不一致的时间窗口,如果在这个时间窗口期间网络突然断开连接,就会导致两者数据不一致。如果不在配置文件中添加其他策略,那就默认会采用这种方式。为了防止主从不一致不可控,redis提供了以下两个参数来做约束:
min-slaves-to-write 3 min-slaves-max-lag 10
当slave数量小于min-slaves-to-write,且延迟小于等于min-slaves-max-lag时,master停止写入操作。
还有一个参数也会影响主从之间的延时:
repl-disable-tcp-nodelay:
设置成yes,则redis会合并小的TCP包从而节省带宽,但会增加同步延迟,造成master与slave数据不一致。设置成no,则redis master会立即发送同步数据,几乎没有延迟。
Redis的主从同步无论那种场景可以抽象为以下七个步骤:
1.建立socket连接
从服务器根据设置的套接字创建连向主服务器的套接字连接,主服务器接收从服务器的套接字连接之后,为该套接字创建响应的客户端状态,并将此时的从服务器看做是主服务器的客户端,也就是该从服务器同时具备服务器与客户端两个身份。
2.发送PING命令
PING命令主要有两种作用:虽然建立了套接字连接,但是还未使用过,通过发送PING命令检查套接字的读写状态是否正常;通过发送PING命令检查主服务器能否正常处理命令请求,能处理主服务器回复PONG。
3.身份验证
从服务器接收到主服务器返回的“PONG”回复,接下来就需要考虑身份验证的事。如果从服务器设置了masterauth选项,那么进行身份验证,如果从服务器没有设置masterauth选项,那么不进行身份验证。
4.发送端口信息
在身份验证步骤之后,从服务器将执行命令REPLCONF listening-port ,向主服务器发送从服务器的监听端口号。
5.数据同步
从服务器向主服务器发送SYNC命令、PSYNC命令,执行同步操作。
6.命令传播
主从服务器就会进入命令传播阶段,主服务器只要将自己执行的写命令发送给从服务器,而从服务器只要一直执行并接收主服务器发来的写命令。
本篇详细介绍了redis主从同步机制,不同场景下同步策略的选择,这也是redis高可用的基石。在此基础上,下一篇将对redis高可用的实现来进行分析讲解。
更多编程相关知识,请访问:编程视频!!
以上がRedis のマスター/スレーブ同期メカニズムについての深い理解の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。