Redis はインメモリ データベースであり、データはメモリに保存されます。プロセスの終了によるデータの永久的な損失を避けるために、Redis 内のデータは定期的に何らかの形式で保存されます (データまたはコマンド) はメモリからハードディスクに保存されます。次回 Redis を再起動するときに、永続ファイルを使用してデータを回復します。さらに、災害時バックアップの目的で、永続ファイルをリモートの場所にコピーできます。
Redis は、複数の異なるレベルの永続化メソッドを提供します。1 つは RDB、もう 1 つは AOF です。
RDB 永続性は、指定された時間間隔内でデータ セットのポイントインタイム スナップショットを生成し、データベース スナップショットをバイナリ形式でディスクに保存できます。
AOF は、サーバーによって実行されたすべての変更操作コマンドを永続的に記録します。AOF ファイル内のすべてのコマンドは Redis プロトコルの形式で保存され、新しいコマンドはファイルの末尾に追加されます。 Redis は、AOF ファイルのサイズがデータ セットの状態を保存するために必要な実際のサイズを超えないように、バックグラウンドで AOF ファイルを書き換えることもできます。
Redis は、AOF 永続性と RDB 永続性を同時に使用できます。この場合、Redis が再起動すると、AOF ファイルを使用してデータセットを復元することが優先されます。これは、AOF ファイルによって保存されたデータセットは、通常、RDB ファイルによって保存されたデータセットよりも完全であるためです。永続性をオフにして、サーバーの実行中にのみデータが存在するようにすることもできます。
RDB 永続化と AOF 永続化の類似点と相違点を理解することは非常に重要です。次のセクションでは、これら 2 つの永続化関数を詳細に紹介し、それらの類似点と相違点について説明します。
Redis の最初の永続化戦略である RDB スナップショットについて話しましょう。 Redis は、現在のメモリ データのスナップショットをデータ ファイルに保存する永続化メカニズムをサポートしています。継続的に書き込まれるデータベースはどのようにしてスナップショットを生成しますか? Redis は、fork コマンドのコピー オン ライト メカニズムを巧みに使用して、現在のプロセスを子プロセスにフォークし、子プロセスはメモリ スナップショットに基づいてデータを RDB ファイルに周期的に永続化します。
デフォルトでは、Redis はルート ディレクトリの dump.rdb という名前のバイナリ ファイルにデータベース スナップショットを保存します。パラメータ dir 設定を通じて保存ディレクトリを指定でき、dbfilename でファイル名を指定します。 Redis では、「N M 回保存」などの設定が可能です。これは、N 秒以内にデータ項目に M 回の変更があり、この条件が満たされた場合にデータセットが自動的に保存されることを意味します。たとえば、10 分以内に 100 件の書き込みがあった場合にスナップショットを生成するように設定したり、1 分以内に 1,000 件の書き込みがあった場合にスナップショットを生成するように設定したり、複数のルールを同時に有効にすることができます。ルールが一致すると有効になります。これらのルールの定義は Redis 構成ファイルにあり、Redis を再起動せずに Redis CONFIG SET コマンドを使用して Redis の実行中にルールを設定することもできます。
たとえば、次の設定では、「60 秒以内に少なくとも 1000 個のキーが変更された」という条件を満たした場合に、Redis がデータ セットを自動的に保存します。 SAVE または BGSAVE を呼び出して、Redis にデータセットを手動で保存させます。 SAVE コマンドは同期操作を実行し、すべてのデータのスナップショットを RDB ファイルの形式で保存します。SAVE コマンドは、すべてのクライアント要求をブロックするため、実稼働環境で直接使用されることはほとんどありません。実稼働環境では使用しないでください。代わりに BGSAVE コマンドを使用できます。 BGSAVE コマンドは子プロセスをフォークすることによって実行されるため、クライアントのリクエストはブロックされません。子プロセスをフォークする場合のみサーバーがブロックされます。さらに、RDB 永続化を自動的にトリガーする場合、Redis は永続化のために SAVE ではなく BGSAVE を選択します。
Redis の自動 RDB 永続化は、serverCron 定期操作機能、ダーティ カウンタ、lastsave タイムスタンプを通じて内部的に実装されています。 ServerCron は 100ms ごとに実行され、「save N M」が条件を満たしているかどうかをチェックし、条件を満たしている場合は BGSAVE を実行するなど、サーバーの状態をチェックします。もちろん、AOF の書き換えチェックも含まれます。ダーティ カウンタは、Redis サーバーによって維持される状態であり、BGSAVE/SAVE コマンドが最後に実行されてからサーバーのステータスが変更された回数 (追加、削除、変更を含む) を記録します。 、ダーティは 0 にリセットされます。 lastsave タイムスタンプも Redis サーバーによって維持される状態です。BGSAVE/SAVE が最後に正常に実行された時刻を記録します。現在の時刻から lastsave を引いた値は M を満たす必要があります。
手動および自動に加えて、BGSAVE をトリガーする状況が他にもいくつかあります。
マスター/スレーブ レプリケーション シナリオでは、スレーブ ノードがフル コピー操作を実行すると、マスター ノードはBGSAVEコマンドを実行し、rdbファイルをスレーブノードに送信します。 shutdownコマンドを実行すると、自動的にRDB永続化が行われます。さらに、書き込み操作は新しいプロセスで実行されるため、新しい RDB ファイルが生成されると、Redis によって生成された子プロセスが最初にデータを一時ファイルに書き込み、次にアトミックな名前変更システムを呼び出すことを理解する必要があります。一時ファイルの名前を RDB ファイルに変更して、いつ障害が発生しても Redis RDB ファイルを常に使用できるようにします。
这种持久化方式被称为快照(snapshot)。但是,我们可以很明显的看到,RDB有他的不足,就是一旦数据库出现问题,那么我们的RDB文件中保存的数据并不是全新的,从上次RDB文件生成到Redis停机这段时间的数据全部丢掉了。在某些业务下,如果可以忍受间隔内数据丢失,我们也推荐这些业务使用RDB的方式进行持久化,因为开启RDB的代价并不高。但是对于另外一些对数据安全性要求极高的应用,无法容忍数据丢失的应用,RDB就无能为力了,所以Redis引入了另一个重要的持久化机制,AOF日志方式持久化。
为了尽可能使RDB文件体积减小,Redis默认采用LZF算法对RDB文件进行压缩。虽然压缩耗时,但是可以大大减小RDB文件的体积,因此压缩默认开启,参数为rdbcompression。需要注意的是,RDB文件的压缩并不是针对整个文件进行的,而是对数据库中的字符串进行的,且只有在字符串达到一定长度(20字节)时才会进行。
除了压缩,你也可以检验RDB文件,通过参数rdbchecksum设置,默认为yes。在写入文件和读取文件时都起作用,关闭checksum在写入文件和启动文件时大约能带来10%的性能提升,但是数据损坏时无法发现。
另外,当bgsave出现错误时,Redis是否停止执行写命令。Redis提供了一个参数stop-writes-on-bgsave-error,设置为yes,则当硬盘出现问题时,可以及时发现,避免数据的大量丢失;设置为no,则Redis无视bgsave的错误继续执行写命令,当对Redis服务器的系统(尤其是硬盘)使用了监控时,该选项考虑设置为no。
父进程通过fork操作可以创建子进程,第一代Unix系统实现了一种傻瓜式的进程创建:当执行fork系统调用时,内核复制父进程的整个用户空间并把复制得到的那一份分配给子进程。这种行为时非常耗时的,因为它需要完成以下几项任务:为子进程的页表分配页面、为子进程的页分配页面、初始化子进程的页表、把父进程的页复制到子进程对应的页中。
现在Linux的fork()使用写时拷贝(copy-on-write)页实现。写时拷贝是一种可以推迟甚至免除拷贝数据的技术。内核此时并不复制整个进程地址空间,而是让父进程和子进程共享同一个拷贝。只有在需要写入的时候,数据才会被复制,从而使各个进程拥有各自的拷贝。也就是说,资源的复制只有在需要写入的时候才进行,在此之前,只是以只读方式共享。这种技术使地址空间上的页的拷贝被推迟到实际发生写入的时候。所以就算fork很大内存的进程,对内存的消耗和耗时都很小。
现在虽然fork时,子进程不会复制父进程的数据空间,但是会复制内存页表(页表相当于内存的索引、目录);父进程的数据空间越大,内存页表越大,fork时复制耗时也会越多。这个问题也是导致Redis内存不宜过大的原因之一,当然还有导致故障恢复时间延长也是Redis内存不宜过大的原因。
通过上面的分析,我们知道RDB快照有大概率丢失最近写入、且仍未保存到快照中的那些数据。尽管对于某些程序来说,数据安全并不是最重要的考虑因素,但是对于那些追求数据安全的程序来说,快照功能就不太适用了。从1.1版本开始,Redis增加了一种实时性更好的持久化方式,即AOF持久化。AOF日志的全称是append only file,从名字上我们就能看出来,它是一个追加写入的日志文件。与RDB相比,AOF的实时性更好,因此已成为主流的持久化方案。
AOF文件与MySQL数据库的binlog不同的是,AOF是一种纯文本格式,具有兼容性好、可读性强、容易处理、操作简单避免二次开销等优点,它记录的内容就是一个个的Redis标准命令。开启AOF持久化命令如下:
appendonly yes appendfilename "appendonly.aof"
从现在开始,每当Redis执行一个改变数据集的命令时(比如SET),这个命令就会被追加到AOF文件的末尾。这样的话,当Redis重新启时,程序就可以通过重新执行AOF文件中的命令来达到重建数据集的目的。
由于需要记录Redis的每条写命令,因此AOF不需要触发,下面介绍AOF的执行流程:
Redis先将写命令追加到缓冲区,而不是直接写入文件,主要是为了避免每次有写命令都直接写入硬盘,导致硬盘IO成为Redis负载的瓶颈。
Redis提供了多种AOF缓存区的同步文件策略,策略涉及到操作系统的write函数和fsync函数,说明如下:
ファイルの書き込み効率を向上させるために、最新のオペレーティング システムでは、ユーザーが書き込み関数を呼び出してデータをファイルに書き込むと、通常、オペレーティング システムはデータをメモリ バッファに一時的に保存します。バッファがいっぱいになったとき、またはバッファがいっぱいになった後、指定された制限時間を超えると、バッファ内のデータが実際にハードディスクに書き込まれます。このような操作により効率は向上しますが、セキュリティ上の問題も発生します。コンピュータがシャットダウンすると、メモリ バッファ内のデータが失われるため、システムは、オペレーティング システムに強制的に同期機能を提供する fsync や fdatasync などの同期機能も提供します。バッファ内のデータをただちに転送します。データのセキュリティを確保するために、データはハードディスクに書き込まれます。
AOF キャッシュ領域の同期ファイル戦略は、パラメータ appendfsync によって制御されます。各値の意味は次のとおりです:
always: コマンドが aof_buf に書き込まれた直後、システムはAOF ファイルと同期するために fsync 操作が呼び出され、fsync が完了するとスレッドが戻ります。この場合、すべての書き込みコマンドを AOF ファイルに同期する必要があり、ハードディスク IO がパフォーマンスのボトルネックになります。Redis は約数百 TPS 書き込みしかサポートできず、たとえソリッド ステート ドライブ ( SSD) が使用されると、1 秒あたり数万のコマンドしか処理できず、SSD の寿命が大幅に短くなります。
no: コマンドが aof_buf に書き込まれた後、システム書き込み操作が呼び出され、AOF ファイルの fsync 同期は実行されません。同期はオペレーティング システムによって処理され、同期期間は通常 30 です。秒。この場合、ファイルの同期時間が制御できなくなり、バッファに大量のデータが蓄積され、データのセキュリティが保証されなくなります。 Everysec: コマンドが aof_buf に書き込まれた後、システム書き込み操作が呼び出されます。書き込みが完了するとスレッドが戻ります。fsync 同期ファイル操作は、専用スレッドによって 1 秒に 1 回呼び出されます。 Everysec は、パフォーマンスとデータ セキュリティのバランスを考慮した、前述の 2 つの戦略の間の妥協案であるため、Redis のデフォルト構成であり、推奨される構成です。
AOF はファイルの末尾にコマンドを追加し続けることで動作するため、書き込みコマンドの数が増加し続けると、AOF ファイルのサイズも増加します。 . どんどん大きくなっていきます。たとえば、カウンターに対して INCR を 100 回呼び出した場合、AOF ファイルはカウンターの現在の値を保存するためだけに 100 個のエントリを使用する必要があります。ただし、実際には、カウンターの現在の値を保存するには SET コマンドを 1 つだけ使用するだけで十分で、残りの 99 レコードは実際には冗長です。さらに、期限切れのデータや無効なデータも削除できる場合があります。
AOF ファイルが大きすぎると、サーバーの通常の動作に影響を与えるだけでなく、データの回復に時間がかかりすぎます。この状況に対処するために、Redis はサービス クライアントを中断せずに AOF ファイルを再構築できる興味深い機能をサポートしています。 BGREWRITEAOF コマンドを実行すると、Redis によって新しい AOF ファイルが生成されます。このファイルには、現在のデータ セットを再構築するために必要な最小限のコマンドが含まれています。
AOF REWRITE (リライト) 生成プロセスは RDB スナップショットに似ており、どちらもコピー オン ライト メカニズムを巧みに利用しています。また、子プロセスもフォークされます (この時点でメイン スレッドはブロックされます)。子プロセスは、メモリ スナップショットとコマンド マージ ルールに従って、新しい AOF ファイルに書き込みます。メイン プロセスが子スレッドをフォークし、リクエストを受け入れ続ける場合でも、すべての書き込みコマンドは AOF バッファ (aof_buf) に書き込まれ、appendfsync ポリシーに従ってハード ディスクに同期され、元の AOF メカニズムの正確性が保証されます。ただし、フォーク操作ではコピーオンライト技術が使用されるため、子プロセスはフォーク操作中にのみメモリ データを共有できます。親プロセスはまだコマンドに応答しているため、Redis は AOF 書き換えバッファ (aof_rewrite_buf) を使用して新しいログのこの部分を保存し、新しい AOF ファイルの生成中にデータのこの部分が失われるのを防ぎます。つまり、bgrewriteaof の実行中に、Redis 書き込みコマンドが 2 つのバッファー aof_buf および aof_revirte_buf に同時に追加されます。
子プロセスが新しい AOF ファイルの書き込みを完了すると、親プロセスにシグナルが送信され、親プロセスは統計情報を更新します。統計情報は情報永続化を通じて表示できます。次に、親プロセスは AOF 書き換えバッファ内のデータを新しい AOF ファイルに書き込み、新しい AOF ファイルに保存されたデータベースの状態がサーバーの現在の状態と一致することを保証します。次に、atomic rename コマンドを呼び出して古い AOF ファイルを新しい AOF ファイルに置き換え、AOF の書き換えを完了します。
メインプロセスは aof_rewrite_buf キャッシュを新しいログ ファイルに追加するため、ここで注意する必要があります。メインプロセスがログを追加するとき、他のリクエストは処理されません。aof_rewrite_buf が数百 M など特に大きい場合、Redis が数秒、場合によっては数十秒応答しなくなる可能性があります。
上記のプロセスから、RDB 操作と AOF 操作は両方ともシーケンシャル IO 操作であり、そのパフォーマンスが非常に高いことがわかります。 RDB ファイルまたは AOF ログを通じてデータベースを復元する場合、データも順次に読み取られてメモリにロードされます。したがって、ディスクのランダムな読み取りが発生することはありません。
ファイル書き換えのトリガーは、手動トリガーと自動トリガーに分けられます:
手動トリガー: bgrewriteaof コマンドを直接呼び出します。このコマンドの実行は bgsave に似ています。どちらもフォーク サブコマンドです。特定の操作を実行するプロセスは機能し、フォーク時にのみブロックされます。
自動トリガー: auto-aof-rewrite-min-size パラメーターと auto-aof-rewrite-percentage パラメーター、および aof_current_size と aof_base_size ステータスに基づいてトリガー時間を決定します。
auto-aof-rewrite-min-size は、AOF 書き換えを実行するときのファイルの最小サイズを示します。デフォルト値は 64MB です。
auto-aof-rewrite-percentage表示执行AOF重写时,当前AOF大小(即aof_current_size)和上一次重写时AOF大小(aof_base_size)的比值,即增长比例达到设定值。
只有当auto-aof-rewrite-min-size和auto-aof-rewrite-percentage两个参数同时满足时,才会自动触发AOF重写,即bgrewriteaof操作。
其中,参数可以通过config get命令查看:
127.0.0.1:6391> CONFIG GET auto-aof-rewrite-min-size 1) "auto-aof-rewrite-min-size"2) "64000000"127.0.0.1:6391> CONFIG GET auto-aof-rewrite-percentage 1) "auto-aof-rewrite-percentage"2) "100"
状态可以通过info persistence查看:
127.0.0.1:6379> info persistence# Persistenceaof_enabled:1 aof_rewrite_in_progress:0 aof_rewrite_scheduled:0 aof_last_rewrite_time_sec:0 aof_current_rewrite_time_sec:-1 aof_last_bgrewrite_status:ok aof_last_write_status:ok aof_current_size:40876638 aof_base_size:2217565 aof_pending_rewrite:0 aof_buffer_length:0 aof_rewrite_buffer_length:0 aof_pending_bio_fsync:0 aof_delayed_fsync:0
另外在aof rewrite过程中,是否采取增量”文件同步”策略,由参数aof-rewrite-incremental-fsync控制,默认为”yes”,而且必须为yes。rewrite过程中,每32M数据进行一次文件同步,这样可以减少”aof大文件”写入对磁盘的操作次数。
bgrewriteaof机制,在一个子进程中进行aof的重写,从而不阻塞主进程对其余命令的处理,同时解决了aof文件过大问题。现在问题出现了,同时在执行bgrewriteaof操作和主进程写aof文件的操作,两者都会操作磁盘,而bgrewriteaof往往会涉及大量磁盘操作,这样就会造成主进程在写aof文件的时候出现阻塞的情形,现在no-appendfsync-on-rewrite参数出场了。
如果该参数设置为no,是最安全的方式,不会丢失数据,但是要忍受阻塞的问题。如果设置为yes呢?这就相当于将appendfsync设置为no,这说明并没有执行磁盘操作,只是写入了缓冲区,因此这样并不会造成阻塞(因为没有竞争磁盘),但是如果这个时候Redis挂掉,就会丢失数据。丢失多少数据呢?在Linux的操作系统的默认设置下,最多会丢失30s的数据。因此,如果应用系统无法忍受延迟,而可以容忍少量的数据丢失,则设置为yes。如果应用系统无法忍受数据丢失,则设置为no。
前面提到过,在AOF中,如果AOF缓冲区的文件同步策略为everysec,则:在主线程中,命令写入aof_buf后调用系统write操作,write完成后主线程返回;fsync同步文件操作由专门的文件同步线程每秒调用一次。这种做法的问题在于,如果硬盘负载过高,那么fsync操作可能会超过1s;如果Redis主线程持续高速向aof_buf写入命令,硬盘的负载可能会越来越大,IO资源消耗更快;如果此时Redis进程异常退出,丢失的数据也会越来越多,可能远超过1s。
为此,Redis的处理策略是这样的:主线程每次进行AOF会对比上次fsync成功的时间;如果距上次不到2s(也就是延迟了1s),主线程直接返回;如果超过2s,则主线程阻塞直到上一次fsync同步完成。因此,如果系统硬盘负载过大导致fsync速度太慢,会导致Redis主线程的阻塞;此外,使用everysec配置,AOF最多可能丢失2s的数据,而不是1s。具体看Redis AOF刷新策略分析
AOF追加阻塞问题定位的方法,监控info Persistence中的aof_delayed_fsync,当AOF追加阻塞发生时(即主线程等待fsync而阻塞),该指标累加。另外,AOF阻塞时的Redis日志:Asynchronous AOF fsync is taking too long (disk is busy?). Writing the AOF buffer without waiting for fsync to complete, this may slow down Redis.
如果AOF追加阻塞频繁发生,说明系统的硬盘负载太大;可以考虑更换IO速度更快的硬盘,或者通过IO监控分析工具对系统的IO负载进行分析。
对于pipelining的操作,其具体过程是客户端一次性发送N个命令,然后等待这N个命令的返回结果被一起返回。通过采用pipilining就意味着放弃了对每一个命令的返回值确认。由于在这种情况下,N个命令是在同一个执行过程中执行的。所以当设置appendfsync为everysec时,可能会有一些偏差,因为这N个命令可能执行时间超过1秒甚至2秒。但是可以保证的是,最长时间不会超过这N个命令的执行时间和。
服务器可能在程序正在对AOF文件进行写入时停机,如果停机造成了 AOF 文件出错(corrupt),那么Redis在重启时会拒绝载入这个AOF文件, 从而确保数据的一致性不会被破坏。当发生这种情况时,可以用以下方法来修复出错的 AOF 文件:为现有的AOF文件创建一个备份。然后使用Redis附带的redis-check-aof –fix程序对原来的AOF文件进行修复。
然后可选使用 diff -u 对比修复后的 AOF 文件和原始 AOF 文件的备份,查看两个文件之间的不同之处。再次重启Redis服务器,等待服务器载入修复后的AOF文件,并进行数据恢复。
ただし、AOF ファイルの終わりが不完全な場合 (突然のマシンのダウンタイムにより、ファイルの終わりが不完全になる可能性があります)、aof-load-truncated パラメーターがオンになっている場合、警告が出力されます。ログに記録され、Redis は AOF ファイルの終わりを無視して成功を開始します。 aof-load-truncated パラメータはデフォルトで有効になっています。
RDB は、サイズが小さく、ネットワーク転送が高速な非常にコンパクトなファイルで、特定の時点の Redis データ セットを保存します。この種類のファイルはバックアップに非常に適しており、回復速度は AOF よりもはるかに高速です。もちろん、RDB の最も重要な利点の 1 つは、AOF に比べてパフォーマンスへの影響が比較的小さいことです。 RDB ファイルを保存するときに親プロセスが行う必要があるのは、子プロセスをフォークアウトすることだけであり、その後の保存作業はすべて子プロセスによって処理され、親プロセスはディスク I/O 操作を実行する必要はありません。
RDB ファイルの致命的な欠点は、データ スナップショットの永続化方法によって、リアルタイムで永続化できないと判断されることです。データの重要性がますます高まっている今日、大量のデータが失われます。したがって、AOF 永続化が主流になっています。さらに、RDB ファイルは特定の形式を満たす必要があり、互換性が低くなります (たとえば、古いバージョンの Redis は新しいバージョンの RDB ファイルと互換性がありません)。
RDB の永続化に対応する AOF の利点は、第 2 レベルの永続化をサポートし、互換性が高いことです。 fsync なし、毎秒 fsync、書き込みコマンドが実行されるたびに fsync など、さまざまな fsync ポリシーを設定できます。 AOF のデフォルト ポリシーは fsync 1 秒に 1 回ですが、この構成でも Redis は良好なパフォーマンスを維持でき、障害が発生した場合でも、失われるデータは最大 1 秒のみです。 AOF ファイルは追加操作のみを実行するログ ファイル (追加のみのログ) であるため、何らかの理由 (書き込み、ディスクがいっぱいである、書き込みが中断されているなど) でログに不完全なコマンドが含まれている場合でも、AOF ファイルへの書き込みにはシークは必要ありません。書き込み中に停止した場合など)、redis-check-aof ツールでもこの問題を簡単に解決できます。
Redis は、AOF ファイルのサイズが大きくなりすぎると、バックグラウンドで AOF を自動的に書き換えることができます。書き換えられた新しい AOF ファイルには、現在のデータ セットを復元するために必要な最小限のコマンド セットが含まれています。 Redis は新しい AOF ファイルの作成プロセス中に既存の AOF ファイルにコマンドを追加し続けるため、書き換え操作全体は完全に安全です。書き換えプロセス中にシャットダウンが発生した場合でも、既存の AOF ファイルは失われません。 。新しい AOF ファイルが作成されると、Redis は古い AOF ファイルから新しい AOF ファイルに切り替えて、新しい AOF ファイルへの追加を開始します。 AOF ファイルには、データベース上で実行されたすべての書き込み操作が順序どおりに保存されます。これらの書き込み操作は Redis プロトコルの形式で保存されるため、AOF ファイルの内容は非常に読みやすく、ファイルの分析も簡単です (解析します)。 AOF ファイルのエクスポート (エクスポート) も非常に簡単です。たとえば、誤って FLUSHALL コマンドを実行した場合でも、AOF ファイルが上書きされていなければ、サーバーを停止し、AOF の最後にある FLUSHALL コマンドを削除するだけです。ファイルを削除し、Redis を再起動すると、データセットを FLUSHALL が実行される前の状態に復元できます。
AOF ファイルのサイズは通常、RDB ファイルよりも大きく、回復速度が遅くなります。同じデータ セットの場合、使用される fsync 戦略によっては、AOF が RDB よりも遅くなる場合があります。通常の状況では、1 秒あたりの fsync のパフォーマンスは依然として非常に高く、fsync をオフにすると AOF を RDB と同じ速度にすることができます。また、AOF には過去にも同様のバグがあり、特定のコマンドにより、AOF ファイルをリロードすると、データセットを保存時の状態に戻すことができなくなりました。この種のバグは AOF ファイルでは一般的ではありませんが、それに比べて、RDB でこの種のバグが発生することはほとんどありません。
まず第一に、RDB であっても AOF であっても、永続性を有効にするとパフォーマンスが犠牲になることを理解する必要があります。RDB 永続性の場合、一方では、bgsave が実行するときに Redis のメイン プロセスがブロックされます。 bgsave がフォーク操作を実行すると、Redis のメインプロセスがブロックされ、子プロセスによるハードディスクへのデータの書き込みも IO プレッシャーになります。ただし、ビジネスが数分から 10 分のデータ損失を許容できる (スタンバイ データベースを使用しない) 場合は、RDB が適切な選択であり、そうでない場合は、AOF を選択します。
AOF 永続性の場合、ハードディスクにデータを書き込む頻度が大幅に増加し (毎秒ポリシーの 2 番目のレベル)、IO プレッシャーが大きくなり、AOF 追加ブロッキングの問題が発生する可能性もあります (このブロッキングについては後で説明します)。また、AOF ファイルの書き換えは RDB の bgsave と同様であり、fork 時のブロックや子プロセスの IO プレッシャーの問題が発生します。比較的に、AOF はハードディスクにデータをより頻繁に書き込むため、Redis メイン プロセスのパフォーマンスに大きな影響を与えます。
在实际生产环境中,根据数据量、应用对数据的安全要求、预算限制等不同情况,会有各种各样的持久化策略;如完全不使用任何持久化、使用RDB或AOF的一种,或同时开启RDB和AOF持久化等。此外,持久化的选择必须与Redis的主从策略一起考虑,因为主从复制与持久化同样具有数据备份的功能,而且主机master和从机slave可以独立的选择持久化方案。比如完全关闭master持久化(包括RDB和AOF),这样可以让master的性能达到最好;而slave可以只开启AOF。但这种情况下,如果master服务因为故障宕掉了,如果系统中有自动拉起机制(即检测到服务停止后重启该服务)将master自动重启,由于没有持久化文件,那么master重启后数据是空的,slave同步数据也变成了空的,意味着数据丢失。所以尽量避免这种情况出现。
在版本号大于等于2.4的Redis中,BGSAVE执行的过程中,不可以执行BGREWRITEAOF。反过来说,在BGREWRITEAOF执行的过程中,也不可以执行BGSAVE。这可以防止两个Redis后台进程同时对磁盘进行大量的I/O操作。
如果BGSAVE正在执行,并且用户显示地调用BGREWRITEAOF命令,那么服务器将向用户回复一个OK状态,并告知用户,BGREWRITEAOF已经被预定执行: 一旦BGSAVE执行完毕,BGREWRITEAOF就会正式开始。当Redis启动时,如果RDB持久化和AOF持久化都被打开了,那么程序会优先使用AOF文件来恢复数据集,因为AOF文件所保存的数据通常是最完整的。
这些持久化的数据有什么用,当然是用于重启后的数据恢复。Redis是一个内存数据库,无论是RDB还是AOF,都只是其保证数据恢复的措施。所以Redis在利用RDB或AOF进行恢复的时候,会读取RDB或AOF文件,重新加载到内存中。相对于MySQL等数据库的启动时间来说,会长很多,因为MySQL本来是不需要将数据加载到内存中的。
但是相对来说,MySQL启动后提供服务时,其被访问的热数据也会慢慢加载到内存中,通常我们称之为预热,而在预热完成前,其性能都不会太高。而Redis的好处是一次性将数据加载到内存中,一次性预热。这样只要Redis启动完成,那么其提供服务的速度都是非常快的。
而在利用RDB和利用AOF启动上,其启动时间有一些差别。RDB的启动时间会更短,原因有两个,一是RDB文件中每一条数据只有一条记录,不会像AOF日志那样可能有一条数据的多次操作记录。所以每条数据只需要写一次就行了。另一个原因是RDB文件的存储格式和Redis数据在内存中的编码格式是一致的,不需要再进行数据编码工作。在CPU消耗上要远小于AOF日志的加载。
注意:当redis启动时,如果rdb持久化和aof持久化都打开了,那么程序会优先使用aof方式来恢复数据集,因为aof方式所保存的数据通常是最完整的。如果aof文件丢失了,则启动之后数据库内容为空。
注意:如果想把正在运行的redis数据库,从RDB切换到AOF,建议先使用动态切换方式,再修改配置文件,重启数据库。(不能直接修改配置文件,重启数据库,否则数据库中数据就为空了。) 在Redis 2.2或以上版本,可以在不重启的情况下,从RDB切换到AOF :
为最新的dump.rdb文件创建一个备份,将备份放到一个安全的地方。执行以下两条命令:
127.0.0.1:6379> CONFIG SET dir /apps/redis/data/redis-8836 127.0.0.1:6379> CONFIG SET appendonly yes 127.0.0.1:6379> CONFIG SET save ""
确保命令执行之后,数据库的键的数量没有改变。确保写命令会被正确地追加到 AOF 文件的末尾。
步骤2是开启了AOF功能,Redis会阻塞直到初始AOF文件创建完成为止,之后Redis会继续处理命令请求,并开始将写入命令追加到AOF文件末尾。
步骤3用于关闭RDB功能,这一步是可选的,如果你愿意的话,也可以同时使用RDB和AOF这两种持久化功能。
以上がRedis の RDB および AOF メソッドの使用方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。