Ruby on rails x Redisでsessionを高速化しよう!


今日の目標

NoSQLデータベースについて学ぶ

今回は
Amazon Web Services Amazon ElastiCache for Redis または
Microsoft Azure Azure Redis Cache を利用する前の予習段階としてごく簡単なアプリケーションでRedisの設定を学習したメモ書きです。

Redisとは

Redisはメモリ上にデータを保存する超高速のデータベースの一種、データをメモリ上に保存するタイプのインメモリ型のKVS(Key Value Store)です。

KVSとは、主としてキーとバリューのシンプルなデータを保存するタイプのデータベースのことで、RDB(Relational Database)のような複雑なデータは扱えない反面、高速に動作するという特徴があります。

データの永続化を目的とする場合は向いていません

RailsでRedisを使うメリットとは?

Redisはシンプルでかつ高速なデータベースであるため、

  • キャッシュ(Rails.cache)
  • Ruby on Rails のセッションデータ

  • 大量データ送信データ(Active Job)

などの一時的なデータ保存先としてRedisを利用するとRailsを高速化することができます!

さらに、セッションデータの場合は、Redisへ変更することでセッションハイジャックなどのセキュリティリスクを軽減できます!

Redisをインストールしてみよう

Redis のインストール

$ brew install redis
(base) USERnoMacBookea:~ user$ brew install redis
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 1 tap (homebrew/services).
No changes to formulae.


==> Downloading https://homebrew.bintray.com/bottles/redis-5.0.8.mojave.bottle.tar.gz
==> Downloading from https://akamai.bintray.com/c7/c72def1c78f6c24c02d47de80a0b5ae5ef67640a42a38d040c503429eb02d3b1?__gda__=exp=1588749665~hmac=c2fa7998accdcd9eaee8924e58ca7815a1
######################################################################## 100.0%
==> Pouring redis-5.0.8.mojave.bottle.tar.gz
==> Caveats
To have launchd start redis now and restart at login:
  brew services start redis
Or, if you don't want/need a background service you can just run:
  redis-server /usr/local/etc/redis.conf
==> Summary
🍺  /usr/local/Cellar/redis/5.0.8: 13 files, 3.1MB

Redis サーバーの起動

$ redis-server

これでローカル環境で Redis を使えるようになります。

ターミナルで新規タブを立ち上げRedis に接続する

$ redis-cli
127.0.0.1:6379>

Redis を使ってみる

redis-cli で Redisサーバーに接続したあとに下記のように操作してみます。

SET を使って Key と Value を設定しデータを保存する
GET で Key を指定して Value を取得する
quit で redis-cli を終了

(base) USERnoMacBookea:~ user$ redis-cli
127.0.0.1:6379> SET mykey "Hello"
OK
127.0.0.1:6379> GET mykey
"Hello"
127.0.0.1:6379> quit

RailsにRedisを導入してみる

環境
ruby 2.5.1
rails 5.2.4

Rails アプリの作成

ここではとあるページにRedisから値を取り出して表示するだけの簡単なアプリケーションを作ります。

rails _5.2.4_ new redis_sample

gem redis-rails のインストール

gem 'redis-rails'
$ bundle install

config/application.rbに以下を記載

config/application.rb
config.cache_store = :redis_store, 'redis://localhost:6379/0/cache', { expires_in: 90.minutes }

config/application.rb に書いていますが、実際は環境毎に参照する Redis サーバーは違うと思うので、config/enviroments/◯◯.rb に書くとよいかと

サンプルページの作成

config/initializers/redis.rb
Redis.current = Redis.new

ローカル環境なので Redis.new しか書いていませんが、下記のように host と port を指定できるので、AWSのElastiCacheのRedisなどを使う場合はそれぞれを指定する必要があります。

app/controller/redis_controller
class RedisController < ApplicationController
  def show
    Redis.current.set('mykey', 'Hello')
  end
end

config/initializers/redis.rb で定義した Redis.current に対して値を保存します。

app/view/redis/show.html.erb
<%= Redis.current.get('mykey') %>

ビューでcontrollerで保存した値が取り出せるか確認してみましょう。

redisから値が取り出せることが確認できました。

Railsのセッション管理をRedisにしてみる

config/initializers/session_store.rbを作成します。(Rails 5.0ではデフォルトですが5.2以降の場合は作成してください)

config/initializers/session_store.rb
Rails.application.config.session_store :redis_store, {
  servers: [
    {
      host: "localhost",  # Redisのサーバー名
      port: 6379,         # Redisのサーバーのポート
      db: 0,              # データベースの番号(0 ~ 15)の任意
      namespace: "session"  # 名前空間。"session:セッションID"の形式
    },
  ],
  expire_after: 90.minutes # 保存期間
}

rails cで確認します

$ bin/rails c
>redis = Redis.new(url: 'redis://localhost:6379/0') # Redisに接続

# セッションを保存しているデータベースを選択
> redis.select 0
=> "OK

# Redisのセッションデータをクリア
> redis.flushdb
=> "OK"

# キーの一覧を取得
> redis.keys 
=> []

今回のサンプルアプリではセッションをくんでいないため redis.keys => []となりますが
Railsアプリケーションからセッションに保存する操作をすると以下のようにredis.keysで内容が確認できると思います。

# キーの一覧を取得
> redis.keys
=> ["session:de7b87c3c487b3622c8a505c5e1ce69a", "session:7d12e83552cd35bb1e082480fbaee71d"]

# 保存データの中身を確認
> redis.get "session:de7b87c3c487b3622c8a505c5e1ce69a"
=> "\u0004\b{\u0006I\"\u0010_csrf_token\u0006:\u0006EFI\"13u/SxOI4lsxx836eIAKj8yOnViUXGcAMF02kvvDQFB8=\u0006;\u0000F"

以上でセッションデータのRedis接続は完了です。

Redisは、メモリ上にデータを保存する超高速のデータベースの一種です。

Ruby on Railsのセッション管理データの保存先をRedisにすると、高速化だけでなくセキュリティー強化にもなるため、ぜひ活用してみてください。

参考

Redis キャッシュの有効化

クエリの結果をキャッシュしてDBアクセスの回数を減らして負荷を軽減するという方法
こちらの記事でサンプルアプリを作成することができます。

Railsでクエリ結果をキャッシュしてDB負荷を軽減する