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