redis_storeを使っているときRails.cache.clearはDBをまるまる吹っ飛ばすから注意


概要

Railsのキャッシュストアにredis_storeを用いている場合、Rails.cache.clearを呼び出すとキャッシュストアが使っているDBのデータが全部消えます。なのでキャッシュ用DBとそれ以外の用途のDBは分けておきましょう。

実験

設定ファイルはこんな感じ

config/initializers/redis.rb
require 'redis'
Redis.current = Redis.new(
  host: 'redis://localhost',
  port: 6379,
  db: 0
)
config/application.rb
...
...
  config.cache_store = :redis_store, {
    url: 'redis://localhost',
    port: 6379,
    db: 0
  }
...
...

では、試してみましょう。

# 書き込み
> Rails.cache.write('aaa', 'aaa')
=> "OK"
> Redis.current.with { |redis| redis.set('bbb', 'bbb') }
=> "OK"

# 読み込み
> Rails.cache.read('aaa')
=> 'aaa'
> Redis.current.with { |redis| redis.get('bbb') }
=> 'bbb'

# キャッシュクリア後読み込み
> Rails.cache.clear
=> nil
> Rails.cache.read('aaa')
=> nil
> Redis.current.with { |redis| redis.get('bbb') }
=> nil

Rails.cache.write で書き込んだ分以外もまとめて消えてしまっているのがわかります。

redis_store の実装を見てみるとわかるように、 Rails.cache.clear はRailsのキャッシュが使っているRedis DBに対して flushdb を行っています。そりゃ全部消えちゃうわけですね。
https://github.com/redis-store/redis-activesupport/blob/master/lib/active_support/cache/redis_store.rb#L247-L253

対処

キャッシュストアとそれ以外で、Redis DBを分けておきましょう。

config/initializers/redis.rb
require 'redis'
Redis.current = Redis.new(
  host: 'redis://localhost',
  port: 6379,
  db: 0
)
config/application.rb
...
...
  config.cache_store = :redis_store, {
    url: 'redis://localhost',
    port: 6379,
    db: 1
  }
...
...