mybook

第2章 — エビクション: 何を捨てるか

キャッシュは有限

「キャッシュのメモリは無限じゃない。満杯になったら、何かを捨てて新しいデータを入れる必要がある。この『何を捨てるか』を決めるのがエビクションアルゴリズムだ」

ケンジはそう切り出した。

主要なエビクションアルゴリズム

LRU(Least Recently Used)

最も長い間使われていないデータを捨てる。最も広く使われるアルゴリズム。

Loading diagram...
メリットデメリット
実装がシンプル(連結リスト+ハッシュマップ)スキャン耐性がない
多くのワークロードで良好頻度を考慮しない
O(1) の読み書き一度だけ大量アクセスされたデータに弱い

LFU(Least Frequently Used)

最もアクセス回数が少ないデータを捨てる。

メリットデメリット
人気データを長く保持過去の人気が永続する(キャッシュ汚染)
スキャン耐性がある実装が複雑(ヒープが必要)
安定したヒット率新しいデータが定着しにくい

FIFO(First In, First Out)

最も古く追加されたデータを捨てる。単純なキュー。

TTL(Time To Live)

一定時間経過後に自動で期限切れにする。他のアルゴリズムと組み合わせて使う。

# Redis での TTL 設定
Rails.cache.write("product:123", product, expires_in: 1.hour)

ARC(Adaptive Replacement Cache)

LRU と LFU を動的に組み合わせる先進的アルゴリズム。ワークロードの変化に自動適応する。

Loading diagram...

INFO

ARC は IBM が開発し、ZFS ファイルシステムで有名。退去されたデータの「ゴースト履歴」を追跡し、LRU と LFU のバランスを動的に調整する。

アルゴリズム比較

Loading chart...

Redis のエビクションポリシー

Redis は8種類のエビクションポリシーを提供する。

ポリシー対象動作
noevictionメモリ上限でエラー
allkeys-lru全キーLRU で退去
volatile-lruTTL 付きキーLRU で退去
allkeys-lfu全キーLFU で退去
volatile-lfuTTL 付きキーLFU で退去
allkeys-random全キーランダム退去
volatile-randomTTL 付きキーランダム退去
volatile-ttlTTL 付きキーTTL が短い順
# redis.conf
maxmemory 256mb
maxmemory-policy allkeys-lru

WARNING

Redis の LRU は厳密な LRU ではなく「近似 LRU」。サンプリングベースで、maxmemory-samples パラメータでサンプル数を調整できる(デフォルト5、増やすと精度向上・CPU増加)。

選び方ガイド

Loading diagram...

マナミの選択

FreshMarket では人気商品が固定的で、セール時に一時的なアクセス急増がある。

マナミは Redis の allkeys-lfu を選んだ。人気商品を長く保持しつつ、セール終了後の一時的データは自然に退去される。さらに TTL を1時間に設定し、データの鮮度も保証した。

次の章では、Web キャッシュの根幹——HTTP キャッシュ——を深掘りする。