【テクニカル・上級編】 AOF (Append Only File) – Redis

AOFの深淵:Redis永続化における「書き込みの美学」と、その代償

Redisはメモリ・ファーストなデータストアである。しかし、我々が真に信頼を置くのは、メモリ上の高速なクエリだけではない。万が一のクラッシュからいかにして「直前まで」の整合性を復元するか――その究極の手段がAOF (Append Only File) だ。

教科書的な説明は省く。今日は、Redisのソースコードとカーネルの挙動の狭間で起きている「戦い」について話そう。

—

1. ログの物理学:fsyncのジレンマ

AOFの核心は、受信したコマンドを単なるテキストとして `append` し続けることにある。だが、ここで最初の壁に突き当たる。カーネルのページキャッシュと物理ディスクの同期だ。

Redisはデフォルトで `appendfsync everysec` を選択する。これがなぜ「賢い」のか、アーキテクチャの観点から解説しよう。

  • `always`: 毎回の書き込みで `fsync` を呼ぶ。安全性は最強だが、ディスクI/OのレイテンシがRedisのメインスレッドを殺す。スループットはディスクの物理性能に支配される。
  • `no`: カーネルのOSバッファに委ねる。高速だが、OSのクラッシュで直近数秒のデータが消えるリスクがある。
  • `everysec`: 1秒おきに別スレッドで `fsync` を実行する。ここが絶妙なバランスだ。

知見: `everysec` を選択すると、`fsync` が実行される直前に、OSのバッファに書き込まれたログが一定量蓄積される。Redisのメインスレッドはディスクの物理的な書き込み待ちから解放され、高いスループットを維持できる。しかし、もしOSがクラッシュすれば、最大1秒間のログが揮発する。これは「データロスの可能性」と「レイテンシ」のトレードオフにおける、工学的な最適解だ。

—

2. AOF Rewrite:肥大化との終わりなき戦い

AOFはコマンドの累積だ。放置すればディスクを食いつぶし、再起動時のリプレイ時間(リカバリコスト)が指数関数的に増大する。そこでRedisは `BGREWRITEAOF` を実行する。

ここで最も重要なのは、「現在のメモリ状態を、最小限のコマンドセットに再構築する」というプロセスだ。

内部メカニズムの真髄

1. Forkのコスト: Redisはプロセスを `fork()` し、子プロセスが現在のメモリ状態をスキャンし、コマンドを生成する。
2. コピーオンライト (COW): `fork()` 直後、メモリは実質的にコピーされないが、書き込みが発生するたびにページ単位で物理コピーが発生する。大規模なインスタンスで `BGREWRITEAOF` を走らせると、メモリ使用率がスパイクするのはこのためだ。
3. AOF再構成中のバッファ: 子プロセスが作業中にメインスレッドに来た新たな書き込みは、「AOF rewrite buffer」に一時保存される。これが完成した瞬間にファイルへフラッシュされ、新しいファイルに切り替わる。

極限の最適化: 大規模環境(100GBクラス)では、この `fork()` 時のメモリコピーでシステムが一時的にフリーズ(latency spike)する可能性がある。これを防ぐには、物理メモリの空き容量を十分に確保し、Transparent Huge Pages (THP) を無効化することが不可欠だ。THPが有効だと、メモリ管理のレイテンシが予期せぬ挙動を引き起こす。

—

3. RDBとAOFのハイブリッド:現代の最適解

Redis 4.0以降、我々は「RDB + AOF」という強力な武器を手に入れた。

`aof-use-rdb-preamble yes` を設定すると、AOFファイルの先頭にRDB形式のバイナリスナップショットを配置し、その後に不足分をAOFログとして追記する。

  • 復元速度: RDB部分を高速にメモリにロードし、残りのわずかなログをリプレイする。
  • 整合性: AOFの強固な永続性と、RDBの高速な再起動性能。

これが現代の大規模Redisクラスタにおける「唯一の正解」だ。

—

4. チーフアーキテクトからの忠告

あなたがもし、ミリ秒以下のレイテンシと、100%のデータ堅牢性を同時に求めているのなら、それはRedisのアーキテクチャに対する誤解だ。

  • ディスクI/Oのボトルネックを監視せよ: `iostat -x` で `await` を見てほしい。`everysec` の `fsync` でさえ、ディスクが悲鳴を上げればメインスレッドに `fsync` の完了待ちが伝搬する。
  • SSDの選定: RedisのAOFはランダムアクセスではなくシーケンシャルな追記だ。だが、高負荷時には `fsync` のオーバーヘッドが顕在化する。IOPSではなく、fsyncのレイテンシが低いNVMe SSDを選ぶべきだ。
  • 再起動時のRDB解析: AOFファイルが巨大化しすぎると、再起動時のロード時間が数十分になる。`auto-aof-rewrite-percentage` を適切に設定し、常にログを「圧縮」し続ける規律が必要だ。

Redisは、メモリという極めて「脆弱」なリソースを使って、いかに「強固」なデータベースを作るかという挑戦の歴史そのものである。AOFはその挑戦の証であり、システムエンジニアとしてのあなたの腕が試される場所でもある。

妥協のないログ設計を。それが、あなたのRedisを伝説にする。

コメント

タイトルとURLをコピーしました