Carpe Diem

備忘録

キャッシュアーキテクチャパターン

概要

キャッシュにおけるアーキテクチャパターンをまとめておきます。

表形式にすると次のようになります。

パターン 読み取り速度 書き込み速度 データ整合性 主な用途
Cache Aside
(キャッシュ層がオーバーヘッドにならない)

(期限切れ考慮)
一般的なWebアプリ
Read-Through
(同上)
読み取り専用が多いデータ
Write-Through 最高 最高 整合性が重要なデータ
Write-Around 大量のログ書き込み等
Write-Back 最高 最高 書き込み頻度が極端に高い

取得パターン

まずは取得系のパターンです。

Cache Aside

よくあるパターンです。Look Aside や Read Aside とも呼ばれます。

メリット

  • 読み取りの多いワークロードに最適
  • ロジックがシンプル
  • キャッシュコンポーネントで障害が起きても問題ない

デメリット

  • 呼び出し側がキャッシュを意識しないといけない
  • 初回アクセス時は必ずキャッシュミスが発生する(コールドスタート問題)
    • 初期は暖気しておいた方が安全。
  • データ整合性がずれることがある
    • TTLでなるべく最新になりやすいよう管理が必要

Read-Through

アプリケーションが常にキャッシュだけを読み取るパターンです。
ただもちろんキャッシュの内部的にはDB読み込みが発生することもあります。

メリット

  • Cache Asideに似ているが、参照が透過的になっている(=アプリケーション側がDBを意識しなくて済む)
    • ライブラリで吸収することが多い
  • 同じデータが何度も要求されるような読み込みの多いワークロードに最適
    • 例)ニュース記事

デメリット

  • キャッシュプロバイダー側でDB接続ロジックを実装する必要がある
  • コールドスタート問題がある。初期は暖気しておいた方が安全。
  • キャッシュレイヤの障害に弱い(実装次第だが)

更新パターン

次はキャッシュの更新パターンです。

Write-Through

アプリケーションがデータをキャッシュ→DBと両方に書き込むパターンです。

良く見る図は上のように透過的にされてますが、SDKなどで対応していない限りは下のように愚直に実装するパターンが多いです。

メリット

  • データ整合性が高い
    • DynamoDB Acceleratorは、リードスルー/ライトスルーキャッシュの良い例

デメリット

  • 両方書き込むため、書き込み速度が遅くなる
    • 書き込みがヘビーな要件でボトルネックになる可能性がある
  • 書き込んだが使われないデータでキャッシュ容量が無駄になる

Write Around

書き込み時はDBにのみ直接保存し、キャッシュには何もしないパターンです。
Cache Asideと併用する形になります。普通に作るとこれになります。

メリット

  • Write-Throughにある「一度書き込まれたが、その後しばらく読み込まれないデータ」でキャッシュが無駄に増えることがない
  • 読み込みが少ないユースケースに適している

デメリット

  • 書き込んだ直後の読み取りで必ずキャッシュミスが発生

Write-Back

基本キャッシュに書き込み、一定時間経過したり一定量溜まったら非同期でDBに書き込むパターンです。

メリット

  • Writeヘビーなユースケースに適している
    • DBへの書き込み・負荷を低減できる
  • DBが落ちてもキャッシュデータを使える

デメリット

  • データロストの可能性がある
    • DBに書き込む前にキャッシュが落ちた場合
  • 更新がリアルタイムでないためデータ整合性が低い

まとめ

キャッシュにおける主要な標準パターンをまとめました。

参考