【実務・中級編】 AOFリライト時のfsync設定 – Redis

Redisの死地を避ける:AOFリライトとfsyncの「黄金律」

Redisを単なる「高速なKVS」と捉えているなら、それはまだ入り口に過ぎない。大規模トラフィックを捌く現場において、Redisの真価は「いかにクラッシュさせず、かつレイテンシのスパイクを許さないか」という極限のトレードオフを制御するエンジニアリングにある。

今回は、多くのエンジニアが「デフォルト設定」で放置し、後にシステムを瀕死に追い込むAOFリライト時のfsync戦略について、アーキテクトの視点から深掘りする。

—

1. なぜ「AOFリライト」は悪魔になり得るのか

AOF(Append Only File)は、すべての書き込み操作をログとして記録する。しかし、時間が経てばログは肥大化し、再起動時のロード時間が地獄と化す。これを解消するためにRedisは「リライト(BGREWRITEAOF)」を行い、現在のデータセットから最小限のコマンド群を再構築する。

問題は、このリライトがバックグラウンドで行われている最中、親プロセスと子プロセスの双方がI/Oを激しく奪い合う点にある。

特に`no-appendfsync-on-rewrite`の設定を誤ると、リライト中のI/O負荷がディスクI/Oのボトルネックを突き抜け、Redis全体のレスポンスを数秒間フリーズさせる「Stop-the-world」を引き起こすことになる。

2. 極限設定:`no-appendfsync-on-rewrite` の真実

Redisの設定ファイルにあるこのパラメータは、一見すると些細なものに見えるが、システムの生存戦略を左右する。

デフォルトは no
これを yes にすると、AOFリライト中は fsync をスキップする
no-appendfsync-on-rewrite yes

なぜ `yes` にすべきなのか?

現代のNVMe SSDであっても、高負荷時のfsyncはレイテンシのスパイクを生む。`no-appendfsync-on-rewrite yes` を設定すると、リライト中、メインスレッド側のfsyncが一時停止される。

  • メリット: リライトによるI/O負荷と、通常書き込みのfsyncが競合しないため、レイテンシのスパイクが劇的に抑制される。
  • リスク: リライト中にOSがクラッシュした場合、最大で30秒分の書き込みデータが消失する可能性がある。

アーキテクトの助言:
「データ消失を許容できない」という声が飛んできそうだが、高可用性を重視するなら、Redis単体のfsyncに頼るべきではない。Replicaによる冗長化が前提であれば、書き込みの堅牢性はRedisのfsyncではなく、クラスタの構成で担保すべきだ。

3. 実務で「詰む」ポイント:ディスクI/Oの平滑化

単に設定を切り替えるだけでは不十分だ。ディスクI/Oのスパイクを完全に抑え込むには、以下の設計パターンを意識してほしい。

① `aof-rewrite-incremental-fsync` の活用

リライト中、Redisは書き出したAOFデータを一定量(デフォルト32MB)ごとにfsyncする。これにより、一度に巨大なデータがカーネルのページキャッシュに流れ込み、後に発生する「fsyncの嵐(大規模なI/Oブロッキング)」を避けることができる。

32MBごとにfsyncすることで、I/Oを小分けにして平滑化する
aof-rewrite-incremental-fsync yes

② ディスクの物理分離

Redisのデータディレクトリと、ログや他のプロセスが使用するディスクは、物理的あるいは論理的に分離せよ。特にクラウド環境では、ディスクI/Oの上限(IOPS/スループット)が設定されている。リライトがスループット制限を食いつぶすと、アプリケーションの読み書きすべてが停滞する。

4. 設計レビューのためのチェックリスト

君たちが現場でRedisを設計する際、以下の項目をクリアしているか自問してほしい。

  • [ ] fsyncの頻度は適切か?: `appendfsync everysec` が標準だが、なぜそれを選んだのか説明できるか?(`always` は論外である)
  • [ ] リライト中のI/O負荷を考慮したか?: `no-appendfsync-on-rewrite yes` にした場合の「最大30秒のデータ欠損」というリスクを、ビジネス要件として許容したか?
  • [ ] 書き込み負荷は平滑化されているか?: 急激なアクセス増でリライトが頻発しないよう、`auto-aof-rewrite-percentage`(通常100%)を適切に調整したか?
  • [ ] 監視は万全か?: `aof_delayed_fsync` メトリクスを監視し、fsyncがボトルネックになっていないか可視化しているか?

終わりに:アーキテクトからのメッセージ

Redisは魔法の箱ではない。メモリという高速な領域と、ディスクという低速な領域を仲介する、非常に繊細な実装の塊だ。

設定値を「なんとなく」で決めるのではなく、その設定が「どのリソースを犠牲にして、何を優先しているのか」を数式のように理解してほしい。 高いパフォーマンスは、こうした地味なI/Oの平滑化と、リスクのトレードオフを言語化できるエンジニアの頭の中にしか存在しない。

次は、Redisのメモリデフラグ(Active Defrag)の挙動について、同じレベルで掘り下げていくとしよう。健闘を祈る。

コメント

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