Redis でダウンタイムを恐れることなく、高速なリカバリと永続性を実現するにはどうすればよいですか?次の記事で詳しく説明しますので、お役に立てれば幸いです。
#自立するのも正しいし、輪に溶け込むのも正しい、自分がどのような人生を送りたいのか、あなたはそれに対していくらの代償を払ってもいいでしょうか。
通常、読み取り応答パフォーマンスを向上させるために Redis をキャッシュとして使用します。Redis がダウンすると、メモリ内のすべてのデータが失われます。データベースに直接アクセスし、大量のトラフィックが MySQL にヒットすると、 、さらに多くの問題を引き起こす可能性があります。深刻な問題です。 [関連する推奨事項: Redis ビデオ チュートリアル ]
さらに、データベースから Redis へゆっくり読み取るパフォーマンスは、必然的に Redis からデータを取得するよりも速くなります。これにより、応答が遅くなります。減速する。
ダウンタイムを恐れることなく高速なリカバリを実現するために、Redis は、AOF (Append Only FIle) ログと RDB スナップショットという 2 つの主要なキラー機能を設計しました。
技術を学ぶとき、頭の中に完全な知識フレームワークやアーキテクチャ体系が確立されず、体系的な視点も持たずに、散在した技術点に触れるだけになってしまいます。これは非常に難しく、一見できるように見えますが、すぐに忘れて混乱してしまいます。
「Ma Ge Byte」に従って Redis を徹底的に理解し、Redis の核となる原則と実践的なスキルを深くマスターしてください。完全な知識フレームワークを構築し、グローバルな視点から知識システム全体を整理する方法を学びます。
この記事はハードコアです。保存して、「いいね!」をして、落ち着いて読むことをお勧めします。多くのことを得ることができると信じています。
前回の記事では、Redis のコア データ構造、IO モデル、スレッド モデルを分析し、さまざまなデータに応じて適切なデータ エンコーディングを使用しました。本当に速い理由を深く理解!
この記事では次の点に焦点を当てます:
関連するナレッジ ポイントは次の図に示すとおりです:
パノラマは、次の 2 つの次元を中心に拡張できます。
アプリケーションの次元: キャッシュの使用量、クラスターの使用量、データ構造の賢明な使用
システムの次元: 3 つの高さに分類できます
Redis シリーズの章は、次のマインド マップを中心に展開します。 Redis の高性能と永続化メカニズムの秘密を探ってみましょう。
パノラマ ビューを取得し、システム ビューをマスターします。
システム ビューは実際には非常に重要であり、問題を解決するときに、ある程度、システム ビューがあるということは、十分な根拠と組織的な方法で問題を特定し、解決できることを意味します。
65 兄弟: Redis が何らかの理由でダウンしているため、すべてのトラフィックがヒットします。バックエンド MySQL , すぐに Redis を再起動しましたが、データはメモリに保存されています。再起動してもデータが表示されないのはなぜですか? 再起動後のデータ損失を防ぐにはどうすればよいですか?
65 心配しないでください。「Code Byte」では、Redis がクラッシュした後に迅速に回復する方法を段階的に説明します。
Redis データはメモリに保存されていますが、メモリ内のデータをディスクに書き込むことを検討できますか? Redis が再起動すると、ディスクに保存されたデータがすぐにメモリに復元されるため、再起動後は通常のサービスが提供されます。
65 兄: 解決策を思いつきました。メモリを操作するために「書き込み」操作が実行されるたびに、同時にディスクに書き込まれます。
この解決策には致命的な問題があります: 書き込みコマンドがメモリだけでなくディスクにも書き込むたびに、ディスクのパフォーマンスがメモリに比べて遅すぎるため、Redis のパフォーマンスが大幅に低下します。 。
65 兄弟: この同時書き込みの問題を回避するにはどうすればよいですか?
通常、Redis をキャッシュとして使用するため、Redis がすべてのデータを保存しなくても、データベースを通じてデータを取得できるため、Redis がすべてのデータを保存するわけではありません。ダウンタイムからの迅速な復旧を実現する「RDB「データスナップショット」方式」。
65 兄:それでは、RDB メモリ スナップショットとは何ですか?
Redis が「write」コマンドを実行すると、メモリ データは変更され続けます。いわゆるメモリ スナップショットとは、ある時点での Redis メモリ内のデータのステータス データを指します。
それは、ある瞬間に時間が止まっているようなもので、写真を撮ると、その瞬間を写真として完全に記録することができます。
Redis もこれに似ており、特定の瞬間のデータをファイルの形式でキャプチャし、ディスクに書き込みます。このスナップショットファイルは RDB ファイルと呼ばれます (RDB は Redis DataBase の略です)。
Redis は RDB メモリ スナップショットを定期的に実行するため、「write」コマンドを実行するたびにディスクに書き込む必要はなく、メモリ スナップショットの作成時にのみディスクに書き込む必要があります。が実行されます。高速で壊れないことを保証するだけでなく、耐久性も実現し、ダウンタイムからの迅速な回復が可能です。
#データリカバリを行う場合、RDBファイルをメモリ上に直接読み込んでリカバリを完了します。
65 兄弟: どのデータのスナップショットを作成する必要がありますか?またはスナップショットを取得する頻度はどれくらいですか?これはスナップショットの実行効率に影響します。
65 わかりました。データの効率について考え始めています。前回の記事で、彼のシングルスレッド モデルでは、メイン スレッドをブロックする操作を可能な限り回避し、RDB ファイルの生成によってメイン スレッドがブロックされるのを回避する必要があると判断したことを学びました。
Redis は、RDB ファイルを生成するための 2 つの命令を提供します。
fork
を呼び出して、RDB ファイルを書き込むための子プロセスを生成します。スナップショットの永続化は子プロセスによって完全に処理され、親プロセスはクライアント要求の処理を続行します。デフォルトRDBファイルを生成するための設定です。 65 兄弟: メモリ データの「スナップショット」を取得する場合、メモリ データは変更できますか?つまり、書き込みコマンドが正常に処理できるか?
まず第一に、ブロッキングを回避することと、RDB ファイル生成中に書き込み操作を処理できることは同じことではないことを明確にする必要があります。メインスレッドはブロックされませんが、スナップショット データの一貫性を確保するために、読み取り操作のみを処理でき、実行中のスナップショットのデータを変更することはできません。
明らかに、Redis では RDB を生成するために書き込み操作を一時停止することはできません。
65 兄弟: Redis はどのようにして書き込みリクエストを処理し、RDB ファイルを同時に生成できるのでしょうか?
Redis は、オペレーティング システムのマルチプロセスコピー オン ライト テクノロジ COW (Copy On Write) を使用して、スナップショットの永続性を実現します。このメカニズムは非常に興味深いものですが、知っている人はほとんどいません。 。マルチプロセス COW は、プログラマの知識の広さを示す重要な指標でもあります。
Redis は永続化 fork
中に glibc 関数を呼び出して子プロセスを生成します。スナップショットの永続化は子プロセスによって完全に処理され、親プロセスはクライアント要求の処理を続行します。
子プロセスが作成されたばかりのとき、メモリ内のコード セグメントとデータ セグメントを親プロセスと共有します。このとき、父と息子のプロセスは、体を共有する結合双生児として想像できます。
これは Linux オペレーティング システムの仕組みであり、メモリ リソースを節約するには、メモリ リソースをできるだけ共有する必要があります。プロセスが分離された時点では、メモリの増加に明らかな変化はほとんどありません。
bgsave
子プロセスは、メインスレッドのすべてのメモリデータを共有し、メインスレッドのデータを読み取り、RDB ファイルに書き込むことができます。
SAVE
コマンドまたは BGSAVE
コマンドを実行して新しい RDB ファイルを作成するとき、プログラムはデータベース内のキーをチェックし、期限切れのキーは削除されません。新しく作成したRDBファイルに保存します。
メインスレッドが書き込みコマンドを実行してデータを変更すると、データがコピーされます。bgsave
子プロセスはコピーデータを読み取り、RDB ファイルに書き込むため、メインスレッドはスレッドは元のデータを直接変更できます。
これにより、スナップショットの整合性が確保されるだけでなく、メインスレッドが同時にデータを変更できるようになり、通常のビジネスへの影響が回避されます。
Redis は bgsave を使用して、現在のメモリ内のすべてのデータのスナップショットを取得します。この操作はバックグラウンドで子プロセスによって完了され、メインスレッドが同時にデータを変更できるようになります。 。
65 兄弟: RDB ファイルを毎秒実行できますか? この方法では、ダウンタイムがあっても最大 1 秒のデータが失われます。
フルデータ スナップショットを頻繁に実行すると、2 つの重大なパフォーマンス オーバーヘッドが発生します。
RDB ファイルを頻繁に生成してディスクに書き込むため、過剰なディスク負荷が発生します。前の RDB がまだ実行されていないように見え、次の RDB が再び生成され始め、無限ループに陥ります。
bgsave サブプロセスからフォークアウトすると、メイン スレッドがブロックされます。メイン スレッドのメモリが大きいほど、ブロック時間も長くなります。
メリットとデメリット
スナップショットの回復速度は速いですが、RDB ファイルの生成頻度の制御が困難です。低すぎるとマシンがクラッシュしたときにデータが失われ、それ以上になると、追加のオーバーヘッドが消費されます。
RDB はバイナリ データ圧縮を使用してディスクに書き込み、ファイル サイズが小さく、データ回復速度が高速です。
RDB の完全なスナップショットに加えて、Redis は AOF ポストライト ログも設計します。次に、AOF ログとは何かについて説明します。
AOF ログには、Redis サーバーの順次命令シーケンスが保存されます。AOF ログには、変更する命令のみが記録されます。記憶、記録。
Redis インスタンスの作成以降に変更されたすべての命令シーケンスが AOF ログに記録されていると仮定すると、空の Redis インスタンスですべての命令を順番に実行する、つまり「再生」することで、現在の Redis インスタンスのメモリを復元できます。データ構造の状態。
先行書き込みログ (WAL): データを実際に書き込む前に、変更はデータはログ ファイルに書き込まれ、障害の回復が保証されます。
たとえば、MySQL Innodb ストレージ エンジンの REDO ログ (REDO ログ) は、変更を記録するデータ ログであり、実際にデータを変更する前に、変更ログが記録され、変更されたデータが実行されます。
書き込み後のログ: 最初に「書き込み」コマンド要求を実行し、データをメモリに書き込み、その後ログを記録します。
Redis がメモリにデータを書き込むための「set key MageByte」コマンドを受信すると、Redis は次のように処理を進めます。 AOF ファイルを書き込むための形式に従います。
65 兄弟: Redis はなぜ書き込み後のログを使用するのですか?
ログの書き込み後は、追加のチェックのオーバーヘッドを回避し、実行されたコマンドの構文チェックを必要としません。先行書き込みログを使用する場合は、まず構文が正しいかどうかを確認する必要があります。そうでないと、ログに間違ったコマンドが記録され、ログ リカバリを使用するときにエラーが発生します。
さらに、ログは書き込み後に記録されます。 は現在の「書き込み」コマンドの実行をブロックしません。
65 兄弟: では、AOF は確実なのでしょうか?
愚かな少年、それはそれほど単純ではありません。 Redis がコマンドの実行を終了した直後で、ログを記録する前にクラッシュした場合、コマンドに関連するデータが失われる可能性があります。
また、AOF は現在のコマンドのブロックを回避しますが、次のコマンドをブロックするリスクをもたらす可能性があります。 AOF ログはメイン スレッドによって実行されます。ログをディスクに書き込むプロセス中に、ディスクの圧力が高いと、ディスクへの書き込みが非常に遅くなり、後続の「書き込み」命令がブロックされます。
もうわかりましたか? これら 2 つの問題はディスクのライトバックに関連しています。「write」コマンドの実行後に AOF ログをディスクに書き戻すタイミングを適切に制御できれば、問題は解決されます。 。
ファイルの書き込み効率を向上させるために、ユーザーが write
関数を呼び出してデータを書き込むとき、ファイル 、オペレーティング システムは通常、書き込まれたデータをメモリ バッファに一時的に保存し、バッファ スペースがいっぱいになるか、指定された制限時間を超えるまで待ってから、実際にバッファ内のデータをディスクに書き込みます。
このアプローチは効率を向上させますが、コンピューターがシャットダウンすると、メモリ バッファーに保存されている書き込みデータが失われるため、書き込まれたデータにセキュリティの問題も生じます。
この目的のために、システムは fsync
と fdatasync
という 2 つの同期関数を提供します。これらは、オペレーティング システムにバッファ内のデータをハードウェアに即座に書き込むように強制できます。ディスクに保存されるため、書き込まれたデータのセキュリティが確保されます。
Redis によって提供される AOF 構成アイテムappendfsync
ライトバック戦略は、AOF 永続化機能の効率とセキュリティを直接決定します。
aof_buf
バッファー内の内容が AOF ファイルに書き込まれます。 両方の利点を生かした戦略は存在しません。パフォーマンスと信頼性の間でトレードオフを行う必要があります。
常に
同期ライトバックではデータが失われないようにできますが、各「書き込み」コマンドをディスクに書き込む必要があるため、パフォーマンスが最悪になります。
everysec
1 秒ごとにライトバックし、同期ライトバックのパフォーマンス オーバーヘッドを回避します。ダウンタイムが発生した場合、ディスクに書き込まれたデータは 1 秒間失われる可能性があります。これは妥協策です。パフォーマンスと信頼性の間の妥協。
no
オペレーティング システム制御では、書き込みコマンドの実行後、AOF ファイル バッファーに書き込み、その後の「書き込み」コマンドを実行します。パフォーマンスは最高ですが、大量のデータが記録される可能性があります。失われます。
65 兄: では、どのように戦略を選択すればよいでしょうか?
システムの高性能と高信頼性の要件に基づいてライトバック戦略を選択できます。要約すると、高いパフォーマンスを実現したい場合は、「いいえ」戦略を選択し、高い信頼性を保証したい場合は、「常に」戦略を選択し、多少のデータ損失は許容するが、パフォーマンスに大きな影響を与えたい場合は、「常に」戦略を選択してください。毎秒戦略。
利点: ログは実行が成功した後にのみ記録されるため、命令構文チェックのオーバーヘッドが回避されます。同時に、現在の「書き込み」コマンドはブロックされません。
欠点: AOF は各命令の内容を記録するため、具体的な形式については上記のログ形式を参照してください。障害回復中にすべてのコマンドを実行する必要があるため、ログ ファイルが大きすぎると、回復プロセス全体が非常に遅くなります。
また、ファイルシステムにもファイルサイズの制限があり、大きすぎるファイルは保存できず、ファイルが大きくなるにつれて追記効率も悪くなります。
65 兄弟: AOF ログ ファイルが大きすぎる場合はどうすればよいですか?
AOF 書き込み前ログは、各「書き込み」コマンド操作を記録します。 RDB フルスナップショットのようなパフォーマンスの低下はありませんが、実行速度は RDB ほど速くありません。同時に、ログ ファイルが大きすぎるとパフォーマンスの問題も発生します。Redis のような高速化だけを求める本格的なユーザーにとっては、彼は大きすぎるログによって引き起こされる問題を絶対に容認できません。
そこで、Redis はキラーな「AOF 書き換えメカニズム」を設計しました。Redis は、AOF ログをスリム化するための bgrewriteaof
命令を提供します。
原理は、サブプロセスを開いてメモリを走査し、それを一連の Redis 操作命令に変換し、新しい AOF ログ ファイルにシリアル化することです。シリアル化完了後、運用中に発生した増分AOFログが新しいAOFログファイルに追記され、追記完了後直ちに古いAOFログファイルと置き換えられ、スリム化作業が完了します。
65 兄弟: AOF 書き換えメカニズムはなぜログ ファイルを縮小できるのですか?
書き換え機構には、古いログにある複数の命令を書き換え後に 1 つの命令に変換する「多対 1」機能があります。
以下に示すように、
AOF 書き換え後に 3 つの LPUSH 命令が生成され、複数回変更されたシーンでは、削減効果がより顕著になります。
#65 兄:書き換え後、AOF ログが小さくなり、最終的にはデータベース全体の最新データの操作ログがディスクにフラッシュされました。書き換えるとメインスレッドがブロックされますか?
「Brother Code」では、AOF ログがメイン スレッドによって書き戻されると説明しましたが、AOF 書き換えのプロセスは、メイン スレッドのブロックを防ぐために、実際にはバックグラウンド サブプロセス bgrewriteaof によって完了します。
書き換えプロセスは、メイン スレッドによって書き戻された AOF ログとは異なります。書き換えプロセスは、バックグラウンド サブプロセス bgrewriteaof によって完了します。これも同様です。メインスレッドがブロックされ、データベースのパフォーマンスが低下することを避けるため。
一般に、2 つのログ、1 つのメモリ データ コピー (古い AOF ログ、新しい AOF 書き換えログ、および Redis データ コピー) があります。
Redis は、書き換えプロセス中に受信した「書き込み」コマンド操作を古い AOF バッファーと AOF 書き換えバッファーに同時に記録するため、書き換えログには最新の操作も保存されます。コピーされたデータのすべての操作記録が書き換えられた後、書き換えバッファーに記録された最新の操作も新しい AOF ファイルに書き込まれます。 AOF が書き換えられるたびに、Redis はまずメモリ コピーを実行してデータを走査し、書き換えレコードを生成します。2 つのログを使用して、新しく書き込まれたデータが書き換えプロセス中に失われないことを確認し、データを維持します。一貫性。
#65 兄弟: AOF リライトにはリライト ログもありますが、なぜ AOF 自体のログを共有しないのですか?
これは次の 2 つの理由から良い質問です。
理由の 1 つは、親プロセスと子プロセスの間で同じファイルを書き込むと必然的に競合の問題が発生するためです。 . 競合を制御します。これは、親プロセスのパフォーマンスに影響を与えることを意味します。
AOF 書き換えプロセスが失敗すると、元の AOF ファイルは汚染されているのと同じになり、復元できなくなります。したがって、Redis AOF は新しいファイルを書き換えます。書き換えに失敗した場合は、ファイルを直接削除するだけで、元の AOF ファイルには影響しません。書き換えが完了したら、古いファイルを置き換えるだけです。
Redis 4.0 この問題を解決するために、新しい永続化オプション ハイブリッド永続化 が導入されました。 rdb ファイルの内容を増分 AOF ログ ファイルと一緒に保存します。ここでの AOF ログは完全なログではなく、永続化の開始から永続化の終了までの期間中に発生した増分 AOF ログです。通常、AOF ログのこの部分は非常に小さいです。
そのため、Redis を再起動するときに、最初に rdb コンテンツをロードしてから、増分 AOF ログを再生することができます。これにより、以前の AOF 完全ファイル再生を完全に置き換えることができ、再起動の効率が大幅に向上します。
そのため、RDB メモリ スナップショットは、AOF ログを使用して、2 つの RDB スナップショット中に発生したすべての「書き込み」操作を記録することにより、少し遅い頻度で実行されます。
このように、スナップショットを頻繁に実行する必要はありませんが、同時に、AOF は 2 つのスナップショットの間に発生する「書き込み」命令のみを記録する必要があるため、すべての操作を記録する必要はありません。過剰なファイルサイズを避けてください。
Redis は、スナップショットの実行中の読み取りおよび書き込み命令への影響を回避するために、bgsave と copy-on write を設計しました。頻繁なスナップショットはディスクに負担をかけ、 fork はメインスレッドをブロックします。
Redis は、データを損失することなくダウンタイムから迅速に回復するために、2 つの主要なキラー機能を設計しました。
ログの肥大化を防ぐため、データベースの最新のデータ状況に応じてデータ書き込み処理を新規ログとして生成し、バックグラウンドで書き込み処理を完了させるAOF書き換え機構を搭載しています。メインスレッドをブロックします。
AOF と RDB を統合することで、Redis 4.0 に新しい永続化戦略とハイブリッド ログ モデルが提供されます。 Redis を再起動すると、最初に rdb コンテンツをロードしてから、増分 AOF ログを再生できます。これにより、以前の AOF 完全ファイル再生を完全に置き換えることができ、再起動の効率が大幅に向上します。
最後に、AOF と RDB の選択に関して、「Code Byte」では 3 つの提案をしています。
お楽しみに...
元のアドレス: https://juejin.cn/post/6961735998547951653
著者: Code Brother Byte
プログラミング関連の知識について詳しくは、プログラミング ビデオをご覧ください。 !
以上がRedis でダウンタイムを恐れずに高速リカバリと永続性を実現する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。