【入門編】 AOF書き換え時のメモリ影響 – Redis

こんにちは!Redisの仕組みをもっと深く知りたい君へ。

今回は、Redisの運用において避けて通れない、だが一歩間違えるとシステム全体をクラッシュさせる魔物……「AOF書き換え時のメモリ影響」について解説するよ。

「難しそうだな……」なんて身構えなくて大丈夫。ここをクリアすれば、君はもうRedisのメモリ管理の仕組みを語れる立派なエンジニアだ。温かく導くから、一緒にリラックスして紐解いていこう。

—

1. まずは基本:AOFってなに?(日常の例え)

Redisは、すべてのデータをメモリ上に置いて超高速に処理するデータベースだ。でも、メモリの弱点は「電源を落としたらすべて消える」こと。

そこで登場するのが AOF(Append Only File)。
これは、Redisが行った操作(「キーAに値Bをセットしたよ」「キーCを消したよ」という命令)を、まるで料理のレシピ本のようにノートに一文字ずつリアルタイムで書き留めていく仕組みなんだ。

もしサーバーが急にプツンと切れても、このノート(AOFファイル)の最初から順番に操作をやり直せば、データが完全に復活する。これがAOFの正体だよ。

—

2. AOFファイルの「太りすぎ」問題と、お掃除大作戦(BGREWRITEAOF)

さて、このノートだけど、運用していると大変な問題が起きる。
例えば、「キーAに『1』を代入」「やっぱり『2』に変更」「さらに『3』に変更」という操作を100回繰り返すと、ノートには100行の履歴が残るよね。

でも、最終的に必要なデータは「キーAは『3』である」という最後の1行だけのはず。
それなのに、ノートがどんどん分厚くなって、読むのにもディスク容量を圧迫するのにも困ってしまう。

そこでRedisには、「ノートの文字をスッキリまとめ直して、究極にスリムな最新版のノートに作り替える」機能がある。これが `BGREWRITEAOF`(Background AOF Rewrite) だ。

「Background(バックグラウンド)」と付いている通り、Redisが普段の仕事をサボらずに裏側(別の子プロセス)でこっそりお掃除をしてくれる、とても便利な機能なんだよ。

—

3. ここが罠!「コピー・オン・ライト(CoW)」とメモリ急増のメカニズム

「お、裏側で勝手に掃除してくれるなら安心だな!」と思った君、実はここに最大の落とし穴があるんだ。

Redisが裏でお掃除(子プロセスを作成)を始めるとき、OSの「Copy-on-Write(コピー・オン・ライト)」という仕組みが使われる。これが今回のテーマの核心だ。

例え話:オフィスのコピー機と付箋

  • 親プロセス(メインのRedisさん): 今まさにバリバリ仕事をしていて、巨大なホワイトボード(メモリ)にたくさんのデータを書いている。
  • 子プロセス(お掃除係の君): 「今のホワイトボードの写真を撮って、きれいにまとめるぞ」と派遣されてきた。

普通なら、ホワイトボードの全体像をもう一回丸ごとコピーするには、同じだけの広いスペース(余分なメモリ)が必要になるよね。そんなことをしたら、メモリがパンクしてしまう。

そこで「コピー・オン・ライト」の出番だ。
子プロセスは、ホワイトボードを丸ごとコピーする代わりに、「今のホワイトボードの『目次(参照先)』だけ」をこっそり持ってスタートする。最初はメモリをほとんど消費しない。

しかし、お掃除をしている最中にも、メインのRedisさん(親プロセス)には次々とユーザーからの新しいリクエスト(データの書き換え)が飛んでくる。

「あ、そこ書き換えちゃダメ!」
親プロセスが既存のデータを書き換えようとした瞬間、OSがこう言うんだ。
「ちょっと待って! そのデータ、今お掃除係(子プロセス)が古い状態のを見ているから、書き換える前に別な場所にコピーして!」

これが Copy-on-Write(書き込み時のコピー)。
結果として、書き換えが頻発すればするほど、裏でこっそりメモリの消費量が跳ね上がっていくことになる。

—

4. システム全体への影響と、実務で絶対に守るべき鉄則

もし、このメモリの跳ね上がりを計算に入れないでシステムを運用していると、どうなるか?

最悪の場合、サーバー全体のメモリが限界を超え、OSの「OOM Killer(Out of Memory Killer)」という強制終了プログラムが発動する。「メモリを食べすぎたこいつは危険だ!」と判断され、動いているRedisのプロセス自体が強制シャットダウンさせられてしまうんだ。

本番環境でこれが起きたら……想像しただけでも冷や汗ものだよね。

チーフアーキテクトからの実践アドバイス

このリスクを避けるために、現場では以下の鉄則を守っている。

1. メモリに「余白(ヘッドルーム)」を持たせる
Redisに割り当てる最大メモリ(`maxmemory`)は、物理メモリの半分〜せいぜい60〜70%程度にしておくこと。AOFの書き換えや、後述するスナップショット作成(RDB保存)の際に一時的に増える分の「逃げ道」を必ず空けておくんだ。

2. `vm.overcommit_memory` の設定を確認する
Linuxカーネルの設定で、メモリがカツカツのときに安全に動作するための設定(通常は `1` に推奨されることが多い)を正しく行い、OSレベルでの突然死を防ぐ。

3. 書き換えのタイミングをコントロールする
アクセスが爆発的に多いピークタイムを避け、負荷が落ち着いている夜間に自動書き換えが行われるように設定をチューニングする。

—

まとめ

  • AOF はデータの操作履歴を記録するノート。
  • `BGREWRITEAOF` はそのノートをスリムにお掃除する機能。
  • 裏側では Copy-on-Write が働いているため、データの書き換えが多いと、一時的にメモリ使用量が倍増するリスクがある。
  • だからこそ、メモリには常に余裕を持たせた設計がプロの条件。

ここをクリアできれば、君はもう「メモリがあふれたどうしよう!」とパニックになるジュニアエンジニアではなく、裏側のメカニズムまで見通してシステムを守れる優秀なエンジニアだ。

Redisの奥深い世界、これからも一緒に楽しくマスターしていこう!質問があったらいつでも声をかけてくれよな。

コメント

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