Deep-dive on the Next Gen Platform. Join the Webinar!

Skip Navigation
Show nav
Dev Center
  • Get Started
  • ドキュメント
  • Changelog
  • Search
  • Get Started
    • Node.js
    • Ruby on Rails
    • Ruby
    • Python
    • Java
    • PHP
    • Go
    • Scala
    • Clojure
    • .NET
  • ドキュメント
  • Changelog
  • More
    Additional Resources
    • Home
    • Elements
    • Products
    • Pricing
    • Careers
    • Help
    • Status
    • Events
    • Podcasts
    • Compliance Center
    Heroku Blog

    Heroku Blog

    Find out what's new with Heroku on our blog.

    Visit Blog
  • Log inorSign up
Hide categories

Categories

  • Heroku のアーキテクチャ
    • Dyno (アプリコンテナ)
      • Dyno Management
      • Dyno Concepts
      • Dyno Behavior
      • Dyno Reference
      • Dyno Troubleshooting
    • スタック (オペレーティングシステムイメージ)
    • ネットワーキングと DNS
    • プラットフォームポリシー
    • プラットフォームの原則
  • Developer Tools
    • コマンドライン
    • Heroku VS Code Extension
  • デプロイ
    • Git を使用したデプロイ
    • Docker によるデプロイ
    • デプロイ統合
  • 継続的デリバリーとインテグレーション
    • 継続的統合
  • 言語サポート
    • Node.js
      • Working with Node.js
      • Troubleshooting Node.js Apps
      • Node.js Behavior in Heroku
    • Ruby
      • Rails のサポート
      • Bundler の使用
      • Working with Ruby
      • Ruby Behavior in Heroku
      • Troubleshooting Ruby Apps
    • Python
      • Working with Python
      • Python でのバックグランドジョブ
      • Python Behavior in Heroku
      • Django の使用
    • Java
      • Java Behavior in Heroku
      • Working with Java
      • Maven の使用
      • Spring Boot の使用
      • Troubleshooting Java Apps
    • PHP
      • PHP Behavior in Heroku
      • Working with PHP
    • Go
      • Go の依存関係管理
    • Scala
    • Clojure
    • .NET
      • Working with .NET
  • データベースとデータ管理
    • Heroku Postgres
      • Postgres の基礎
      • Postgres スターターガイド
      • Postgres のパフォーマンス
      • Postgres のデータ転送と保持
      • Postgres の可用性
      • Postgres の特別なトピック
      • Migrating to Heroku Postgres
    • Heroku Data For Redis
    • Apache Kafka on Heroku
    • その他のデータストア
  • AI
    • Working with AI
  • モニタリングとメトリクス
    • ログ記録
  • アプリのパフォーマンス
  • アドオン
    • すべてのアドオン
  • 共同作業
  • セキュリティ
    • アプリのセキュリティ
    • ID と認証
      • シングルサインオン (SSO)
    • Private Space
      • インフラストラクチャネットワーキング
    • コンプライアンス
  • Heroku Enterprise
    • Enterprise Accounts
    • Enterprise Team
    • Heroku Connect (Salesforce 同期)
      • Heroku Connect の管理
      • Heroku Connect のリファレンス
      • Heroku Connect のトラブルシューティング
  • パターンとベストプラクティス
  • Heroku の拡張
    • Platform API
    • アプリの Webhook
    • Heroku Labs
    • アドオンのビルド
      • アドオン開発のタスク
      • アドオン API
      • アドオンのガイドラインと要件
    • CLI プラグインのビルド
    • 開発ビルドパック
    • Dev Center
  • アカウントと請求
  • トラブルシューティングとサポート
  • Salesforce とのインテグレーション
  • 言語サポート
  • Ruby
  • Rails のサポート
  • Memcache を使用した Rails 5 アプリケーションの構築

This article was contributed by The MemCachier Add-on

MemCachier manages and scales clusters of memcache servers so you can focus on your app. Tell us how much memory you need and get started for free instantly. Add capacity later as you need it.

follow @MemCachier on Twitter

Memcache を使用した Rails 5 アプリケーションの構築

日本語 — Switch to English

この記事の英語版に更新があります。ご覧の翻訳には含まれていない変更点があるかもしれません。

最終更新日 2020年05月22日(金)

Table of Contents

  • 前提条件
  • アプリケーションの作成
  • Heroku にデプロイ
  • MemCachier アドオンのインストールとキャッシングの設定
  • 機能の追加
  • キャッシングの追加
  • キャッシュの期限切れ処理
  • 組み込みの Rails キャッシング
  • 参考情報と資料

Web アプリケーションにキャッシングを追加して、パフォーマンスを大きく改善することができます。複雑なデータベースクエリ、コストの高い計算、または時間のかかる外部リソース呼び出しの結果を、単純な key-value ストアにアーカイブできます。このストアには、高速な O(1) ルックアップを使用してアクセスできます。

Rails 3.1 以降での Rack::Cache を使用した静的アセットキャッシングについては この記事​で説明しています

このチュートリアルでは、単純な Rails 5 アプリケーションを作成して Heroku にデプロイし、MemCachier アドオン を使用してコストの高いクエリをキャッシュする手順を解説します。

小規模なデモ用に作成された Rails サンプルの動作は こちら​で確認できます。
​ソースコード​または Heroku にデプロイ

前提条件

  • Ruby/Rails に関する基本的な知識
  • Ruby 2.2 以降、Rubygems、Bundler、Rails 5 以降のローカルにインストールされたバージョン。 注: このガイドは Rails 3 および 4 にも対応しています。
  • Git に関する基本的な知識
  • Heroku ユーザーアカウント。 無料ですぐにサインアップできます​。

アプリケーションの作成

rails​ コマンドを使用してアプリのスケルトンを生成します。

$ rails new memcache-example
$ cd memcache-example/

まず、Gemfile​ で ruby バージョンを指定します。

ruby '2.5.0'

次に、データベースをセットアップします。Gemfile で、次の行を変更します。

gem 'sqlite3'

変更後は次のとおりです。

group :development do
  gem 'sqlite3'
end

group :production do
  gem 'pg', '~>0.21'
end

これにより、アプリは本番環境で必ず Postgres データベースを利用します。注: ​pg​ へのバージョン制約の追加は今後不要になる可能性がありますが、現在の Rails バージョン 5.1.4​ は現在の pg バージョン 1.0.0​ と互換性がありません。

ここで、次のように実行して

$ bundle install --without production

Gemfile.lock​ ファイルを更新します。--without production​ オプションを指定すると、pg gem がローカルにインストールされなくなります。

変更をコミットします (注: 古いバージョンの Rails を使用している場合、先に git init​ で Git リポジトリを作成することが必要な場合があります)。

$ git add .
$ git commit -m "Initial rails app."

Heroku にデプロイ

heroku​ コマンドを使用して、新しい Heroku アプリをプロビジョニングします。

$ heroku create

次に、Heroku にデプロイします。

$ git push heroku master

MemCachier アドオンのインストールとキャッシングの設定

MemCachier​ の記事で述べたように、アドオンと dalli​ gem をインストールする必要があります。オプションの memcachier​ gem も推奨されます。

ターミナルで次のように実行します。

$ heroku addons:create memcachier:dev

Gemfile を変更して、memcache クライアントライブラリ dalli​ と、セットアップに役立つ単純な gem である memcachier​ を含めます。

gem 'dalli'

その後、次のように実行します。

$ bundle install --without production

これにより、追加された gem がインストールされ、Gemfile.lock​ ファイルが更新されます。

ここで、config/environments/production.rb​ を変更して次の内容を含めることにより、dalli​ によって提供されるキャッシュストアを利用するようにデフォルトの Rails キャッシングを 設定します。

config.cache_store = :mem_cache_store,
                    (ENV["MEMCACHIER_SERVERS"] || "").split(","),
                    {:username => ENV["MEMCACHIER_USERNAME"],
                     :password => ENV["MEMCACHIER_PASSWORD"],
                     :failover => true,
                     :socket_timeout => 1.5,
                     :socket_failure_delay => 0.2,
                     :down_retry_delay => 60
                    }

この例がどのように動作するかを確認しやすくするために、組み込みのキャッシングを一時的に無効化します。

config.action_controller.perform_caching = false

機能の追加

Rails scaffold ジェネレーターを使用して、名前とメールアドレスの単純なディレクトリを保存および表示するためのインターフェースを作成します。

$ rails g scaffold contact name:string email:string
$ rake db:migrate

config/routes.rb​ を編集して、contacts#index​ を root ルートとして設定します。

root :to => 'contacts#index'

注: Rails 3 アプリで public/index.html​ を削除できるようになりました。

変更をコミットし、Heroku にプッシュし、次のコマンドを使用してリモートデータベースを移行します。

$ git add .
$ git commit -m "Added first model."
$ git push heroku master
$ heroku run rake db:migrate

heroku open​ を使用してアプリにアクセスし、連絡先のリストを表示できるようになったはずです。"New Contact" (新しい連絡先) リンクから、いくつかのレコードを作成します。

キャッシングの追加

ContactsController​ のコードは次のようになります。

def index
    @contacts = Contact.all
end

/contacts​ がリクエストされるたびに、index​ メソッドが実行され、連絡先テーブル内のすべてのレコードを取得するためのデータベースクエリが実行されます。

テーブルが小さくリクエストの分量が少ない場合、これはあまり問題になりませんが、データベースとユーザーの規模が拡大すると、このようなクエリがアプリのパフォーマンスに影響を及ぼす可能性があります。このページにアクセスするたびにデータベースクエリが実行されないよう、Contact.all​ の結果をキャッシュしましょう。

Rails.cache.fetch​ メソッドはキー引数とブロックを取ります。キーが 存在する場合、それに対応する値が返されます。キーが 存在しない場合、ブロックが実行され、提供されたキーで値が保存されてから 返されます。

app/models/contact.rb​ で、次のメソッドを Contact クラスに追加します。

def self.all_cached
  Rails.cache.fetch('Contact.all') { all.to_a }
end

app/controllers/contacts_controller.rb​ で、次の部分を変更します。

@contacts = Contact.all

変更後は次のとおりです。

@contacts = Contact.all_cached

all​ の代わりに all.to_a​ をキャッシュすることに注意してください。これは、Rails 4 の Model.all​ は遅延実行され、実際の連絡先をキャッシュするためには to_a​ を使用して Contact.all​ を 配列に変換する必要があるからです。

インデックスページにもいくつかの統計を表示してみましょう。app/controllers/contacts_controller.rb​ で、次の行を index​ メソッドに追加します。

@stats = Rails.cache.stats.first.last

次のマークアップを app/views/contacts/index.html.erb​ の下部に追加します。

<h1>Cache Stats</h1>

<table>
  <tr>
    <th>Metric</th>
    <th>Value</th>
  </tr>
  <tr>
    <td>Cache hits:</td>
    <td><%= @stats['get_hits'] %></td>
  </tr>
  <tr>
    <td>Cache misses:</td>
    <td><%= @stats['get_misses'] %></td>
  </tr>
  <tr>
    <td>Cache flushes:</td>
    <td><%= @stats['cmd_flush'] %></td>
  </tr>
</table>

結果をコミットして Heroku にプッシュします。

$ git commit -am "Add caching."
$ git push heroku master

/contacts​ ページを更新すると “Cache misses: 1”​ と表示されます。これは、'Contact.all'​ キーの取得を試みたものの存在しなかったためです。 もう一度更新すると、今度は “Cache hits: 1”​ と表示されます。 前回のリクエスト中に 'Contact.all'​ キーが保存されたため、今回はこのキーが存在していました。

Heroku コンソールでキャッシュをクリアすると、この効果をもう一度確認できます。

$ heroku run console
>> Rails.cache.clear

キャッシュの期限切れ処理

Contact.all​ がキャッシュされるようになりましたが、そのテーブルが変更されるとどうなるでしょうか。新しい連絡先を追加し、リスト表示ページに戻ってみてください。 新しい連絡先が表示されないことがわかります。Contact.all​ が キャッシュされているので、古い値がまだ表示されています。何か変更があったときにキャッシュの値を期限切れにする方法が必要です。 これは、Contact​ モデルでフィルターを使用して実現できます。

次のコードを app/models/contact.rb​ の Contact クラスに追加します。

class Contact < ApplicationRecord
  after_save    :expire_contact_all_cache
  after_destroy :expire_contact_all_cache

  def expire_contact_all_cache
    Rails.cache.delete('Contact.all')
  end

  #...

end

これらの変更をコミットして Heroku にプッシュします。

$ git commit -am "Expire cache."
$ git push heroku master

連絡先を保存 (作成または更新) または破棄するたびに Contact.all​ キャッシュキーが削除されるようになったことがわかります。これらの変更のいずれかを行って /contacts​ に戻るたびに “Cache misses” カウントが 1 ずつ増加するはずです。

組み込みの Rails キャッシング

上記の例では、キャッシュを明示的に取得して期限切れにする方法を説明しています。 便利なことに、Rails にはこの機能の多くが組み込まれています。 次のように

config.action_controller.perform_caching = true

config/environments/production.rb​ で設定すると、Rails でフラグメント、アクション、ページのキャッシングを実行できます。

ここでは、これらのキャッシング手法を簡単に紹介するにとどめます。詳細および “ロシア人形方式” キャッシングなどのその他の手法については、 キャッシングに関する Rails ガイド​を参照してください。

フラグメントキャッシング

Rails のページは、さまざまなコンポーネントで構成されるのが一般的です。これらのコンポーネントはフラグメントキャッシングでキャッシュできるため、ページがリクエストされるたびに再構築する必要はありません。

たとえば、今回の /contacts​ ページは複数の連絡先コンポーネントで構成され、それぞれのコンポーネントで名前、メールアドレス、3 つのアクション (表示、編集、破棄) を表示しています。app/views/contacts/index.html.erb​ で次の内容を @contacts.each​ ループに追加することによって、これらのフラグメントをキャッシュできます。

# ...
<% @contacts.each do |contact| %>
  <% cache contact do %>
    # ...
  <% end %>
<% end %>
# ...

アクションキャッシング

フラグメントに加えて、Rails ではページとアクションのキャッシングを使用してページ全体をキャッシュすることもできます。Rails スタックを完全にバイパスできるページキャッシングの方が効率的ですが、認証などの事前フィルターがあるページでは機能せず、ファイルストレージがない Heroku でのセットアップには少しコツが必要です。アクションキャッシングでは、ページキャッシングと同様にオブジェクトとビューを保存しますが、こちらは Rails スタックによって提供されます。

アクションキャッシングを使用するには、actionpack-action_caching gem​ を Gemfile に追加して bundle install​ を実行する必要があります。

gem 'actionpack-action_caching'

たとえば、show​ アクションの結果をキャッシュするには、次の行を app/controllers/contacts_controller.rb​ に追加します。

class ContactsController < ApplicationController
  caches_action :show
  # ...
end

適切な期限切れ処理のために、contacts_controller.rb​ で次の行を update​ メソッドと destroy​ メソッドの両方に追加します。

def update
  expire_action :action => :show
  # ...
end

def destroy
  expire_action :action => :show
  # ...
end

アクションキャッシングを使用する場合でも、フラグメントキャッシングの重要性は変わらないことに注意してください。 フラグメントキャッシュにより、ページの有効期限が切れた場合でもページ全体をゼロから再構築する必要はなくキャッシュ済みのフラグメントを使用できることが保証されます。この手法は “ロシア人形方式” のキャッシングに似ています。

セッションのキャッシング

Memcache は非永続セッションに適した高速ストレージです (永続セッションにはデータベースを使用してください)。これは、各 dyno が独自の一時的なファイルシステムを備える Heroku で特に当てはまります。したがって Heroku では、ファイルシステムを使用してセッションを保存するデフォルトの動作が不整合につながる可能性があります。

キャッシュをセッションストレージに使用するには、次の内容で config/initializers/session_store.rb​ ファイルを作成するか (Rails 5)、このファイルを編集して次の内容を含めます (Rails 3 および 4)。

# Be sure to restart your server when you modify this file.
Rails.application.config.session_store :cache_store, key: '_memcache-example_session'

参考情報と資料

このチュートリアルで構築したアプリケーションの完全なソースは GitHub​ から自由にダウンロードできます。

  • キャッシングに関する Rails ガイド
  • Rails でのキャッシング戦略
  • Memcached での Rack::Cache の使用
  • Memcache の高度な使用法
  • MemCachier ドキュメント
  • MemCachier アドオンページ

関連カテゴリー

  • Rails のサポート
Unicorn を使用した Rails アプリケーションのデプロイ Rails 3.1 以降 (Rails 4 を含む) での Rack::Cache と Memcached の使用

Information & Support

  • Getting Started
  • Documentation
  • Changelog
  • Compliance Center
  • Training & Education
  • Blog
  • Support Channels
  • Status

Language Reference

  • Node.js
  • Ruby
  • Java
  • PHP
  • Python
  • Go
  • Scala
  • Clojure
  • .NET

Other Resources

  • Careers
  • Elements
  • Products
  • Pricing
  • RSS
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku Blog
    • Heroku News Blog
    • Heroku Engineering Blog
  • Twitter
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku
    • Heroku Status
  • Github
  • LinkedIn
  • © 2025 Salesforce, Inc. All rights reserved. Various trademarks held by their respective owners. Salesforce Tower, 415 Mission Street, 3rd Floor, San Francisco, CA 94105, United States
  • heroku.com
  • Legal
  • Terms of Service
  • Privacy Information
  • Responsible Disclosure
  • Trust
  • Contact
  • Cookie Preferences
  • Your Privacy Choices