【実務・中級編】 rdbcompression設定 – Redis

【Redis設計レビュー】`rdbcompression`の罠:CPUとI/Oの極限トレードオフを制するアーキテクチャ

テックリードの私だ。今日のコードレビュー、あるいはインフラ設計レビューで、また見かけたぞ。
`redis.conf` のデフォルト値をそのまま本番環境に投入し、「なぜか高負荷時にレイテンシが跳ね上がる」「フォロワーのレプリケーションが頻繁にタイムアウトする」と頭を抱えているエンジニアの姿を。

ターゲットは一つ、`rdbcompression` 設定だ。

「LZFアルゴリズムで文字列を圧縮するんでしょ? ディスク容量が浮くから `yes` のままでいいじゃん」――そんな浅い理解で設計しているなら、今すぐそのキーボードを置いてこの記事を読んでくれ。

今回は、Redisの永続化メカニズムの裏側にある「CPUとディスクの残酷なトレードオフ」を解剖し、実務の現場でどう判断すべきかをロジカルに叩き込む。

—

1. そもそも `rdbcompression` とは何か?

`rdbcompression` は、RDB(Redis Database)スナップショット(`BGSAVE`)をディスクに書き出す際、文字列型の値(String values)に対して LZF アルゴリズムによる圧縮を適用するかどうかを制御するフラグだ。

  • `yes` (デフォルト): 圧縮する。ディスク容量を削減できるが、親プロセスからforkした子プロセスがCPUサイクルを消費する。
  • `no`: 圧縮しない。CPU負荷は劇的に下がるが、RDBファイルのサイズが肥大化し、ディスクI/Oおよびネットワーク帯域を圧迫する。

一見すると「ディスクは安いんだから、CPUをケチって `no` にすればいいのでは?」あるいは「ストレージを節約したいから `yes` だ」と思いがちだが、Redisのアーキテクチャの本質は 「シングルスレッドとforkの呪縛」 にある。ここに踏み込んでいない設計はすべてモグラ叩きに終わる。

—

2. アーキテクチャの深層:裏で何が起きているか?

Redisが `BGSAVE` を実行するとき、OSの `fork()` システムコールが走り、メモリのCopy-on-Write(CoW)機構を利用して子プロセスが生成される。この子プロセスが黙々とメモリ上のデータをシリアライズし、ディスクに吐き出す。

ここで `rdbcompression yes` が有効な場合、子プロセスは以下の子細な処理を行う:

1. メモリ上のオブジェクトをスキャン。
2. それが文字列型であり、かつ一定の長さを満たしている場合、LZFアルゴリズムで圧縮を試みる。
3. 圧縮後のストリームをファイルに書き込む。

ここに潜む「2つの致命傷」

1. CPUの無駄骨(CPU Bottleneck)
LZFは高速な圧縮アルゴリズムだが、数GBから数十GBに及ぶRedisのメモリ空間全体に対してこれを実行すると、子プロセスは数コアのCPUを完全に飽和させる。もしRedisサーバーがCPUバウンドな処理(Luaスクリプトの多用など)や、他のミドルウェアと同居している場合、リソースコンテンションを引き起こす。
2. レプリケーション(Full Resync)への波及効果
RDBファイルは、単にディスクバックアップのためだけに存在するのではない。Replicationの初期同期(Full Resync) でもこのRDBファイルがそのままマスターからスレーブへ転送される。
つまり、RDBがデカければ(`rdbcompression no`)、ネットワーク帯域を食い潰し、スレーブ側のロード時間も伸びる。逆に圧縮すれば(`yes`)、マスターのCPUがさらに喘ぐことになる。

—

3. 実務での判断基準:ケーススタディ

では、我々アーキテクトはどのようにこの設定値を決定すべきか。以下のマトリクスを頭に叩き込んでおいてほしい。

パターンA:`rdbcompression yes` を維持すべきシステム

  • 対象: キャッシュではなく、永続的なデータストアとしてRedisを使っている(例:数千万件のセッションデータ、JSON文字列のキャッシュ)。
  • 特徴: 文字列の平均サイズが大きく(1KB〜数10KB)、かつテキストデータ(JSON, HTMLなど)が中心。LZFの圧縮率が非常に高く効く(50%以上の削減が狙える)。
  • インフラ環境: CPUに余裕があり、ストレージI/O(特にクラウドのIOPS課金など)のコストをシビアに抑えたい場合。

パターンB:`rdbcompression no` にブチ伏せるべきシステム

  • 対象: 超高スループット・低レイテンシが求められるキャッシュ層。データ構造の多くが Hash, ZSet など、文字列の直接圧縮の恩恵を受けにくい場合。
  • 特徴: すでにバイナリデータ(画像データや暗号化されたトークンなど)を格納しており、LZFを通してもほとんど圧縮できない(エントロピーが高いデータ)。
  • インフラ環境: NVMeなどの高速なローカルSSDを使用しており、ディスク容量よりもCPUのアイドル時間と `BGSAVE` の完了速度(forkの生存期間短縮)を最優先したい場合。

—

4. 検証:設定による挙動の違いを見極める

百聞は一見にしかず。手元の検証環境で、100万件のランダムな文字列(JSON風データ)を投入したRedisに対し、それぞれの挙動を計測してみよう。

設定ファイルの該当箇所
redis.conf
rdbcompression yes # または no

もしあなたがパフォーマンスチューニングを行うなら、`INFO persistence` のメトリクスを監視ツール(Prometheus + Grafanaなど)で常に注視すべきだ。

redis-cliでの確認例
127.0.0.1:6379> INFO persistence
Persistence
rdb_changes_since_last_save:1240
rdb_bgsave_in_progress:0
rdb_last_bgsave_time_sec:2 # ← BGSAVEにかかった時間(ここが重要)
rdb_last_bgsave_status:ok

`rdb_last_bgsave_time_sec` が急激に伸びている場合、メモリの肥大化とCPU圧縮処理がボトルネックになっているサインだ。

—

5. テックリードからの提言:設計チェックリスト

今後のプロジェクト設計レビューにおいては、以下の基準をクリアしているものだけマージを許可する。

1. データの性質を計測したか?
格納するString値の平均サイズとエントロピー(圧縮効率)を事前に測定したか?(ランダムなハッシュ値やバイナリに `rdbcompression yes` を使うのは、ただのCPUの無駄撃ちだ)
2. インフラのボトルネックはどこか?
CPUコア数に余裕があるならデフォルトの `yes` で安全にディスクを守れ。しかし、CPUが常に70%以上で、かつストレージ帯域に余裕があるなら、`no` への変更をベンチマークを取った上で検討しろ。
3. AOF(Append Only File)との兼ね考慮は済んでいるか?
もし `appendonly yes` を有効にしており、実質的な永続化をAOFに依存している場合、RDBの生成頻度や役割は変わってくる。システムの全体アーキテクチャから逆算して設定しているか?

—

結び

たった1行の `rdbcompression` 設定だが、ここにはRedisというプロダクトの思想――「限界までリソースを絞り出し、ミリ秒単位のレイテンシを死守する」――が凝縮されている。

「なんとなくデフォルト」を卒業し、システムの特性に合わせたリソース配分をデザインすること。それこそが、我々エンジニアがプロフェッショナルである証だ。

次回のレビューでは、根拠のある設定値と言語化されたトレードオフの解説を期待している。健闘を祈る。

コメント

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