この記事では、Redis に関する関連知識を提供します。主に永続化戦略に関する関連コンテンツを紹介します。RDB 永続化とは、指定された時間間隔内でデータをメモリに保存するプロセスを指します。データ セットのスナップショットは次のとおりです。ディスクに書き込まれています。見てみましょう。皆さんのお役に立てれば幸いです。
推奨学習: Redis ビデオ チュートリアル
Redis (Remote Dictionary Server)、つまりリモート辞書サービス、は、オープンソースのインメモリ キャッシュ データ ストレージ サービスです。 ANSI C 言語で書かれており、ネットワーク、メモリベースおよび永続的なログタイプ、Key-Value データ ストレージをサポートし、複数の言語で API を提供します
Redis はインメモリ データベースであり、データはメモリに保存されますが、プロセスの終了によるデータの永久的な損失を避けるために、Redis 内のデータは何らかの形式 (データまたはコマンド) でメモリからハードディスクに定期的に保存する必要があります。次回 Redis を再起動するときは、永続ファイルを使用してデータを回復します。さらに、災害時バックアップの目的で、永続ファイルをリモートの場所にコピーできます。 Redis には 2 つの永続化メカニズムがあります:
RDB は現在のデータをハードディスクに保存し、AOF は実行された各書き込みコマンドをハードディスクに保存します (MySQL の Binlog と同様)。 AOF 永続性はリアルタイム パフォーマンスが向上します。つまり、プロセスが予期せず終了したときに失われるデータが少なくなります。
##RDB ( Redis データベース) は、指定された時間間隔内にメモリ内のデータ セットのスナップショットをディスクに書き込むことを指します。RDB はメモリ スナップショット (メモリ データのバイナリ シーケンス (永続化の形式で)、Redis からスナップショットが生成されるたびに、データを完全にバックアップします。
利点:REDIS 長さ 5 バイトの定数文字列。
手動指示トリガー
save コマンドと
bgsave コマンド、これら 2 つのコマンドの違いは次のとおりです。
save:
save コマンドを実行して、Redis の他の操作をブロックします。 Redis がクライアント要求に応答できなくなるため、推奨されません。
bgsave:
bgsave コマンドを実行すると、Redis はバックグラウンドで子プロセスを作成し、スナップショットを非同期で保存します。この時点では、Redis はまだクライアントのリクエスト。
自動間隔保存
デフォルトでは、Redis はデータベース スナップショットを dump.rdb という名前のバイナリ ファイルに保存します。 Redis は、「N 秒以内にデータ セットに少なくとも M 個の変更がある」という条件が満たされた場合にデータ セットを自動的に保存するように設定できます。 たとえば、次の設定では、「60 秒以内に少なくとも 10 個のキーが変更された」という条件を満たす場合、Redis はデータ セットを自動的に保存します:save 60 10。
Redis のデフォルト構成は次のとおりです。3 つの設定のいずれかが満たされた場合に自動保存をトリガーできます:
save 60 10000 save 300 10 save 900 1
自動保存構成のデータ構造
サーバー トリガーを記録します。自動 BGSAVE
条件の saveparams
属性。
lastsave
属性: サーバーが最後に SAVE
または BGSAVE
を実行した時刻を記録します。
dirty
属性: RDB ファイルが最後に保存されてからサーバーが書き込んだ回数。
RDB 永続化スキームをバックアップする場合、Redis は永続化のために別の子プロセスをフォークし、データを一時ファイルに書き込み、データを一時ファイルに書き込みます。永続化が完了した後の古い RDB ファイル。永続化プロセス全体を通じて、メイン プロセス (クライアントにサービスを提供するプロセス) は IO 操作に参加しないため、Redis サービスの高いパフォーマンスが保証されます。RDB 永続化メカニズムは、高い要件を持たないアプリケーションに適しています。データの整合性を確保しながらも、効率的なリカバリを追求します。以下に、RDB 永続化プロセスを示します。
主な実行手順は次のとおりです。
Redis 親プロセスは、最初に次のことを決定します。 save が現在実行中です。または、bgsave/bgrewriteaof の子プロセスが実行中の場合、bgsave コマンドは直接戻ります。 bgsave/bgrewriteaof の子プロセスは、主にパフォーマンス上の考慮事項により同時に実行できません。2 つの同時子プロセスが同時に大量のディスク書き込み操作を実行するため、重大なパフォーマンス上の問題が発生する可能性があります。
RDB ファイルを生成するステップで、ディスクへの同期と連続書き込みのプロセス中にデータの不整合にどのように対処するか?スナップショット RDB ファイルを生成するときにビジネスへの影響はありますか?
前述したように、RDB 永続化プロセス中に、メイン プロセスは責任を負うサブプロセスをフォークします。 RDB バックアップの場合 これは簡単です fork を紹介します:
Redis では、RDB 永続化はこのテクノロジを最大限に活用しています。Redis は、永続化中に glibc 関数を呼び出して子プロセスをフォークし、永続化作業に対して完全な責任を負います。そのため、親プロセスは引き続き実行できます。クライアントにサービスを提供します。 fork の子プロセスは、最初は親プロセス (Redis のメイン プロセス) と同じメモリを共有します。永続化プロセス中にクライアントがメモリ内のデータの変更を要求すると、COW (Copy On Write) メカニズムが使用されます。メモリ内のデータを変更します。データ セグメント ページが分離されます。つまり、メイン プロセスが変更するためにメモリの一部がコピーされます。
fork によって作成された子プロセスは、親プロセスとまったく同じメモリ空間を取得できます。親プロセスによるメモリの変更は、子プロセスには認識されません。相互影響;
fork によって子プロセスを作成する場合、大量のメモリのコピーがすぐにトリガーされるのではなく、代わりに COW (Copy On Write) が使用されます。カーネルは、新しく生成された子プロセスの仮想空間構造のみを作成します。カーネルは、親プロセスの実際の仮想構造をコピーしますが、これらのセグメントに物理メモリを割り当てません。親プロセスの物理空間を共有します。親プロセスと子プロセスは、親プロセスの物理空間を共有します。プロセスは対応するセグメントを変更します。動作が発生すると、子プロセスの対応するセグメントに物理スペースが割り当てられます。
AOF (Append Only File) 是把所有对内存进行修改的指令(写操作)以独立日志文件的方式进行记录,重启时通过执行 AOF 文件中的 Redis 命令来恢复数据。类似MySql bin-log 原理。AOF 能够解决数据持久化实时性问题,是现在 Redis 持久化机制中主流的持久化方案。
优点:
缺点:
被写入 AOF 文件的所有命令都是以 RESP 格式保存的,是纯文本格式保存在 AOF 文件中。
Redis 客户端和服务端之间使用一种名为
RESP(REdis Serialization Protocol)
的二进制安全文本协议进行通信。
下面以一个简单的 SET 命令进行举例:
redis> SET mykey "hello" //客户端命令OK
客户端封装为以下格式(每行用 \r\n
分隔)
*3$3SET$5mykey$5hello
AOF 文件中记录的文本内容如下
*2\r\n$6\r\nSELECT\r\n$1\r\n0\r\n //多出一个SELECT 0 命令,用于指定数据库,为系统自动添加 *3\r\n$3\r\nSET\r\n$5\r\nmykey\r\n$5\r\nhello\r\n
AOF 持久化方案进行备份时,客户端所有请求的写命令都会被追加到 AOF 缓冲区中,缓冲区中的数据会根据 Redis 配置文件中配置的同步策略来同步到磁盘上的 AOF 文件中,追加保存每次写的操作到文件末尾。同时当 AOF 的文件达到重写策略配置的阈值时,Redis 会对 AOF 日志文件进行重写,给 AOF 日志文件瘦身。Redis 服务重启的时候,通过加载 AOF 日志文件来恢复数据。
AOF 的执行流程包括:
命令追加(append)
Redis 先将写命令追加到缓冲区 aof_buf,而不是直接写入文件,主要是为了避免每次有写命令都直接写入硬盘,导致硬盘 IO 成为 Redis 负载的瓶颈。
struct redisServer { //其他域... sds aof_buf; // sds类似于Java中的String //其他域...}
文件写入(write)和文件同步(sync)
根据不同的同步策略将 aof_buf 中的内容同步到硬盘;
Linux 操作系统中为了提升性能,使用了页缓存(page cache)。当我们将 aof_buf 的内容写到磁盘上时,此时数据并没有真正的落盘,而是在 page cache 中,为了将 page cache 中的数据真正落盘,需要执行 fsync / fdatasync 命令来强制刷盘。这边的文件同步做的就是刷盘操作,或者叫文件刷盘可能更容易理解一些。
AOF 缓存区的同步文件策略由参数 appendfsync 控制,有三种同步策略,各个值的含义如下:
always
:命令写入 aof_buf 后立即调用系统 write 操作和系统 fsync 操作同步到 AOF 文件,fsync 完成后线程返回。这种情况下,每次有写命令都要同步到 AOF 文件,硬盘 IO 成为性能瓶颈,Redis 只能支持大约几百TPS写入,严重降低了 Redis 的性能;即便是使用固态硬盘(SSD),每秒大约也只能处理几万个命令,而且会大大降低 SSD 的寿命。可靠性较高,数据基本不丢失。no
:命令写入 aof_buf 后调用系统 write 操作,不对 AOF 文件做 fsync 同步;同步由操作系统负责,通常同步周期为30秒。这种情况下,文件同步的时间不可控,且缓冲区中堆积的数据会很多,数据安全性无法保证。everysec
:命令写入 aof_buf 后调用系统 write 操作,write 完成后线程返回;fsync 同步文件操作由专门的线程每秒调用一次。everysec 是前述两种策略的折中,是性能和数据安全性的平衡,因此是 Redis 的默认配置,也是我们推荐的配置。文件重写(rewrite)
定期重写 AOF 文件,达到压缩的目的。
AOF 重写是 AOF 持久化的一个机制,用来压缩 AOF 文件,通过 fork 一个子进程,重新写一个新的 AOF 文件,该次重写不是读取旧的 AOF 文件进行复制,而是读取内存中的Redis数据库,重写一份 AOF 文件,有点类似于 RDB 的快照方式。
文件重写之所以能够压缩 AOF 文件,原因在于:
前面提到 AOF 的缺点时,说过 AOF 属于日志追加的形式来存储 Redis 的写指令,这会导致大量冗余的指令存储,从而使得 AOF 日志文件非常庞大,比如同一个 key 被写了 10000 次,最后却被删除了,这种情况不仅占内存,也会导致恢复的时候非常缓慢,因此 Redis 提供重写机制来解决这个问题。Redis 的 AOF 持久化机制执行重写后,保存的只是恢复数据的最小指令集,我们如果想手动触发可以使用如下指令:
bgrewriteaof
文件重写时机
相关参数:
同时满足下面两个条件,则触发 AOF 重写机制:
AOF 重写流程如下:
bgrewriteaof 触发重写,判断是否存在 bgsave 或者 bgrewriteaof 正在执行,存在则等待其执行结束再执行
子进程遍历 Redis 内存快照中数据写入临时 AOF 文件,同时会将新的写指令写入 aof_buf 和 aof_rewrite_buf 两个重写缓冲区,前者是为了写回旧的 AOF 文件,后者是为了后续刷新到临时 AOF 文件中,防止快照内存遍历时新的写入操作丢失
子进程结束临时 AOF 文件写入后,通知主进程
主进程会将上面 3 中的 aof_rewirte_buf 缓冲区中的数据写入到子进程生成的临时 AOF 文件中
在实际中,为了避免在执行命令时造成客户端输入缓冲区溢出,重写程序会检查集合元素数量是否超过 REDIS_AOF_REWRITE_ITEMS_PER_CMD 常量的值,如果超过了,则会使用多个命令来记录,而不单单使用一条命令。
Redis 2.9版本中该常量为64,如果一个命令的集合键包含超过了64个元素,重写程序会拆成多个命令。
AOF重写是一个有歧义的名字,该功能是通过直接读取数据库的键值对实现的,程序无需对现有AOF文件进行任何读入、分析或者写入操作。
Redis 为什么考虑使用 AOF 而不是 WAL 呢?
很多数据库都是采用的 Write Ahead Log(WAL)写前日志,其特点就是先把修改的数据记录到日志中,再进行写数据的提交,可以方便通过日志进行数据恢复。
但是 Redis 采用的却是 AOF(Append Only File)写后日志,特点就是先执行写命令,把数据写入内存中,再记录日志。
システムに最初にコマンドを実行させると、正常に実行できたコマンドのみがログに記録されます。したがって、Redis は書き込み後のログを使用して、誤ったコマンドが記録されることを回避します。
もう 1 つの理由は、AOF はコマンドの実行後にのみログを記録するため、現在の書き込み操作はブロックされないことです。
バージョン番号 2.4 以降の Redis では、BGSAVE の実行中に BGREWRITEAOF を実行できません。一方、BGREWRITEAOF 実行中は BGSAVE を実行できません。これにより、2 つの Redis バックグラウンド プロセスがディスク上で同時に大量の I/O 操作を実行するのを防ぎます。
BGSAVE が実行中で、ユーザーが BGREWRITEAOF コマンドを明示的に呼び出した場合、サーバーはユーザーに OK ステータスを返し、BGREWRITEAOF の実行がスケジュールされていることをユーザーに通知します。BGSAVE が完了すると、BGREWRITEAOF が正式に開始されます。 。
Redis の起動時に、RDB 永続性と AOF 永続性の両方がオンになっている場合、通常は AOF ファイルに保存されたデータが最も完全であるため、プログラムは AOF ファイルを使用してデータセットを復元することを優先します。
Redis 4.0 以降、ほとんどの使用シナリオでは、RDB または AOF を永続化メカニズムとして単独で使用するのではなく、両方を考慮するようになります。 。その理由は、RDBは高速ではありますが、多くのデータが失われ、データの完全性が保証できないためであり、AOFはデータの完全性を可能な限り保証できるものの、データの再生や回復などのパフォーマンスには確かに批判があるからです。
Redis は、バージョン 4.0 以降、RDB-AOF ハイブリッド永続モードを導入しました。このモードは、AOF 永続モードに基づいて構築されています。ハイブリッド永続パス aof-use-rdb-preamble yes
オンにする。
その後、Redis サーバーが AOF 書き換え操作を実行すると、BGSAVE コマンドを実行するのと同じように、データベースの現在のステータスに基づいて対応する RDB データが生成され、これらのデータが新しく作成された AOF ファイルに書き込まれます。 Redis の場合、AOF 書き換え開始後に実行されるコマンドは、引き続き新しい AOF ファイルの末尾、つまり既存の RDB データの後にプロトコル テキストの形式で追加されます。
つまり、RDB-AOFハイブリッド永続化機能をオンにすると、サーバーが生成するAOFファイルは2つの部分から構成され、AOFファイルの先頭のデータがRDB形式のデータとなります。とそれに続くRDBデータ 以下はAOF形式のデータです。
RDB-AOF ハイブリッド永続モードをサポートする Redis サーバーが起動して AOF ファイルをロードすると、AOF ファイルの先頭に RDB 形式のコンテンツが含まれているかどうかがチェックされます。
ログ ファイルの構造は次のとおりです:
最後に この2つをまとめるとどちらが良いでしょうか?
推奨学習: Redis ビデオ チュートリアル
以上がRedis 永続化戦略の簡単な分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。