mybook

第1章 — 読み書き戦略: キャッシュの基本パターン

5つの基本パターン

「キャッシュの読み書きには5つの基本パターンがある」とケンジはホワイトボードに書いた。

「それぞれに得意・不得意がある。プロジェクトの特性に合わせて選ぶんだ」

Cache-Aside(キャッシュアサイド)

最も一般的なパターン。アプリケーションがキャッシュとデータベースの両方を直接制御する。

Loading diagram...
# Rails での Cache-Aside パターン
def find_product(id)
  cache_key = "product:#{id}"
  
  # 1. キャッシュを確認
  product = Rails.cache.read(cache_key)
  return product if product
  
  # 2. DB から取得
  product = Product.find(id)
  
  # 3. キャッシュに保存
  Rails.cache.write(cache_key, product, expires_in: 1.hour)
  
  product
end
メリットデメリット
実装がシンプル初回アクセスは常にミス
アプリが全制御キャッシュとDBの不整合リスク
障害時もDB直接アクセス可能書き込み時の無効化が必要

INFO

Cache-Aside は「遅延読み込み(Lazy Loading)」とも呼ばれる。データは初めてリクエストされた時点でキャッシュに載る。

Read-Through(リードスルー)

キャッシュ層がデータの取得を自動的に代行する。アプリケーションはキャッシュにだけアクセスする。

Loading diagram...

Cache-Aside との違い: アプリケーションは DB の存在を知らない。キャッシュ層が透過的にデータを取得する。

Write-Through(ライトスルー)

書き込み時にキャッシュとDBの両方に同期的に書き込む

Loading diagram...
メリットデメリット
キャッシュとDBが常に一致書き込みレイテンシが増加
データロスのリスクが低い読まれないデータもキャッシュ

Write-Behind(ライトビハインド / Write-Back)

書き込みをキャッシュにだけ行い、DBへの書き込みを非同期で遅延させる。

Loading diagram...
メリットデメリット
書き込みが非常に高速キャッシュ障害でデータロス
DB負荷を平準化実装が複雑
バッチ書き込みで効率化一貫性の保証が困難

WARNING

Write-Behind は高速だが危険。キャッシュサーバーがクラッシュすると、DB に書き込まれていないデータが失われる。金融系システムには不向き。

Write-Around(ライトアラウンド)

書き込みはDBにだけ行い、キャッシュをスキップする。キャッシュは読み込み時にのみ更新される。

Loading diagram...

「書き込んだデータがすぐに読まれない場合」に有効。ログデータや分析データに向いている。

5パターンの比較

Loading chart...

選び方ガイド

Loading diagram...

Refresh-Ahead(先回りリフレッシュ)

TTL 切れを待たずに、期限が来る前にバックグラウンドでキャッシュを更新する。「空になる瞬間」を作らない。

Loading diagram...
class Ranking
  SOFT_TTL = 50.minutes
  HARD_TTL = 70.minutes
  CACHE_KEY = "ranking:popular"
 
  def self.fetch
    payload = Rails.cache.read(CACHE_KEY)
    if payload.nil? || Time.current >= payload[:refresh_at]
      schedule_refresh
    end
    return payload[:data] if payload
    regenerate
  end
 
  def self.schedule_refresh
    lock_key = "#{CACHE_KEY}/lock"
    if Rails.cache.write(lock_key, "1", unless_exist: true, expires_in: 1.minute)
      RefreshRankingJob.perform_async
    end
  end
end

INFO

Refresh-Ahead は Cache Stampede(サンダリングハード)の最も効果的な対策。TTL 切れの瞬間に大量リクエストが DB に殺到する問題を、「空になる瞬間を作らない」ことで根本解決する。

6パターンの比較

Loading chart...

選び方ガイド

Loading diagram...

マナミの選択

FreshMarket の最終的な組み合わせ:

データ戦略理由
商品詳細Cache-Aside + Write-Through読み多い+更新即反映
人気ランキングRefresh-Ahead重い集計+スタンピード防止
セール在庫Write-Behind書き込み殺到+多少の損失許容
操作ログWrite-Around書いて読まれない

次の章では、キャッシュが満杯になったときの退去戦略——エビクションアルゴリズム——を学ぶ。