ホームページ  >  記事  >  データベース  >  Redis 永続化戦略の簡単な分析

Redis 永続化戦略の簡単な分析

WBOY
WBOY転載
2022-11-09 14:35:411717ブラウズ

この記事では、Redis に関する関連知識を提供します。主に永続化戦略に関する関連コンテンツを紹介します。RDB 永続化とは、指定された時間間隔内でデータをメモリに保存するプロセスを指します。データ セットのスナップショットは次のとおりです。ディスクに書き込まれています。見てみましょう。皆さんのお役に立てれば幸いです。

Redis 永続化戦略の簡単な分析

推奨学習: Redis ビデオ チュートリアル

Redis (Remote Dictionary Server)、つまりリモート辞書サービス、は、オープンソースのインメモリ キャッシュ データ ストレージ サービスです。 ANSI C 言語で書かれており、ネットワーク、メモリベースおよび永続的なログタイプ、Key-Value データ ストレージをサポートし、複数の言語で API を提供します

Redis はインメモリ データベースであり、データはメモリに保存されますが、プロセスの終了によるデータの永久的な損失を避けるために、Redis 内のデータは何らかの形式 (データまたはコマンド) でメモリからハードディスクに定期的に保存する必要があります。次回 Redis を再起動するときは、永続ファイルを使用してデータを回復します。さらに、災害時バックアップの目的で、永続ファイルをリモートの場所にコピーできます。 Redis には 2 つの永続化メカニズムがあります:

  • RDB (Redis データベース) メモリ スナップショット
  • AOF (追加専用ファイル) 増分ログ

RDB は現在のデータをハードディスクに保存し、AOF は実行された各書き込みコマンドをハードディスクに保存します (MySQL の Binlog と同様)。 AOF 永続性はリアルタイム パフォーマンスが向上します。つまり、プロセスが予期せず終了したときに失われるデータが少なくなります。

RDB 永続性

概要

##RDB ( Redis データベース) は、指定された時間間隔内にメモリ内のデータ セットのスナップショットをディスクに書き込むことを指します。RDB はメモリ スナップショット (メモリ データのバイナリ シーケンス (永続化の形式で)、Redis からスナップショットが生成されるたびに、データを完全にバックアップします。

利点:

    コンパクトなストレージでメモリスペースを節約します。
    回復速度が非常に速いです。
    完全バックアップおよび完全レプリケーションのシナリオに適しており、災害復旧 (データの整合性と整合性の要件が比較的低いシナリオ) によく使用されます。
欠点:

    データが失われやすく、2 つのスナップショット間で Redis サーバー内のデータが変更されます。
  • RDB はフォーク子プロセスを使用してメモリ スナップショットを完全にバックアップします。これは重量のある操作であり、頻繁に実行するとコストがかかります。

Redis 永続化戦略の簡単な分析

RDB ファイル構造

デフォルトでは、Redis はデータベース スナップショットを dump.rdb という名前のファイルに保存します。バイナリーファイル。 RDB ファイル構造は 5 つの部分で構成されます。

(1)

REDIS 長さ 5 バイトの定数文字列。

(2) 4 バイトの db_version。RDB ファイルのバージョンを識別します。

(3)データベース: 0 個以上のデータベースと、各データベース内のキーと値のペアのデータを含む、長さは無限です。

(4) ファイル内容の終わりを示す 1 バイトの EOF 定数。

(5) check_sum: 8 バイトの符号なし整数、チェックサムを保存します。

Redis 永続化戦略の簡単な分析

データ構造の例。以下はデータベース [0] とデータベース [3] にデータがある状況です。

Redis 永続化戦略の簡単な分析

RDB ファイルの作成

手動指示トリガー

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 ファイルが最後に保存されてからサーバーが書き込んだ回数。

Redis 永続化戦略の簡単な分析

バックアップ プロセス

RDB 永続化スキームをバックアップする場合、Redis は永続化のために別の子プロセスをフォークし、データを一時ファイルに書き込み、データを一時ファイルに書き込みます。永続化が完了した後の古い RDB ファイル。永続化プロセス全体を通じて、メイン プロセス (クライアントにサービスを提供するプロセス) は IO 操作に参加しないため、Redis サービスの高いパフォーマンスが保証されます。RDB 永続化メカニズムは、高い要件を持たないアプリケーションに適しています。データの整合性を確保しながらも、効率的なリカバリを追求します。以下に、RDB 永続化プロセスを示します。

Redis 永続化戦略の簡単な分析

主な実行手順は次のとおりです。

  • Redis 親プロセスは、最初に次のことを決定します。 save が現在実行中です。または、bgsave/bgrewriteaof の子プロセスが実行中の場合、bgsave コマンドは直接戻ります。 bgsave/bgrewriteaof の子プロセスは、主にパフォーマンス上の考慮事項により同時に実行できません。2 つの同時子プロセスが同時に大量のディスク書き込み操作を実行するため、重大なパフォーマンス上の問題が発生する可能性があります。

  • 親プロセスは子プロセスを作成するためにフォーク操作を実行します。このプロセス中、親プロセスはブロックされ、Redis はクライアントからのコマンドを実行できません。親プロセスがフォークすると、bgsave コマンドは「バックグラウンド保存が開始されました」というメッセージを返し、親プロセスをブロックしなくなり、他のコマンドに応答できるようになります。
  • サブプロセス プロセスは、メモリ データのスナップショット ファイルを生成します。
  • この期間中に親プロセスによって受け取られた新しい書き込み操作は、COW メカニズムを使用して書き込まれます。
  • 子プロセスはスナップショットの書き込みを完了し、古い RDB ファイルを置き換えた後、子プロセスを終了します。

RDB ファイルを生成するステップで、ディスクへの同期と連続書き込みのプロセス中にデータの不整合にどのように対処するか?スナップショット RDB ファイルを生成するときにビジネスへの影響はありますか?

Fork サブプロセスの役割

前述したように、RDB 永続化プロセス中に、メイン プロセスは責任を負うサブプロセスをフォークします。 RDB バックアップの場合 これは簡単です fork を紹介します:

  • Linux オペレーティング システムのプログラムである fork は、親プロセスとまったく同じ子プロセスを生成します。子プロセスのすべてのデータは親プロセスのデータと一致しますが、子プロセスはまったく新しいプロセスであり、元のプロセスとは親子プロセス関係を持ちます。
  • 効率上の理由から、Linux オペレーティング システムは COW (Copy On Write) コピーオンライト メカニズムを使用しており、フォーク子プロセスは通常、物理メモリのセクションを親プロセスと共有します。プロセス空間内のメモリが変更されると、メモリ空間のコピーがコピーされます。

Redis では、RDB 永続化はこのテクノロジを最大限に活用しています。Redis は、永続化中に glibc 関数を呼び出して子プロセスをフォークし、永続化作業に対して完全な責任を負います。そのため、親プロセスは引き続き実行できます。クライアントにサービスを提供します。 fork の子プロセスは、最初は親プロセス (Redis のメイン プロセス) と同じメモリを共有します。永続化プロセス中にクライアントがメモリ内のデータの変更を要求すると、COW (Copy On Write) メカニズムが使用されます。メモリ内のデータを変更します。データ セグメント ページが分離されます。つまり、メイン プロセスが変更するためにメモリの一部がコピーされます。

Redis 永続化戦略の簡単な分析

fork によって作成された子プロセスは、親プロセスとまったく同じメモリ空間を取得できます。親プロセスによるメモリの変更は、子プロセスには認識されません。相互影響;

fork によって子プロセスを作成する場合、大量のメモリのコピーがすぐにトリガーされるのではなく、代わりに COW (Copy On Write) が使用されます。カーネルは、新しく生成された子プロセスの仮想空間構造のみを作成します。カーネルは、親プロセスの実際の仮想構造をコピーしますが、これらのセグメントに物理メモリを割り当てません。親プロセスの物理空間を共有します。親プロセスと子プロセスは、親プロセスの物理空間を共有します。プロセスは対応するセグメントを変更します。動作が発生すると、子プロセスの対応するセグメントに物理スペースが割り当てられます。

AOF 持久化

简介

AOF  (Append Only File)  是把所有对内存进行修改的指令(写操作)以独立日志文件的方式进行记录,重启时通过执行 AOF 文件中的 Redis 命令来恢复数据。类似MySql bin-log 原理。AOF 能够解决数据持久化实时性问题,是现在 Redis 持久化机制中主流的持久化方案。

Redis 永続化戦略の簡単な分析

优点:

  • 数据的备份更加完整,丢失数据的概率更低,适合对数据完整性要求高的场景
  • 日志文件可读,AOF 可操作性更强,可通过操作日志文件进行修复

缺点:

  • AOF 日志记录在长期运行中逐渐庞大,恢复起来非常耗时,需要定期对 AOF 日志进行瘦身处理
  • 恢复备份速度比较慢
  • 同步写操作频繁会带来性能压力

AOF 文件内容

被写入 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 持久化方案进行备份时,客户端所有请求的写命令都会被追加到 AOF 缓冲区中,缓冲区中的数据会根据 Redis 配置文件中配置的同步策略来同步到磁盘上的 AOF 文件中,追加保存每次写的操作到文件末尾。同时当 AOF 的文件达到重写策略配置的阈值时,Redis 会对 AOF 日志文件进行重写,给 AOF 日志文件瘦身。Redis 服务重启的时候,通过加载 AOF 日志文件来恢复数据。

Redis 永続化戦略の簡単な分析

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 文件,原因在于:

  • 过期的数据不再写入文件
  • 无效的命令不再写入文件:如有些数据被重复设值(set mykey v1, set mykey v2)、有些数据被删除了(sadd myset v1, del myset)等等
  • 多条命令可以合并为一个:如 sadd myset v1, sadd myset v2, sadd myset v3 可以合并为 sadd myset v1 v2 v3。不过为了防止单条命令过大造成客户端缓冲区溢出,对于 list、set、hash、zset类型的 key,并不一定只使用一条命令;而是以某个常量为界将命令拆分为多条。这个常量在 redis.h/REDIS_AOF_REWRITE_ITEMS_PER_CMD 中定义,不可更改,2.9版本中值是64。

AOF 重写

前面提到 AOF 的缺点时,说过 AOF 属于日志追加的形式来存储 Redis 的写指令,这会导致大量冗余的指令存储,从而使得 AOF 日志文件非常庞大,比如同一个 key 被写了 10000 次,最后却被删除了,这种情况不仅占内存,也会导致恢复的时候非常缓慢,因此 Redis 提供重写机制来解决这个问题。Redis 的 AOF 持久化机制执行重写后,保存的只是恢复数据的最小指令集,我们如果想手动触发可以使用如下指令:

bgrewriteaof

文件重写时机

相关参数:

  • aof_current_size:表示当前 AOF 文件空间
  • aof_base_size:表示上一次重写后 AOF 文件空间
  • auto-aof-rewrite-min-size: 表示运行 AOF 重写时文件的最小体积,默认为64MB
  • auto-aof-rewrite-percentage: 表示当前 AOF 重写时文件空间(aof_current_size)超过上一次重写后 AOF 文件空间(aof_base_size)的比值多少后会重写。

同时满足下面两个条件,则触发 AOF 重写机制:

  • aof_current_size 大于 auto-aof-rewrite-min-size
  • 当前 AOF 相比上一次 AOF 的增长率:(aof_current_size - aof_base_size)/aof_base_size 大于或等于 auto-aof-rewrite-percentage

AOF 重写流程如下:

  • bgrewriteaof 触发重写,判断是否存在 bgsave 或者 bgrewriteaof 正在执行,存在则等待其执行结束再执行

  • 主进程 fork 子进程,防止主进程阻塞无法提供服务,类似 RDB
  • 子进程遍历 Redis 内存快照中数据写入临时 AOF 文件,同时会将新的写指令写入 aof_buf 和 aof_rewrite_buf 两个重写缓冲区,前者是为了写回旧的 AOF 文件,后者是为了后续刷新到临时 AOF 文件中,防止快照内存遍历时新的写入操作丢失

  • 子进程结束临时 AOF 文件写入后,通知主进程

  • 主进程会将上面 3 中的 aof_rewirte_buf 缓冲区中的数据写入到子进程生成的临时 AOF 文件中

  • 主进程使用临时 AOF 文件替换旧 AOF 文件,完成整个重写过程。

Redis 永続化戦略の簡単な分析

在实际中,为了避免在执行命令时造成客户端输入缓冲区溢出,重写程序会检查集合元素数量是否超过 REDIS_AOF_REWRITE_ITEMS_PER_CMD 常量的值,如果超过了,则会使用多个命令来记录,而不单单使用一条命令。

Redis 2.9版本中该常量为64,如果一个命令的集合键包含超过了64个元素,重写程序会拆成多个命令。

Redis 永続化戦略の簡単な分析

AOF重写是一个有歧义的名字,该功能是通过直接读取数据库的键值对实现的,程序无需对现有AOF文件进行任何读入、分析或者写入操作。

思考

AOF 与 WAL

Redis 为什么考虑使用 AOF 而不是 WAL 呢?

很多数据库都是采用的 Write Ahead Log(WAL)写前日志,其特点就是先把修改的数据记录到日志中,再进行写数据的提交,可以方便通过日志进行数据恢复。

但是 Redis 采用的却是 AOF(Append Only File)写后日志,特点就是先执行写命令,把数据写入内存中,再记录日志。

システムに最初にコマンドを実行させると、正常に実行できたコマンドのみがログに記録されます。したがって、Redis は書き込み後のログを使用して、誤ったコマンドが記録されることを回避します。

もう 1 つの理由は、AOF はコマンドの実行後にのみログを記録するため、現在の書き込み操作はブロックされないことです。

AOF と RDB 間の相互作用

バージョン番号 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 形式のコンテンツが含まれているかどうかがチェックされます。

  • これが含まれている場合、サーバーは最初に最初の RDB データをロードし、次に後続の AOF データをロードします。
  • AOF ファイルに AOF データのみが含まれている場合、サーバーは AOF データを直接ロードします。

ログ ファイルの構造は次のとおりです:

Redis 永続化戦略の簡単な分析

概要

最後に この2つをまとめるとどちらが良いでしょうか?

  • 両方を有効にすることをお勧めします。
  • データが機密でない場合は、RDB を単独で使用することを選択できます。
  • 純粋なメモリ キャッシュを実行するだけの場合は、それを使用する必要はまったくありません。

    推奨学習: Redis ビデオ チュートリアル

    以上がRedis 永続化戦略の簡単な分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

    声明:
    この記事はjuejin.imで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。