Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

RubyでRedisデータベースを使う方法|インストールからRailsキャッシュ活用まで徹底解説

Redisとは?

Redisは、多彩なデータ構造を扱えるインメモリデータベースです。主なデータ構造には以下のようなものがあります。

  • キー/バリュー(Key/Value)ストレージ
  • リスト
  • セット

Postgresなどの一般的なSQLデータベースとは、データの保存方式も設計思想もまったく異なります。

Redisの主な用途

  • キャッシュ
  • ランキング(リーダーボード)
  • 訪問者数のカウント
  • 高速なオートコンプリート(入力補完)
  • アクティブなユーザーセッションの管理
  • ジョブ&メッセージキュー

それでは、RubyアプリケーションでRedisを活用する方法を見ていきましょう!

Redisのローカル環境へのインストール

まず最初に必要なのは、Redisサーバーのインストールです。他のデータベースと同じように、ローカルマシンに導入します。

Ubuntuならapt install redis-server、Macならbrew install redisでインストールできます。Windows 10の場合は「Windows Subsystem for Linux(WSL)」経由での利用が必要です。

サーバーが起動したら、redis-cliコマンドでサーバーに接続できます。

注意:接続する前に、別のターミナルでredis-serverを実行してサーバーを起動しておく必要がある場合があります。

これでRedisを使う準備が整いました!

RubyからRedisを操作するためのGem

redis-cliを使えば直接Redisを操作できますが、RubyのコードからRedisを扱いたい場合はGemを利用するのが便利です。

代表的なGemには以下があります

  • oxblood
  • redic
  • redis-rb

この中でRedis開発チームが公式に推奨しているのはredis-rbだけです。

インストール方法

gem install redis

Gemをインストールしたら、Redisサーバーに接続して実際に操作してみましょう。

まずは、キーaに値1を設定してみます。

サンプルコード

require 'redis'

redis = Redis.new(host: "localhost")

redis.set("a", 1)
# "OK"

redis.get("a")
# "1"

このGemは、RubyのメソッドをRedisのコマンドへうまくマッピングしてくれます。使えるコマンドを調べたいときは、Redis公式ドキュメントかGemのドキュメントを参照するとよいでしょう。

ドキュメントの効果的な活用法

Redisのドキュメントでは、特定のコマンド名を直接入力して検索できるほか、データ構造ごとに絞り込んで検索することもできます。

「Filter by group」をクリックして「Strings」を選択し、任意のコマンドを選んで試してみてください。

たとえば、値を1ずつ増やせるincrコマンドは次のように使います。

redis.incr("a")
# "2"

また、setexを使えば、有効期限つきのキーを自動的に作成できます。

redis.setex("bacon", 10, 100)

第2引数はキーが失効するまでの秒数、第3引数はキーに格納する値です。

実行例

redis.get("bacon")
# "100"

10秒後には……

redis.get("bacon")
# nil

このように、指定時間が経過するとキーは自動的に消えます。ほかのコマンドもいろいろ試してみてください!

ソート済みセット(Sorted Set)の使い方

Redisの能力は、単純なキー/バリュー保存にとどまりません。強力なデータ構造がいくつも用意されています。

そのひとつがソート済みセット(Sorted Set)です。

これは、指定した値(スコア)で並べ替えられた、重複のない要素のリストを作成できるデータ構造です。Redisのドキュメントでは、この並べ替えの基準となる値を「スコア」と呼んでいます。

セットの中から上位N件を取得するクエリも簡単に実行できます。つまり、ランキング機能に最適というわけです!

サンプル

redis.zadd("popular_fruit", 10, "apple")
# true
redis.zadd("popular_fruit", 20, "banana")
# true
redis.zadd("popular_fruit", 30, "orange")
# true

セットができたら、上位1件を取得してみましょう。

r.zrevrange("popular_fruit", 0, 0)
# ["orange"]

このコマンドの意味は次のとおりです。

「最高ランク(0)からスタートして、上位1件を取得せよ」

すべての要素を順番に取得したい場合

r.zrevrange("popular_fruit", 0, -1)
# ["orange", "banana", "apple"]

zrevrangeの「rev」はreverse(逆順)を意味し、要素を降順で返します。

zrangeを使えば、要素は昇順で取得できます。

ソート済みセットの用途はランキングだけではありません。もうひとつの応用例として、ZRANGEBYLEXコマンドを使った高速なオートコンプリート(入力補完)エンジンの構築が挙げられます。

その他のセット操作については、公式ドキュメントを参照してください。

キー・バリューと名前空間の設計

Redisにはカラムもテーブルも存在せず、すべてがひとつのフラットな名前空間の中にあります。

では、どうやってデータを整理すればよいのでしょうか?

答えは、キー名そのものを工夫することです。

よく使われる命名規則のひとつが、総称部分と個別部分をコロン(:)で区切る方法です。

記述例

redis.set("fruit:1", "apple")
# OK
redis.set("fruit:2", "banana")
# OK

この規則自体に特別な意味はありません。Redis(ソフトウェア)にとっては、コロンありのキーコロンなしのキーもまったく同じものとして扱われます。しかし、あなた(Ruby開発者)にとっては、データを整理・把握するうえで非常に役立つでしょう。

Redisのデータ永続化

デフォルト設定のRedisは、通常のデータベースのようにすべての操作を即座にディスクへ書き込みません。

サーバーを停止するとき、または以下の条件を満たしたときにのみ、データがディスクへ保存されます。

  • 15分経過後、1個以上のキーが変更されていた場合
  • 5分経過後、10個以上のキーが変更されていた場合
  • 1分経過後、10,000個以上のキーが変更されていた場合

このとき、カレントディレクトリにdump.rdbファイルが作成されます。

SQLデータベースに近い永続化の挙動を望む場合は、「Append Only Mode(AOF)」を有効にしましょう。このモードでは、変更内容が毎秒ディスクに保存されます。

有効にするには、Redisの設定ファイルに以下の行を追加(またはコメント解除)します。

appendonly yes

RailsのキャッシュストアとしてRedisを使う

Rails 5.2以降では、Redisをキャッシュストアとして利用できます。必要なのはredisGemとRedisサーバーだけです。

設定方法

# config/environments/production.rb

Rails.application.configure do
  config.cache_store = :redis_cache_store, { url: "redis://localhost:6379/0" }
end

これで、Railsはすべてのキャッシュ処理にRedisを使うようになります。

キャッシュにデータを保存することもできます

Rails.cache.write("a", 1)
# "OK"

Rails.cache.read("a")
# 1

Railsが保存する値は次のような形式になります

"\u0004\bo: ActiveSupport::Cache::Entry\t:\v@valuei\u0006:\r@version0:\u0010@created_atf\u00171555005228.7954454:\u0010@expires_in0"

つまり、シリアライズ可能な任意のRubyオブジェクト——たとえばActiveRecordクエリの結果など——をそのままキャッシュに保存できるのです。

Redisに関するFAQ

「Redisサーバー内のすべてのキーを一覧表示できますか?」

はい、keysscanコマンドで一覧表示できます。ただし、これらのコマンドは動作が非常に遅く、データベースが大きくなるほど顕著になるため、本番環境での使用は推奨されません。

「Redisはどんなときに使うべき?」

自分のユースケースに合っているときだけ使いましょう。具体的には、Redisのデータ構造を活かすことでコードの見通しが良くなるような場面です。

「流行っているから」「かっこいいから」という理由だけで採用するのは避けましょう。他のソリューションよりも優れた形で問題を解決できるときに使うのが正解です。

「Redisをもっと速くするには?」

redis-rbに加えてhiredisGemをインストールすると、最大限のパフォーマンスを引き出せます。

まとめ

この記事では、高速なインメモリデータベースであるRedisについて学びました。キャッシュ、カウンタ、キューなど、適切な場面で活用すれば大きな力を発揮します。

この記事が役に立ったと思ったら、ぜひシェアして更多人に届けてください。

最後までお読みいただきありがとうございました!

  1. Rubyのmapメソッド完全ガイド!配列・ハッシュのデータ変換を実例で解説

    Rubyのmapメソッドは、配列(Array)・ハッシュ(Hash)・範囲(Range)といったコレクションに対して使用できる強力なメソッドです。 mapの主な用途は、データの変換です。 例えば、文字列の配列があった場合、すべての文字列を順番に処理して、各文字を大文字に変換することができます。 また、Userオブジェクトのリストがある場合も同様です。 それらを変換して、対応するメールアドレスや電話番号など、Userクラスに定義された任意の属性のリストを作成できます。 それでは、具体的な使い方を見ていきましょう! Ruby mapメソッドの基本構文 mapの構文は次のようになっています。 a

  2. RubyのStructとOpenStructの使い方を徹底解説!値オブジェクトを簡単に作る方法

    Rubyには、関連する属性をまとめて保持する「値オブジェクト」を手軽に作れるStructという組み込みクラスが用意されています。本記事では、Structの基本的な使い方から注意点、そしてOpenStructとの違いまで詳しく解説します。 そもそもStructとは何か? StructはRubyに組み込まれたクラスで、新しいクラスを動的に生成し、値オブジェクト(Value Object)を作成するために使われます。値オブジェクトとは、関連性のある複数の属性をひとまとめにして扱うためのオブジェクトです。 具体例を挙げてみましょう。 2つの座標(xとy)を持つPointというデータを表したい場合、この