分散型Redisデプス・プロファイル-レプリケーション
4730 ワード
分散型Redisデプス・プロファイル-レプリケーション
詳細については、個人ブログを参照してください.https://github.com/farmerjohngit/myblog
Redisの深さの冒険は2つの部分に分けられ,単機Redisと分布式Redisである.
本文は分布式Redis深さ冒険シリーズの第1編であり,主な内容はRedisの複製機能である.
Redisのレプリケーション機能は、ほとんどの分散型ストレージシステムと同様に、主従設計をサポートするために、主従設計のメリットは以下の点です.読み書き分離、読み書き性能向上 データバックアップ、データ損失のリスクを減らす 高可用性、単一障害を回避 image
旧バージョンのレプリケーションの実装
Redisのレプリケーションは、主に同期とコマンド伝播の2つのステップに分けられます.
同期は全量と理解でき,プライマリサーバのある時点のすべてのデータをスレーブサーバに同期する.
コマンド伝播はインクリメンタルと理解され、プライマリ・サーバのデータが変更されると、プライマリ・サーバは対応するデータ変更コマンドをサーバから送信する.
同期
同期には、次のステップがあります.
1.サーバからマスタサーバに
2.プライマリサーバは、スレーブサーバコマンドを受信すると、
3.サーバからRDBファイルを送信する
4.バッファからの書き込みコマンドをスレーブサーバに送信
同期は、サーバからプライマリ・サーバに最初に接続する場合と、サービスからプライマリ・サーバへのネットワーク・リンクが切断され、プライマリ・サーバに再接続して再同期する場合の2つに分けられます.
コマンド伝播
コマンド伝播の実現ロジックは比較的簡単で、マスターサーバがライトコマンドを実行した後、サーバーからマスターサーバデータとの整合性を保証するために、マスターサーバはライトコマンドをスレーブサーバに送信し、サーバーから受け取ったライトコマンドを実行した後、そのデータはマスターサーバーと一致する(もちろん遅延がある)ことに注意してください.スレーブサーバはクライアントに対して読み取り専用であるため、サーバからのすべてのデータはプライマリサーバからの同期orコマンド伝播である.
旧版コピーの問題点
Redisプライマリスレーブサーバ間のネットワーク環境が信頼できないと仮定し、上記のレプリケーション方法でどのような問題が発生するかを見てみましょう.プライマリサーバAとスレーブサーバBがあると仮定すると、プライマリサーバには現在1~10000の計1万件のデータが存在する.
1.初期接続、サーバーから初めてメインサーバーからデータを同期し、同期完了後、サーバーからも1-10000の計1万件のデータがある.
2.メインサーバーに1000110002のデータを追加
3.コマンド伝播により、サーバからも1000110002両データを追加
4.このときプライマリサーバ間のネットワークが切断される
5.マスタサーバ新規データ10003は、ネットワークが切断されているため、サーバからデータの変化を感じない
6.ネットワーク復旧、サーバーからメインサーバーへの再接続、SYNCコマンドの送信、同期操作
7.プライマリ・サーバは、すべてのデータをスレーブ・サーバに送信する(1-10003)
上記の手順から、サーバからプライマリサーバに再接続すると、フル同期が再開され、不要なIOオーバーヘッドが大量に発生し、ネットワーク環境が不安定な場合、プライマリサーバはメモリのデータをディスクに書き込んでセカンダリサーバに送信し続けることがわかります.
新しいレプリケーションの実装
古いレプリケーションの問題を解決するために、Redis 2.8レプリケーション機能を最適化しました.次のようになります.
1.プライマリ・サーバは、Nバイトのデータをサーバに伝播するたびにNを加算するオフセット量を維持します.たとえば、最初は0で、
2.サーバからもオフセット量を維持し、サーバからプライマリサーバへのNバイトデータを受信すると、そのオフセット量にNが加算されます.
3.プライマリ・サーバは固定サイズのバッファを維持し、クライアントの書き込みコマンドを受信するたびに、対応する
4.プライマリサーバに一意のidがある
5.サーバからプライマリ・サービスに接続すると、前回接続したプライマリ・サーバのidおよびオフセット量がプライマリ・サーバに送信されます.ここでは、いくつかのケースに分けられます.サーバからidが送信されなかったり、idが現在のプライマリサーバと一致しなかったりした場合、プライマリサーバは全量のデータ を送信する.サーバのoffsetからバッファ内に見つからない場合(遅れすぎてバッファが新しいデータで上書きされている)には、フル同期 も行われる. offsetがバッファで見つけられる場合、プライマリ・サービスはoffsetから始まり、バッファのデータをスレーブ・サーバに順次送信する.(pipelineの最適化はありますか) 以上が新版レプリケーションの大まかな考え方であり、メインサーババッファのサイズ設定が重要であり、設定が大きすぎるとスペースの浪費を招き、小さすぎるとネットワーク環境が悪くなると、古いレプリケーションに劣化することに注意してください.
前に私はこのような穴を踏んだことがあります:クラウドに上がる時、redisクラスタは2つの異なる機械室にあって、主従の前のネットワーク環境はあまり安定していませんが、redis機械の上で記憶するvalueは比較的に大きくて、バッファをいっぱい占めて毎回全量同期して、悪循環を形成して、サーバーから遅れて読むことができません.プライマリ・サーバは書き込み不可(Redisからの遅れが多すぎる場合、プライマリ・Redisは書き込みを拒否し、特定のパラメータは構成できますが、後述します)
バッファサイズを
主従心拍メカニズム
サーバからデフォルトでは、1秒に1回の頻度でプライマリサーバにハートビートが送信されます.
心拍数には3つの役割があります.
1.マスタスレーブサーバのネットワーク接続を検出する
2.min-slaves機能の実現
3.検出コマンドの紛失
プライマリ・スレーブ・サーバのネットワーク接続の検出
プライマリ・サーバは、サーバから最後に送信された心拍数がいつだったかを記録します.この時間によって、プライマリ・セカンダリ・サーバ間の接続に障害が発生したかどうかを知ることができます.
min-slaves機能の実現
Redisは、データのセキュリティを保証するために、サーバから
コマンドロスの検出
プライマリ・スレーブ間のレプリケーションは、実はプライマリ・サーバをスレーブ・サーバのクライアントとして実現される(Redisでは、すべてのサーバ間のデータ転送はこの方法で行われる).プライマリ・サーバがサーバから書き込みコマンドを送信したとしますが、ネットワークに異常が発生し、サーバからコマンドが受信されませんでした.これにより、データが一致しない状態になります(プライマリ・サーバがコマンドを送信した場合、エラーが返されなければ再送すればいいのではないでしょうか.コマンドが正常に実行されたからといって、プライマリに返信する際に問題が発生した場合、プライマリが再送するとデータが異常になります).したがって、プライマリサーバは、ハートビート情報に基づいて送信するデータを決定します.例を見てみましょう.
当初、プライマリ・サーバとセカンダリ・サーバのオフセット量はいずれも100であった.
プライマリ・サーバは、クライアントから書き込みコマンドを受信し、オフセット量を110に変更するとともに、書き込みコマンドをサーバから送信するが、ネットワーク上の理由でサーバから受信されず、そのオフセット量は依然として100である.プライマリ・サーバは、ハートビートによりサーバからのオフセット量が100より遅れていることを発見し、100-110のデータを再送する.
ここで、サーバから100-110のデータを受信する前に、プライマリサーバに現在100にオフセットしていることを通知し、100-110のデータを受信したことを疑問に思うかもしれません.このとき次の心拍数はまだ出ていません.メインサーバはサーバから自分に遅れていると思って、再び100-110のデータを送信して、サーバから再び100-110のデータを書き込んで、データの異常を招きます!
もしあなたがこの問題を考えたら、あなたが真剣に考えていることを意味します.
redisが単一スレッドであるため、このような状況は存在しません.単一スレッドの3つの字を覚えて、もう一度問題の説明を振り返って、あなたが理解できると信じています.
リファレンス
詳細については、個人ブログを参照してください.https://github.com/farmerjohngit/myblog
Redisの深さの冒険は2つの部分に分けられ,単機Redisと分布式Redisである.
本文は分布式Redis深さ冒険シリーズの第1編であり,主な内容はRedisの複製機能である.
Redisのレプリケーション機能は、ほとんどの分散型ストレージシステムと同様に、主従設計をサポートするために、主従設計のメリットは以下の点です.
旧バージョンのレプリケーションの実装
Redisのレプリケーションは、主に同期とコマンド伝播の2つのステップに分けられます.
同期は全量と理解でき,プライマリサーバのある時点のすべてのデータをスレーブサーバに同期する.
コマンド伝播はインクリメンタルと理解され、プライマリ・サーバのデータが変更されると、プライマリ・サーバは対応するデータ変更コマンドをサーバから送信する.
同期
同期には、次のステップがあります.
1.サーバからマスタサーバに
SYNC
コマンドを送信する(SLAVE OF
コマンドを実行する第1ステップもSYNC
を実行する)2.プライマリサーバは、スレーブサーバコマンドを受信すると、
BGSAVE
を実行します.すなわち、メモリ内のデータをRDBファイルに保存するための新しいサブプロセスを実行します.同時に、RDBファイル生成期間のインクリメンタルを記録するメモリバッファを使用して、これから実行される書き込みコマンドを記録します.3.サーバからRDBファイルを送信する
4.バッファからの書き込みコマンドをスレーブサーバに送信
同期は、サーバからプライマリ・サーバに最初に接続する場合と、サービスからプライマリ・サーバへのネットワーク・リンクが切断され、プライマリ・サーバに再接続して再同期する場合の2つに分けられます.
コマンド伝播
コマンド伝播の実現ロジックは比較的簡単で、マスターサーバがライトコマンドを実行した後、サーバーからマスターサーバデータとの整合性を保証するために、マスターサーバはライトコマンドをスレーブサーバに送信し、サーバーから受け取ったライトコマンドを実行した後、そのデータはマスターサーバーと一致する(もちろん遅延がある)ことに注意してください.スレーブサーバはクライアントに対して読み取り専用であるため、サーバからのすべてのデータはプライマリサーバからの同期orコマンド伝播である.
旧版コピーの問題点
Redisプライマリスレーブサーバ間のネットワーク環境が信頼できないと仮定し、上記のレプリケーション方法でどのような問題が発生するかを見てみましょう.プライマリサーバAとスレーブサーバBがあると仮定すると、プライマリサーバには現在1~10000の計1万件のデータが存在する.
1.初期接続、サーバーから初めてメインサーバーからデータを同期し、同期完了後、サーバーからも1-10000の計1万件のデータがある.
2.メインサーバーに1000110002のデータを追加
3.コマンド伝播により、サーバからも1000110002両データを追加
4.このときプライマリサーバ間のネットワークが切断される
5.マスタサーバ新規データ10003は、ネットワークが切断されているため、サーバからデータの変化を感じない
6.ネットワーク復旧、サーバーからメインサーバーへの再接続、SYNCコマンドの送信、同期操作
7.プライマリ・サーバは、すべてのデータをスレーブ・サーバに送信する(1-10003)
上記の手順から、サーバからプライマリサーバに再接続すると、フル同期が再開され、不要なIOオーバーヘッドが大量に発生し、ネットワーク環境が不安定な場合、プライマリサーバはメモリのデータをディスクに書き込んでセカンダリサーバに送信し続けることがわかります.
新しいレプリケーションの実装
古いレプリケーションの問題を解決するために、Redis 2.8レプリケーション機能を最適化しました.次のようになります.
1.プライマリ・サーバは、Nバイトのデータをサーバに伝播するたびにNを加算するオフセット量を維持します.たとえば、最初は0で、
set key1 value1
を受信すると、そのオフセット量は13になります(実際のオフセットは13ではなく、例を挙げるだけです).//ここではコード確認を見るかもしれません2.サーバからもオフセット量を維持し、サーバからプライマリサーバへのNバイトデータを受信すると、そのオフセット量にNが加算されます.
3.プライマリ・サーバは固定サイズのバッファを維持し、クライアントの書き込みコマンドを受信するたびに、対応する
をこのバッファに書き込みます.書き込み内容が固定サイズを超えると、元のデータが上書きされます.4.プライマリサーバに一意のidがある
5.サーバからプライマリ・サービスに接続すると、前回接続したプライマリ・サーバのidおよびオフセット量がプライマリ・サーバに送信されます.ここでは、いくつかのケースに分けられます.
前に私はこのような穴を踏んだことがあります:クラウドに上がる時、redisクラスタは2つの異なる機械室にあって、主従の前のネットワーク環境はあまり安定していませんが、redis機械の上で記憶するvalueは比較的に大きくて、バッファをいっぱい占めて毎回全量同期して、悪循環を形成して、サーバーから遅れて読むことができません.プライマリ・サーバは書き込み不可(Redisからの遅れが多すぎる場合、プライマリ・Redisは書き込みを拒否し、特定のパラメータは構成できますが、後述します)
バッファサイズを
* *2
に設定することをお勧めします主従心拍メカニズム
サーバからデフォルトでは、1秒に1回の頻度でプライマリサーバにハートビートが送信されます.
REPLCONF AÇK
、replication_offsetは、サーバから現在コピーされているオフセットの量を表します.心拍数には3つの役割があります.
1.マスタスレーブサーバのネットワーク接続を検出する
2.min-slaves機能の実現
3.検出コマンドの紛失
プライマリ・スレーブ・サーバのネットワーク接続の検出
プライマリ・サーバは、サーバから最後に送信された心拍数がいつだったかを記録します.この時間によって、プライマリ・セカンダリ・サーバ間の接続に障害が発生したかどうかを知ることができます.
min-slaves機能の実現
Redisは、データのセキュリティを保証するために、サーバから
min-slaves-to-write
個未満またはmin-slaves-to-write
個未満のサーバからの遅延がmin-slaves-max-lag
個以上である場合、プライマリサーバが書き込みを拒否するように構成することができる.コマンドロスの検出
プライマリ・スレーブ間のレプリケーションは、実はプライマリ・サーバをスレーブ・サーバのクライアントとして実現される(Redisでは、すべてのサーバ間のデータ転送はこの方法で行われる).プライマリ・サーバがサーバから書き込みコマンドを送信したとしますが、ネットワークに異常が発生し、サーバからコマンドが受信されませんでした.これにより、データが一致しない状態になります(プライマリ・サーバがコマンドを送信した場合、エラーが返されなければ再送すればいいのではないでしょうか.コマンドが正常に実行されたからといって、プライマリに返信する際に問題が発生した場合、プライマリが再送するとデータが異常になります).したがって、プライマリサーバは、ハートビート情報に基づいて送信するデータを決定します.例を見てみましょう.
当初、プライマリ・サーバとセカンダリ・サーバのオフセット量はいずれも100であった.
プライマリ・サーバは、クライアントから書き込みコマンドを受信し、オフセット量を110に変更するとともに、書き込みコマンドをサーバから送信するが、ネットワーク上の理由でサーバから受信されず、そのオフセット量は依然として100である.プライマリ・サーバは、ハートビートによりサーバからのオフセット量が100より遅れていることを発見し、100-110のデータを再送する.
ここで、サーバから100-110のデータを受信する前に、プライマリサーバに現在100にオフセットしていることを通知し、100-110のデータを受信したことを疑問に思うかもしれません.このとき次の心拍数はまだ出ていません.メインサーバはサーバから自分に遅れていると思って、再び100-110のデータを送信して、サーバから再び100-110のデータを書き込んで、データの異常を招きます!
もしあなたがこの問題を考えたら、あなたが真剣に考えていることを意味します.
redisが単一スレッドであるため、このような状況は存在しません.単一スレッドの3つの字を覚えて、もう一度問題の説明を振り返って、あなたが理解できると信じています.
リファレンス
<>
、強くお勧めします!