railsにredisを導入する

前回、ruby で redis を使ってみるを書いたのですが、今回は activesupport を入り口に redis を rails で使ってみます。

目次

実行環境

  • windows
    • Windows10 ver.1909
  • Mac
    • macOS Mojave 10.14.4

参考

キャッシュ利用

導入(memory_store)

通常、キャッシュする仕組みは開発環境に対して有効化されていないということなので、
config\environments\development.rb を確認します。

config\environments\development.rb
1
2
3
4
5
6
7
8
9
10
11
12
if Rails.root.join('tmp', 'caching-dev.txt').exist?
config.action_controller.perform_caching = true

config.cache_store = :memory_store
config.public_file_server.headers = {
'Cache-Control' => "public, max-age=#{2.days.to_i}"
}
else
config.action_controller.perform_caching = false

config.cache_store = :null_store
end

/tmp/caching-dev.txtを作れば有効化できそうなので、/tmp/caching-dev.txtを作ります。
キャッシュ先として、memory_storeを使うことがわかります。

実装(memory_store)

users テーブルへのアクセス結果をキャッシュしてみることにします。

変更前は、次のようになります。

app\controllers\users_controller.rb(変更前抜粋)
1
2
3
4
5
6
7
8
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]

def index
@users = User.all
end

end

変更後は、次のようになります。

app\controllers\users_controller.rb(変更後抜粋)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]

def index
@users = users_all
end

def users_all
Rails.cache.fetch('USERS_ALL') do
User.all.to_a
end
end

end

確認(memory_store)

bundle exec rails sを実行し確認します。
localhost:3000/usersにアクセスします。
すると、コンソール上に初回だけUser Load (0.1ms) SELECT "users".* FROM "users"が表示され、
ページリロード以降は表示されません。

User のレコードを追加して、localhost:3000/usersに再度アクセスしても、件数が増えていません。
キャッシュした User.all の結果を使用しているからですね。
どうやら意図通り動いているようです。

一度停止し、再度bundle exec rails sを実行してlocalhost:3000/usersにアクセスすると増えていることを確認できます。

redis 利用

導入(redis)

ここまでは、キャッシュ先としてmemory_storeを使用していました。
キャッシュ先を redis に変えてみます。

Gemfile に、以下を追記します。

Gemfileに追記
1
gem 'redis-activesupport'

以下を実行します。

1
bundle install

github - redis-store/redis-railsを参考に、
config\environments\development.rbを以下のように編集します。

config\environments\development.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
if Rails.root.join('tmp', 'caching-dev.txt').exist?
config.action_controller.perform_caching = true

#config.cache_store = :memory_store # コメントアウトする
config.cache_store = :redis_store, {
host: "localhost",
port: 6379,
db: 0,
#password: "password",
namespace: "cache"
},{ expires_in: 90.minutes }# この記載を追加

config.public_file_server.headers = {
'Cache-Control' => "public, max-age=#{2.days.to_i}"
}
else
config.action_controller.perform_caching = false

config.cache_store = :null_store
end

確認(redis)

bundle exec rails sを実行してlocalhost:3000/usersにアクセスします。
memory_storeを使用していた時同様に、コンソール上に初回だけUser Load (0.1ms) SELECT "users".* FROM "users"が表示されます。

redis-cli を用いて確認してみます。
以下のコマンドを実行します。

1
2
3
4
5
6
7
redis-cli
127.0.0.1:6379> keys *
1) "cache:USERS_ALL"
127.0.0.1:6379> get cache:USERS_ALL
"\x04\bo: ActiveSupport::Cache::Entry\n:\x0b@value\"\x02\x04\x03x\x9c\xa5\x93]o\xd30\x14\x86\x8b\x84\xba&\x1d\x14$\x10\xbb\x80\xd1u\x80@\xa8\x95\xf3\xd56\xc77.\xb0\x88\"v\xc1\xe8\xb8\xa0\x17\x91\x9b\x98,
~~かなりの文字数なので省略~~
"

redis に、指定したUSERS_ALLをキーにキャッシュされたことが確認できます。
次は、現在キャッシュ時間に任意変更とエラー対応をしてみます。

キャッシュ時間変更他

実装

app\controllers\users_controller.rbを以下のように書き換えます。

app\controllers\users_controller.rb(抜粋)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]

def index
@users = users_all
end

def users_all
# キャッシュ時間を30秒に設定
Rails.cache.fetch('USERS_ALL', expires_in: 30.second) do
#キャッシュになかったらDBから取得
User.all.to_a
end
end

end

確認

redis-cli を使用し、一度登録したキーcache:USERS_ALLを削除しておきます。

1
2
3
4
5
redis-cli
127.0.0.1:6379> keys *
1) "cache:USERS_ALL"
127.0.0.1:6379> del cache:USERS_ALL
(integer) 1

bundle exec rails sを実行してlocalhost:3000/usersにアクセスします。
コンソール上に初回はUser Load (0.1ms) SELECT "users".* FROM "users"が表示るのは、これまで同様です。
加えて、30 秒程度立ってからアクセスするとUser Load (0.1ms) SELECT "users".* FROM "users"が再度表示されます。
キャッシュ時間 30 秒を行った結果が反映されました。

試しに、redis-server を停止してlocalhost:3000/usersにアクセスすると、レスポンスが遅くなります。
Chrome の開発者ツールでレスポンスを確認すると、20 秒程度かかっていました。
redis にアクセスできないとき、都度 DB にアクセスしていることも確認できました。


今回は、activesupport で memory_store でのキャッシュを試し、最後にキャッシュ先を redis に変更することを試しました。
今回 users テーブルからは 10 件程度しか取得していないのですが、DB から取得した時とキャッシュから時では、1ms 程度差が出ました。
データ数が、増えると差がより開いてくるでしょうから押さえておけたのはよかったです。

ではでは。