Redisのデータ永続化入門：AOF方式とRDB方式

[![表紙](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/f8a23ab7-c8ab-4a8d-9e47-c646932ecf12.png)](https://leapcell.io/?lc_t=q_redispersistence)

## AOF 永続化

Redis はメモリベースのシステムであり、Redis サーバーがクラッシュするとデータは失われてしまいます。データ損失を回避するために、Redis は 2 種類の永続化方式、RDB と AOF を提供しています。まずは AOF について説明します。

AOF（Append Only File）永続化は、各書き込み操作をログとして記録し、AOF ファイルの末尾に追加していく方式です。Redis ではデフォルトで AOF は無効になっています。再起動時には AOF ファイルに記録されたコマンドを再実行することでデータを復元します。これは主にデータ永続化のリアルタイム性を向上させるための仕組みです。

AOF では、コマンドの実行後にログが記録されます。では、なぜコマンドの実行前にログを記録しないのでしょうか？それは、Redis が AOF にログを記録する際、コマンドの文法チェックを行わないためです。もしログを先に記録してからコマンドを実行する方式にすると、ログに誤ったコマンドが記録される可能性があり、その結果、Redis がログからデータを復元する際にエラーが発生する可能性があります。

コマンドの実行後にログを記録することで、現在の書き込み操作をブロックしないというメリットがありますが、以下の 2 つのリスクが存在します：

- コマンドの実行後にログがまだ記録されていないタイミングでクラッシュが発生すると、データが失われる
- AOF は現在のコマンドをブロックしませんが、次の操作をブロックする可能性がある

この 2 つのリスクに対応する最良の方法は、AOF の書き戻し戦略である appendfsync を適切に選択・活用することです。以下の 3 種類の戦略があります：

- `always`：同期書き込み。各コマンド実行後すぐにログをディスクに書き込む
- `everysec`：各コマンド実行後、まず AOF のメモリバッファにログを書き込み、1 秒ごとにディスクに同期
- `no`：まずログをメモリバッファに書き込み、ディスクへの書き込みタイミングは OS に任せる

`always` のような同期書き込みは、データ損失をほぼ回避できますが、`no` 戦略は性能が高い反面、データが失われる可能性があります。一般的には `everysec` をバランスの取れた選択肢として使うことができます。

受信するコマンドが増えれば増えるほど、AOF ファイルもどんどん大きくなり、最終的にはパフォーマンスの問題を引き起こします。ログファイルが大きくなった場合はどうするか？AOF のリライト（再書き込み）機能を使います。時間の経過とともに、AOF ファイルには無効なコマンドや期限切れのデータなど冗長なコマンドが蓄積されます。AOF リライトでは、それらをまとめて一つのコマンドに圧縮し、ファイルサイズを削減します。

AOF リライトはブロッキング（処理の停止）を引き起こすのか？AOF ログの書き込みはメインスレッドが行いますが、リライト処理は異なり、バックグラウンドの子プロセス（`bgrewriteaof`）によって実行されます。

- AOF の利点：データの一貫性と完全性が高く、データ損失は秒単位に抑えられる
- 欠点：同じデータセットの場合、AOF ファイルは RDB ファイルよりもサイズが大きくなる。また、データの復元にも時間がかかる

## RDB 永続化

AOF 永続化方式では、操作ログが非常に多い場合、Redis の復元に時間がかかってしまいます。クラッシュ時に高速で復元する方法はないのでしょうか？あります、それが RDB です！

RDB とは、メモリ上のデータをスナップショット（Snapshot）の形式でディスクに保存する方式です。AOF と比べて、操作ログではなく、ある時点のデータ全体を記録します。

> スナップショットとは？簡単に言えば、現在の時点のデータに対して写真を撮るようなもので、それを保存するイメージです。

RDB 永続化とは、指定された時間間隔内に、指定回数の書き込み操作が発生した場合に、メモリ内のデータセットをスナップショットとしてディスクに書き込むことを意味します。これは Redis のデフォルトの永続化方式です。操作完了後、指定されたディレクトリに `dump.rdb` ファイルが生成され、Redis の再起動時にはこのファイルを読み込むことでデータを復元します。RDB のトリガー方式には以下の種類があります：

- `save`：手動トリガー、同期保存。現在の Redis サーバーをブロックする
- `bgsave`：手動トリガー、非同期保存。Redis プロセスが `fork` を実行して子プロセスを生成
- `save m n`：自動トリガー。_m_ 秒間に _n_ 回のデータ変更があった場合、自動的に `bgsave` を実行

RDB は `bgsave` コマンドを使ったフルスナップショットを通して、メインスレッドのブロックを避けることができます。`bgsave` コマンドは子プロセスを `fork` して生成し、その子プロセスが RDB ファイルの作成を担当し、一方のサーバープロセスは引き続きコマンドリクエストを処理します。

スナップショット中にデータは更新できるのか？Redis は OS のコピーオンライト（Copy-On-Write、COW）技術を利用して、スナップショットを実行しながらでも書き込み操作を通常通り処理できます。

`bgsave` の実行自体はメインスレッドをブロックしませんが、頻繁なフルスナップショットの実行はパフォーマンスの負担になります。たとえば、`bgsave` の子プロセスは `fork` によってメインスレッドから生成されますが、生成の瞬間はメインスレッドをブロックします。このような問題には、差分（インクリメンタル）スナップショットを導入することで対応可能です。

- RDB の利点：AOF に比べて、大規模なデータセットをより高速に復元できるため、バックアップやフルレプリケーションなど大規模なデータ復元シナリオに適している
- 欠点：リアルタイムまたは秒単位の永続化には対応できない

Redis 4.0 以降は、RDB と AOF のハイブリッド永続化をサポートしています。これは、一定間隔でメモリスナップショットを実行し、2 回のスナップショットの間の操作コマンドは AOF に記録するという方式です。

## RDB と AOF の選び方

- データを絶対に失いたくない場合は、RDB と AOF を併用する
- キャッシュとしてのみ使用し、数分間のデータ損失を許容できる場合は、RDB のみを使用してもよい
- AOF のみを使用する場合は、書き戻し戦略として `everysec` を優先的に使用する

---

### [私たちはLeapcell、バックエンド・プロジェクトのホスティングの最適解です。](https://leapcell.io/?lc_t=q_redispersistence)

[![Leapcell](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/af9747f9-3708-496c-8f61-2c0484475149.png)](https://leapcell.io/?lc_t=q_redispersistence)

[Leapcell](https://leapcell.io/?lc_t=q_redispersistence)は、Webホスティング、非同期タスク、Redis向けの次世代サーバーレスプラットフォームです：

**複数言語サポート**

- Node.js、Python、Go、Rustで開発できます。

**無制限のプロジェクトデプロイ**

- 使用量に応じて料金を支払い、リクエストがなければ料金は発生しません。

**比類のないコスト効率**

- 使用量に応じた支払い、アイドル時間は課金されません。
- 例: $25で6.94Mリクエスト、平均応答時間60ms。

**洗練された開発者体験**

- 直感的なUIで簡単に設定できます。
- 完全自動化されたCI/CDパイプラインとGitOps統合。
- 実行可能なインサイトのためのリアルタイムのメトリクスとログ。

**簡単なスケーラビリティと高パフォーマンス**

- 高い同時実行性を容易に処理するためのオートスケーリング。
- ゼロ運用オーバーヘッド — 構築に集中できます。

[ドキュメントで詳細を確認！](https://docs.leapcell.io/)

[![Try Leapcell](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/4dcd35e3-f430-4fa1-8195-d8fd661613a1.png)](https://leapcell.io/?lc_t=q_redispersistence)

Xでフォローする：[@LeapcellHQ](https://x.com/LeapcellHQ)

---

[ブログでこの記事を読む](https://leapcell.io/blog/in-depth-guide-to-redis-persistence-mechanisms)