【テクニカル・上級編】 redis-check-aofツール – Redis

AOFの死闘:`redis-check-aof` と極限状態からの生還

大規模なインメモリデータストアの運用において、最も冷や汗をかく瞬間は何か。それは、ハードウェアの突然の断絶、OSのパニック、あるいはストレージのI/O枯渇によって、Redisが再起動時にAOF(Append Only File)のロードに失敗し、クラッシュループに陥った瞬間だ。

「`Fatal error loading the AOF file: Invalid file format`」

このログがコンソールに吐き出された時、素人は絶望する。だが、シニアエンジニアやアーキテクトにとって、これは平時のルーティンワークの延長に過ぎない。Redisの内部構造、特にAOFのバイナリフォーマットと書き込みメカニズムを骨の髄まで理解していれば、失われたデータの境界を特定し、システムを強制的に生還させることは容易い。

今回は、AOFの破損という修羅場において唯一の救世主となるツール `redis-check-aof` について、その内部メカニズムと実戦的な極限の知見を解説する。

—

1. なぜAOFは「壊れる」のか:内部メカニズムの闇

表面的な使い方だけを知る者は「RedisのAOFは堅牢だ」と過信する。しかし、ファイルシステムとカーネルの挙動を低レイヤから見れば、AOFが破損するリスクは常にゼロではない。

ページキャッシュとディスクフラッシュの非対称性

Redisが `appendfsync everysec`(あるいは `always`)で動作している時、データは `write(2)` システムコールを通じてカーネルのページキャッシュに書き込まれ、その後に `fsync(2)` によって物理ストレージへと同期される。

しかし、以下のような極限状況では不整合が生じる。
1. 部分的な書き込み(Partial Writes): ディスクのセクタサイズ(通常4KB、Advanced Formatでは4096バイト)の境界を跨ぐ書き込み途中で電源が喪失した場合、ファイル末尾に「中途半端なコマンドバイト列」が残る。
2. ストレージのメタデータ破損: ファイルシステム(ext4やXFSなど)のジャーナル記録と実際のブロック割当の不整合により、ファイル末尾にゴミデータ(ヌルバイトや古いブロックの残骸)がパディングされる。

Redisは起動時、AOFファイルを先頭から順にパースしていく。RESP(REdis Serialization Protocol)の厳密なプロトコルパーサであるため、期待されたマジックバイトや引数の数、区切り文字(`\r\n`)が少しでも崩れていた瞬間にパースエラーを吐き、安全のために起動を中断する。これが破損の正体だ。

—

2. `redis-check-aof` の解剖:何が起きているのか

`redis-check-aof` は、単なる「エラーチェッカー」ではない。実体は、RESPプロトコルの文法チェッカー兼、ファイル終端の外科手術用メスである。

通常、このツールは以下の2つのモードで使用される。

  • 診断モード: ファイルを検証し、破損箇所を特定する。
  • 修復モード(`–fix`): 破損した末尾を切り詰め(Truncate)、整合性が取れる最後のトランザクションまでを救出する。

内部動作のアルゴリズム

1. ファイルの先頭からRESPのパースを開始。
2. アレイの要素数 (`3\r\n`)、バルクストリングの長さ (`$3\r\nSET\r\n`) を厳密に検証。
3. 途中でEOF(ファイルの終端)に達するか、不正なバイトシーケンスを検知した時点でスキャンを停止。
4. `–fix` フラグが有効な場合、「正常にパースできた最後のバイト位置」にファイルのEOFを強制的に移動(truncate)させる。

つまり、`redis-check-aof –fix` とは、「破損した末尾のデータを潔く切り捨てる」という極めて破壊的な、しかし唯一の生存戦略なのだ。

—

3. 実戦:修羅場での `redis-check-aof` 運用手順

理論はここまでだ。ここからは、本番環境で実際にAOFが破損した際の、秒単位を争うリカバリ手順を記述する。

Step 1: 現状の保全(絶対の鉄則)

修復作業を行う前に、必ず破損したAOFファイルのバックアップを取れ。`–fix` はファイルを直接書き換える(destructive)ため、失敗した際のセーフティネットが不可欠である。

作業ディレクトリへ移動
cd /var/lib/redis

破損したAOFを即座に退避(容量が大きい場合はcpではなくハードリンクやスナップショット推奨)
cp appendonly.aof appendonly.aof.corrupted

Step 2: 診断の実行

まずは、どの程度ファイルが破損しているのかを `redis-check-aof` で診断する。

redis-check-aof appendonly.aof

実行結果の例:

0ings read, 1245000 valid entries, 1 invalid entries.
AOF File is not valid. At byte 89452311, line 1502392:
Expected \r\n, got: “X”

知見: この出力から、ファイルサイズのうち約89MB地点でプロトコル違反(期待された `\r\n` の位置に `”X”` がある)が発生していることが一目でわかる。

Step 3: 限界突破の修復(`–fix`)

いよいよ修復を実行する。

redis-check-aof –fix appendonly.aof

実行すると、以下のような対話的(または自動)プロンプトが表示される。

The AOF file appears to be corrupted, or the last command was truncated.
Would you like to truncate the AOF file at byte 89452311? [y/N]: y
Successfully truncated AOF

ここで `y` を選択すると、バイト位置 `89452311` 以降のゴミデータが切り落とされる。

Step 4: 差分の確認(diffの活用)

プロフェッショナルなエンジニアは、ツールを盲信しない。何バイトが切り捨てられたのか、エンジニアリングの観点から正確に把握すべきだ。

修復前後のファイルサイズを比較
ls -l appendonly.aof

-rw-r—– 1 redis redis 91234500 May 20 10:00 appendonly.aof
-rw-r—– 1 redis redis 89452311 May 20 09:59 appendonly.aof.corrupted

差分(約1.7MB分、最後の数秒間のトランザクション)が切り捨てられたことが確認できる。この切り捨てられたデータは「失われたデータ」だが、Redisインスタンス全体が起動不能になるリスクに比べれば、軽微な犠牲である。

—

4. アーキテクトからの提言:AOF破損を防ぐために

`redis-check-aof` は最後の砦だが、このツールに頼る頻度が高いアーキテクチャは「欠陥がある」と言わざるを得ない。本番環境の設計において、AOFの破損リスクを極限まで低減するための知見を授ける。

1. ストレージの選定とバリアフラッシュ:
AWS EBS (gp3/io2) やローカルNVMeを使用する場合、ファイルシステムのマウントオプションに注意せよ。`noatime` は当然として、ストレージコントローラ側でのライトバックキャッシュの挙動、およびバッテリバックアップ付きライトキャッシュ(BBU)の有無が、突然の電源断における部分書き込みの発生率を左右する。
2. `aof-use-rdb-preamble` の活用 (Redis 5+):
現代のRedisでは、AOFとRDBのハイブリッド永続化(`aof-use-rdb-preamble yes`)を強く推奨する。AOFの前半部分がRDBフォーマットでスナップショットとして保存されるため、仮にAOF後半の追記ログ部分が破損したとしても、失われるデータ量を最小限(直近の書き込みのみ)に抑えられ、かつリカバリ時のロード速度が劇的に向上する。
3. モニタリングの徹底:
Redisのログ監視において、「`Reading from AOF`」「`Error loading AOF`」のキーワードは即座にPagerDutyやOpsgenie等のアラートを鳴らすようルーティングしておけ。人間の手動介入を待つのではなく、自動化されたフェイルオーバーやスタンバイからの昇格パスを用意することが、真の高可用性(HA)システムである。

結び

`redis-check-aof` は、冷徹なまでの現実主義で作られたツールだ。「失われたものは戻らない。だが、残されたデータでシステムを継続させる」。これがこのユーティリティの哲学である。

低レイヤのバイナリ構造を理解し、パニックにならずに正確なバイト位置を切り詰める――このスキルこそが、ジュニアと、修羅場をくぐり抜けてきた本物のアーキテクトを分かつ境界線なのである。

コメント

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