💾

Solid Cache(Rails)

Redisの代わりにSSD — データベース基盤Railsキャッシュストア

GitHub: rails/solid_cache

Solid Cacheは37signalsが作ったDB基盤のキャッシュストアです。「メモリ(RAM)は高く、SSDは安い」というシンプルな観察から出発しています。Redisのメモリ制限(数GB)の代わりにSSD(数TB)を活用すれば、はるかに大きなキャッシュをはるかに安価に運用できます。

詳細なアーキテクチャ分析については韓国語版を参照してください。キャッシュエントリをDBテーブルの行として保存するコアアイデア、solid_cache_entriesスキーマ、キャッシュ読み書き操作、書き込み頻度に比例した確率的期限切れメカニズム(EXPIRY_MULTIPLIER = 2)、シャーディングのためのMaglev一貫ハッシュ、設定オプション、Redis vs Solid Cache比較が含まれます。

トレードオフ: 若干遅い(msレベル)が、はるかに大きなキャッシュをはるかに安価に運用できます。ほとんどのRailsアプリでこの差は体感されません。

構造ダイアグラム

キャッシュ保存構造

💾 solid_cache_entries entry.rb ↗
key string
キャッシュキー
key_hash int64
SHA256 → signed int
value blob
シリアライズされた値
byte_size integer
値サイズ (期限切れ用)
INDEX: key_hash (検索) / ID順 = 時間順 (期限切れ)
ポイント: <strong>key_hash</strong>で高速検索 + <strong>ID順</strong>でFIFO期限切れ (created_atインデックス不要)

キャッシュ読み書きフロー

書き込み (Write)
1. Rails.cache.write('key', value)
2. Entry.write_multi → upsert_all code ↗
3. track_writes → カウンター増加
確率的期限切れトリガー? expiry.rb ↗
読み込み (Read)
1. Rails.cache.read('key')
2. LocalCache確認 (メモリ1次キャッシュ)
3. Entry.read_multi → key_hash IN (?)
uncached(dirties: false)
クエリキャッシュOFF → 常に最新

期限切れメカニズム (TTLではなく確率的期限切れ)

write
write
write
write
50%!
↓ batch_sizeの50%到達
expire_later (非同期) expiration.rb ↗
max_age
2週間超過削除
max_entries
ID順FIFO削除
max_size
サイズ基準削除
EXPIRY_MULTIPLIER = 2 → 書き込み1件あたり2件分の期限切れ圧力

Redis vs Solid Cache

Redis
Solid Cache
ストレージ
RAM (高価)
SSD (安価)
キャッシュサイズ
~数 GB
~数 TB
速度
~0.1ms
~1-5ms
期限切れ
TTLベース
確率的FIFO
運用
Redisサーバー必要
DBのみ必要
シャーディング
Redis Cluster
Maglev ハッシング

シャーディング (Maglev Consistent Hashing)

Rails.cache.write('user:123', data)
MaglevHash
CRC32('user:123') → テーブル[2053] → shard決定
maglev_hash.rb ↗
Shard 1
cache_db_1
Shard 2
cache_db_2
Shard 3
cache_db_3
ポイント: シャード追加/削除時に<strong>最小限のキーのみ再分配</strong> (一貫性ハッシュ)

キーポイント

1

GitHubでrails/solid_cacheリポジトリを開く

2

app/models/solid_cache/entry.rb → キャッシュエントリモデルを分析

3

app/models/solid_cache/entry/expiration.rb → 期限切れロジックを分析

4

lib/solid_cache/store.rb → ActiveSupport::Cache::Storeサブクラス構造

5

lib/solid_cache/store/expiry.rb → 書き込み基盤の確率的期限切れトリガー

6

lib/solid_cache/maglev_hash.rb → 一貫ハッシュ実装を分析

7

lib/solid_cache/connections/ → 単一DB vs シャーディング接続管理

8

db/migrate/ → solid_cache_entriesテーブルスキーマを確認

メリット

  • Redis不要 — 運用インフラの簡素化
  • SSD活用 — RAMよりはるかに大きなキャッシュが可能
  • ActiveSupport互換 — Rails.cache APIをそのまま使用
  • 別途設定なしでRails 8でデフォルト動作
  • Maglevハッシュ — 優雅なシャーディングサポート
  • 暗号化サポート — ActiveRecord Encryptionを活用

デメリット

  • Redisより遅い(RAM ~0.1ms vs SSD ~1-5ms)
  • DB負荷増加 — 別途キャッシュDB推奨
  • 確率的期限切れ — TTLのような正確な期限切れ時点を保証しない
  • 高性能リアルタイムシステムにはRedisが依然として有利
  • クエリキャッシュ無効化で常にDBヒット

ユースケース

Redis削除: インフラ簡素化(DBだけでキャッシュ) 大容量キャッシュ: SSD基盤で数TBキャッシュ可能 インストール型アプリ: ONCEのような単一サーバーアプリでRedisなしで運用 Rails.cache.fetchパターン: 既存コード変更なしでバックエンドのみ交換 シャーディング: 複数DBにキャッシュを分散して性能確保