Ubuntu 12.04 LTSでMemcachedをRuby on Railsで使用する方法

Memcachedは、非常に高速なメモリ内のオブジェクトをキャッシュするためのシステムです。 Memcachedを使用すると、最小限のコストでRailsアプリケーションの速度を大幅に向上させることができます。



前提条件


Ruby on RailsとMemcachedが既にシステムにインストールされていることを前提としています。 そうでない場合は、以下のリンクが役立ちます。



また、Memcachedを使用して最適化する予定の実行中のRailsアプリケーションがあることを前提としています。



Dalli Gemのインストール



最初に行う必要があるのは、Mike Perham Dalli gemをインストールすることです。

gem install dalli
      
      





Bundlerを使用している場合は、 gem 'dalli'行をGemfileに追加し、 バンドルインストールを完了します。

次に、RailsとMemcachedの間の相互作用を構成するための非常に短い方法を説明します。



Railsの構成



まず、RailsとMemcachedの間の相互作用を構成するには、 config / environment / production.rbファイルを編集する必要があります。 キャッシングにDalliを使用するようにRailsに指示する次の行を追加します。

 config.cache_store = :dalli_store
      
      





ActionControllerがキャッシュできるように、同じファイルに別の行を追加します。

 config.action_controller.perform_caching = true
      
      





これで、通常の将来の作業のためにRailsアプリケーションを再起動するときが来ました。



Railsアプリケーションのセットアップ



Memcachedをさらに使用するには、Railsアプリケーションを構成する必要があります。 構成には主に2つの方法があり、それらについては以下で説明します。



キャッシュ管理のためのヘッダー(Cache-Control)の追加


最も簡単な方法は、ヘッダー(Cache-Control)を追加して、アクションの1つにキャッシュを制御することです。 これにより、Rack :: Cacheは、アクションの結果をMemcachedに保存できます。 この場合、 app / controllers / slow_controller.rbのアクションには次が含まれている必要があります。

 def slow_action sleep 15 # todo - print something here end
      
      





次の行を追加して、Rack :: Cacheが結果を5分間保存できるようにすることもできます。

 def slow_action expires_in 5.minutes sleep 15 # todo - print something here end
      
      





これで、このアクションを再度実行すると、作業速度が大幅に向上したことに気付くはずです。 Railsは5分ごとにアクションコードを実行して、Rack :: Cacheを更新します。

Cache-Controlヘッダーは一般公開されます。 特定のユーザーにのみ表示されるアクションがある場合は、 expires_in 5.minutes、public => falseを使用します 。 また、アプリケーションに最適なキャッシュ時間を決定する必要があります。 アプリケーションごとに、この最適な時間は異なる場合があり、経験的に決定する必要があります。



HTTPキャッシングの詳細については、Mark Nottingham のWeb AuthorおよびWebmasters向けキャッシングガイドを参照してください。



Memcachedにオブジェクトを保存する


アクションにリソースを大量に消費する操作がある場合、または何らかの理由で頻繁に作成する必要があるオブジェクトを操作する場合、中間結果をMemcachedに保存するのが合理的です。 アクションに次のコードが含まれているとします:

 def slow_action slow_object = create_slow_object end
      
      





次のように、Memcachedに結果を保存できます。

 def slow_action slow_object = Rails.cache.fetch(:slow_object) do create_slow_object end end
      
      





この場合、RailsはMemcachedからキー「slow_object」を持つオブジェクトを要求します。 オブジェクトが既に存在する場合(以前にメモリに保存されていた場合)、オブジェクトが返されます。 それ以外の場合、ブロックの内容が実行され、結果が「slow_object」に書き込まれます。



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


フラグメントキャッシングは、Railsの機能の1つで、アプリケーションの最も動的な(多くの場合、変化する)部分をキャッシュできます。 ビューの任意の部分をキャッシュブロックにラップすることでキャッシュできます。

 <% # app/views/managers/index.html.erb %> <% cache manager do %> Manager s Direct Reports: <%= render manager.employees %> <% end %> <% # app/views/employees/_employee.html.erb %> <% cache employee do %> Employee Name: <%= employee.name %> <%= render employee.incomplete_tasks %> <% end %> <% # app/views/tasks/_incomplete_tasks.html.erb %> <% cache task do %> Task: <%= task.title %> Due Date: <%= task.due_date %> <% end %>
      
      





このキャッシュ手法は、 ロシアの入れ子人形と呼ばれます。 RailsはこれらのフラグメントをすべてMemcachedにキャッシュします。 モデル名をパラメーターとしてキャッシュメソッド呼び出しに追加したため、 キャッシュ内のこれらのモデルのキーは、モデルが変更されたときにのみ変更されます。 「タスク」モデルを更新する必要がある場合、この問題は特に関連します。

 @task.completed! @task.save!
      
      





したがって、ネストされたオブジェクトキャッシュがあり、Railsはモデルに関連付けられたフラグメントキャッシュの有効期間について何も知りません。 この場合、ActiveRecord タッチキーが役立ちます。

 class Employee < ActiveRecord::Base belongs_to :manager, touch: true end class Task < ActiveRecord::Base belongs_to :employee, touch: true end
      
      





タスクモデルが更新されたので、キャッシュはフラグメントに対して無効になり、 従業員モデルにはフラグメントも更新する必要があることが通知されます。 次に、 EmployeeモデルはManagerモデルに、キャッシュも更新する必要があることを伝えます。 その後、キャッシュの更新プロセスは正常に完了したと見なすことができます。



ロシアのマトリョーシカタイプに類似した別の追加のキャッシュの問題があります。新しいアプリケーションをデプロイするとき、Railsはいつビューを更新するかを知りません。 次のように「タスク」を更新したとします。

 <% # app/views/tasks/_incomplete_tasks.html.erb %> <% cache task do %> Task: <%= task.title %> Due Date: <%= task.due_date %> <p><%= task.notes %></p> <% end %>
      
      





部分テンプレートを使用している場合、Railsはフラグメントキャッシュを更新できません。 以前は、この問題を回避するには、 キャッシュメソッドにバージョン番号を追加する必要がありました。 現在、この問題はcache_digests gemを使用して解決できます。これは、キャッシュキーにMD5ハッシュを自動的に追加します。 部分的なテンプレートを更新してアプリケーションを再起動すると、キャッシュキーも更新され、Railsは新しい世代のビューテンプレートを実行するように強制されます。 また、たとえば、部分的な_incomplete_tasks.html.erbテンプレートが変更れた場合に、すべての依存テンプレートがチェーンで更新されるように、テンプレートファイル間の依存関係を処理する方法も知っています。



この機能はRails 4.0で考慮されていました。 以前のバージョンを使用している場合は、次のコマンドを使用してgemをインストールする必要があります。

 gem install cache_digests
      
      





バンドラーを使用している場合は、gemfileに次の行を追加します。

 gem 'cache_digests'
      
      







高度なRailsとMemcachedのカスタマイズ



Dalli gemは非常に強力なソリューションであり、Memcachedサーバーのクラスター内のキーを操作する機能を提供します。 彼は負荷を分散する方法を知っているため、Memcachedの可能性が高まります。 複数のサーバーがある場合は、各サーバーにMemcachedをインストールし、 config / environment / production.rb構成ファイルに適切な設定を追加できます。

 config.cache_store = :dalli_store, 'web1.example.com', 'web2.example.com', 'web3.example.com'
      
      





この設定により、 一貫したハッシュを使用し 、使用可能なMemcachedサーバー間でキーを配布できます。



All Articles