ホームページ > データベース > Redis > Redis の永続化メカニズムの詳細な分析

Redis の永続化メカニズムの詳細な分析

青灯夜游
リリース: 2021-12-29 10:11:46
転載
1801 人が閲覧しました

この記事では、Redis の永続化メカニズム (RDB と AOF) を理解し、RDB と AOF を比較します。お役に立てば幸いです。

Redis の永続化メカニズムの詳細な分析

#Redis の永続化メカニズム

##なぜ永続化するのか If Redis に再度アクセスし、Redis データが空であることが判明すると、キャッシュの侵入が発生します。さらに重要なのは、Redis データが空であるため、クライアントがアクセスしたいキーが存在しないため、大量のリクエストが即座にデータベースにヒットし、キャッシュ雪崩が発生します (少数のキーが侵入し、多数のキーが侵入します)。キーは Avalanche です)。

現時点では、データベースがハングする可能性があります。また、redis がダウンしないという保証はありません。そのため、redis がダウンした場合は、内部のコンテンツを迅速に復元する必要があります。したがって、粘り強さが必要です。永続化はデータを保存するためのものではなく、データを回復するためのものです。 [関連する推奨事項:

Redis ビデオ チュートリアル

]

RDBRDB (Redis Database) は Redis のデフォルトのストレージですRDB 方式はスナップショットによって実装されます。

#スナップショットをトリガーする方法

カスタム構成されたスナップショット ルールに準拠する

save 900 1 # 15 分 (900 秒) 以内に少なくとも 1 つのキーが変更された場合にスナップショットが作成されることを示します。
  • save 300 10 # 5 分 (300 秒) 以内に少なくとも 10 個のキーが変更された場合にスナップショットが作成されることを示します。
  • #save 60 10000 # 1 分以内に少なくとも 10,000 個のキーが変更された場合、N 秒以内のデータ セットが迅速に処理されることを示します

  • 「変更が M 個ある」という条件が満たされた場合、データセットは自動的に 1 回保存されます。

#save または bgsave コマンドを実行します。

save または bgsave コマンドを実行して dump.rdb ファイルを生成します。コマンドが実行されるたびに、すべての Redis メモリが新しい rdb ファイルにスナップショットされ、元の rdb スナップショット ファイルは上書きされます。

save と bgsave の比較:

コマンド

savebgsave同期 #非同期# #いいえ (フォーク関数を実行するために子プロセスが生成されるときにショート ブロッキングが発生します)ComplexityO(n)O (n)利点 追加のメモリを消費しないクライアント コマンドをブロックしない欠点クライアントコマンドをブロックします子プロセスをフォークする必要があり、メモリを消費します

バックグラウンドで bgsave メソッドを使用して rdb ファイルの自動生成を構成します。

flushall コマンドを実行します

flushall
ログイン後にコピー

Redis をクリアする前に、現在の Redis スナップショットを保存します

マスター/スレーブ レプリケーションを実行します操作 (初回)

最初のマスター/スレーブ コピーでは rdb ファイルを生成する必要があり、現在の Redis スナップショットが保存されます

RDB 実行プロセス

Redis の永続化メカニズムの詳細な分析

  • プロセス分析

      1. Redis 親プロセスは、最初に次のことを決定します。 : 現在save実行中かbgsave実行中であるか /bgrewriteaof(aofファイル書き換えコマンド)の子プロセスが実行されている場合は、bgsaveコマンドがそのままリターンします。
      1. 親プロセスはフォーク (オペレーティング システムの関数を呼び出してメイン プロセスをコピーする) 操作を実行して子プロセスを作成します。このプロセス中に、親プロセスははブロックされており、Redis はクライアントからのリクエストやターミナルからのコマンドを実行できません。
      1. #親プロセスがフォークした後、bgsave コマンドは「バックグラウンド保存が開始されました」メッセージを返し、親プロセスをブロックしなくなり、他のコマンドに応答できるようになります。 。
      1. #子プロセスは RDB ファイルを作成し、親プロセスのメモリ スナップショットに基づいて一時スナップショット ファイルを生成し、完了後に元のファイルをアトミックに置き換えます。 (RDB は常に完了しています)
      1. 子プロセスは親プロセスに完了を示すシグナルを送信し、親プロセスは統計を更新します。
      1. #親プロセスが子プロセスをフォークした後も、子プロセスは引き続き動作します。

RDB ファイル構造

Redis の永続化メカニズムの詳細な分析#1. 最初の 5 バイトは「REDIS」文字列として固定されます

    2. 4 バイトの「RDB」バージョン番号 (Redis バージョン番号ではありません) (現在 9) は、埋め込み後は 0009# になります。
  • ##3. キーと値の形式の補助フィールド
  • 4. ストレージ データベース番号
  • ##5. ディクショナリ サイズ
  • ##6. 期限切れのキー
  • 7. 主要なデータはキーと値の形式で保存されます
  • 8. 終了フラグ
  • 9. チェックサムはファイルが破損しているか変更されているかどうかを確認するためのものです
  • RDB のメリットとデメリット

メリット

RDB はバイナリです圧縮ファイルは占有スペースが少なく、送信が簡単です (スレーブに渡す)

#メイン プロセスは子プロセスをフォークするため、Redis のパフォーマンスを最大化できます。メイン プロセスは大きすぎてはいけません。
  • 欠点
  • データの整合性は保証されず、すべてのデータはコピー プロセス中に変更されます。最後のスナップショットは失われます

AOF
AOF (ファイル追加のみ) は、Redis のもう 1 つの永続化方法です。 Redis はデフォルトでは有効になっていません。 AOF 永続性を有効にした後、Redis はデータベースのステータスを記録するという目的を達成するために、データベースに書き込まれたすべてのコマンド (およびそのパラメーター) (RESP) を AOF ファイルに記録します。これらのコマンドを順番に再生すると、元の状態に戻ります。 AOF はプロセスを記録し、RDB は結果のみを考慮します

AOF 永続性の実装

構成 redis.conf

# 可以通过修改redis.conf配置文件中的appendonly参数开启 
appendonly yes

# AOF文件的保存位置和RDB文件的位置相同,都是通过dir参数设置的。 
dir ./

# 默认的文件名是appendonly.aof,可以通过appendfilename参数修改 
appendfilename appendonly.aof
ログイン後にコピー

AOF 原則

AOF ファイルには Redis コマンドが保存されます。コマンドを AOF ファイルに同期するプロセス全体は、次の 3 つの段階に分けることができます:

コマンドの伝播: Redis は、実行されたコマンド、コマンド パラメーター、コマンド パラメーター番号、およびその他の情報を AOF プログラムに送信します。

キャッシュの追加: AOF プログラムは、受信したコマンド データに基づいてコマンドをネットワーク通信プロトコルの形式に変換し、プロトコルの内容をサーバーの AOF キャッシュに追加します。

  • ファイルの書き込みと保存: AOF キャッシュの内容が AOF ファイルの末尾に書き込まれ、設定された AOF 保存条件が満たされると、fsync 関数または fdatasync 関数が実行されます。と呼ばれ、実際に書き込まれた内容をディスクに保存します。

  • コマンドの伝播

  • Redis クライアントがコマンドを実行する必要がある場合、ネットワーク経由で接続します。 , プロトコル テキストを Redis サーバーに送信します。サーバーはクライアントのリクエストを受信すると、プロトコル テキストの内容に基づいて適切なコマンド関数を選択し、各パラメーターを文字列テキストから Redis 文字列オブジェクト (StringObject) に変換します。コマンド関数が正常に実行されると、コマンド パラメータが AOF プログラムに伝播されます。

Redis の永続化メカニズムの詳細な分析キャッシュ追加

コマンドが AOF プログラムに伝達されると、プログラムはコマンドに基づいてコマンドを文字列オブジェクトから元のプロトコル テキストに変換します。とコマンドのパラメータ。プロトコル テキストが生成されると、redis.h/redisServer 構造内の aof_buf の末尾に追加されます。

redisServer 構造体は Redis サーバーのステータスを維持し、aof_buf フィールドには AOF ファイルへの書き込みを待機しているすべてのプロトコル テキスト (RESP) が保存されます

ファイルの書き込みと保存

每当服务器常规任务函数被执行、或者事件处理器被执行时,aof.c/flushAppendOnlyFile 函数都会被调用,这个函数执行以下两个工作:

  • WRITE:根据条件将aof_buf中的缓存写入到AOF文件。

  • SAVE:根据条件调用fsync或 fdatasync函数将AOF文件保存到磁盘中。

AOF保存模式

Redis 目前支持三种 AOF 保存模式,它们分别是:

  • AOF_FSYNC_NO :不保存。

  • AOF_FSYNC_EVERYSEC :每一秒钟保存一次。(默认)

  • AOF_FSYNC_ALWAYS :每执行一个命令保存一次。(不推荐)

AOF_FSYNC_NO

从不fsync,将数据交给操作系统来处理。更快,也更不安全的选择。

SAVE只会在以下任意一种情况中被执行:

  • Redis被关闭

  • AOF功能被关闭

  • 系统的写缓存被刷新(可能是缓存已经被写满,或者定期保存操作被执行)

这三种情况下的SAVE操作都会引起Redis主进程阻塞。

AOF_FSYNC_EVERYSEC

SAVE原则上每隔一秒钟就会执行一次,因为SAVE操作是由后台子线程(fork)调用的, 所以它不会引起服务器主进程阻塞,并且在故障时只会丢失1秒钟的数据。

AOF_FSYNC_ALWAYS

每次执行完一个命令之后,WRITE和SAVE都会被执行。每次有新命令追加到AOF文件时就执行一次fsync,非常慢,也非常安全。

因为SAVE是由Redis主进程执行的,所以在SAVE执行期间,主进程会被阻塞,不能接受命令请求。

AOF保存模式对性能和安全性的影响

三种模式的比较

Redis の永続化メカニズムの詳細な分析

AOF重写

AOF记录数据的变化过程,越来越大,需要重写“瘦身”

Redis可以在AOF体积变得过大时,自动地在后台(Fork子进程)对AOF进行重写。

重写后的新AOF文件包含了恢复当前数据集所需的最小命令集合。

所谓的“重写”其实是一个有歧义的词语,实际上,AOF重写并不需要对原有的AOF文件进行任何写入和读取,它针对的是数据库中键的当前值。

举例说明

set s1 11
set s1 22
set s1 33

lpush list1 1 2 3
lpush list1 4 5 6
ログイン後にコピー

AOF重写后

set s1 33

lpush list1 1 2 3 4 5 6
ログイン後にコピー

Redis不希望AOF重写造成服务器无法处理请求,所以Redis决定将AOF重写程序放到(后台)子进程里执行,

  • 1、子进程进行AOF重写期间,主进程可以继续处理命令请求。

  • 2、子进程带有主进程的数据副本,使用子进程而不是线程,可以在避免锁的情况下,保证数据的安全性。

不过,使用子进程也有一个问题需要解决:因为子进程在进行AOF重写期间,主进程还需要继续处理命令,而新的命令可能对现有的数据进行修改,这会让当前数据库的数据和重写后的AOF文件中的数据不一致。

为了解决这个问题,Redis增加了一个AOF重写缓存,这个缓存在fork出子进程之后开始启用,Redis主进程在接到新的写命令之后,除了会将这个写命令的协议内容追加到现有的AOF文件之外,还会追加到这个缓存中。

重写过程分析

Redis の永続化メカニズムの詳細な分析

Redis在创建新AOF文件的过程中,会继续将命令追加到现有的AOF文件里面,即使重写过程中发生停机,现有的AOF文件也不会丢失。而一旦新AOF文件创建完毕,Redis就会从旧AOF文件切换到新AOF文件,并开始对新AOF文件进行追加操作。

当子进程在执行AOF重写时,主进程需要执行以下三个工作:

  • 处理命令请求。
  • 将写命令追加到现有的AOF文件中。
  • 将写命令追加到AOF重写缓存中

。这样一来可以保证:现有的AOF功能会继续执行,即使在AOF重写期间发生停机,也不会有任何数据丢失。所有对数据库进行修改的命令都会被记录到AOF重写缓存中。

当子进程完成AOF重写之后,它会向父进程发送一个完成信号,父进程在接到完成信号之后,会调用一个信号处理函数,并完成以下工作:

  • 将AOF重写缓存中的内容全部写入到新AOF文件中。
  • 对新的AOF文件进行改名,覆盖原有的AOF文件。

Redis数据库里的+AOF重写过程中的命令------->新的AOF文件---->覆盖老的当步骤1执行完毕之后,现有AOF文件、新AOF文件和数据库三者的状态就完全一致了。

当步骤2执行完毕之后,程序就完成了新旧两个AOF文件的交替。这个信号处理函数执行完毕之后,主进程就可以继续像往常一样接受命令请求了

。在整个AOF后台重写过程中,只有最后的写入缓存和改名操作会造成主进程阻塞,在其他时候,AOF后台重写都不会对主进程造成阻塞,这将AOF重写对性能造成的影响降到了最低。

AOF重写触发方式

  • 1、配置触发
#表示当前aof文件大小超过上一次aof文件大小的百分之多少的时候会进行重写。如果之前没有重写过,以启动时aof文件大小为准
auto-aof-rewrite-percentage 100

#限制允许重写最小aof文件大小,也就是文件大小小于64mb的时候,不需要进行优化
auto-aof-rewrite-min-size 64mb
ログイン後にコピー
  • 2、执行bgrewriteaof命令
127.0.0.1:6379>bgrewriteaof‘
Backgroundappendonlyfilerewritingstarted
ログイン後にコピー

AOF重写总结

Redis の永続化メカニズムの詳細な分析

混合持久化

RDB和AOF各有优缺点,Redis 4.0开始支持rdb和aof的混合持久化。

如果把混合持久化打开,aofrewrite的时候就直接把rdb的内容写到aof文件开头。

RDB的头+AOF的身体---->appendonly.aof

开启混合持久化

aof-use-rdb-preambleyes
ログイン後にコピー

AOF文件的载入与数据还原

如果开启了混合持久化,AOF在重写时,不再是单纯将内存数据转换为RESP命令写入AOF文件,而是将重写这一刻之前的内存做RDB快照处理,并且将RDB快照内容和增量的AOF修改内存数据的命令存在一起,都写入新的AOF文件,新的文件一开始不叫appendonly.aof,等到重写完新的AOF文件才会进行改名,覆盖原有的AOF文件,完成新旧两个AOF文件的替换。

于是在Redis重启的时候,可以先加载RDB的内容,然后再重放增量AOF日志就可以完全替代之前的AOF全量文件重放,因此重启效率大幅得到提升。

  • 1、创建一个不带网络连接的伪客户端(fake client)

因为Redis的命令只能在客户端上下文中执行,而载入AOF文件时所使用的命令直接来源于AOF文件而不是网络连接,所以服务器使用了一个没有网络连接的伪客户端来执行AOF文件保存的写命令,伪客户端执行命令的效果和带网络连接的客户端执行命令的效果完全一样

  • 2、从AOF文件中分析并读取出一条写命令

  • 3、使用伪客户端执行被读出的写命令

  • 4、一直执行步骤2和步骤3,直到AOF文件中的所有写命令都被处理完毕为止

Redis の永続化メカニズムの詳細な分析

Redis数据备份策略

  • 1.写crontab定时调度脚本,每小时都copy一份rdb或aof的备份到一个目录中去,仅仅保留最近48小时的备份

  • 2.每天都保留一份当日的数据备份到一个目录中去,可以保留最近1个月的备份

  • 3.每次copy备份的时候,都把太旧的备份给删了

  • 4.每天晚上将当前机器上的备份复制一份到其他机器上,以防机器损坏

RDB和AOF对比

  • 1、RDB存某个时刻的数据快照,采用二进制压缩存储,AOF存操作命令,采用文本存储(混合)

  • 2、RDB性能高、AOF性能较低

  • 3、RDB在配置触发状态会丢失最后一次快照以后更改的所有数据,AOF设置为每秒保存一次,则最多丢2秒的数据

  • 4、Redis以主服务器模式运行,RDB不会保存过期键值对数据,Redis以从服务器模式运行,RDB会保存过期键值对,当主服务器向从服务器同步时,再清空过期键值对。AOF写入文件时,对过期的key会追加一条del命令,当执行AOF重写时,会忽略过期key和del命令。

更多编程相关知识,请访问:编程视频!!

##IO タイプ
#他の Redis コマンドをブロックするかどうか Yes

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

関連ラベル:
ソース:juejin.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート