In this fifth part of a six-part article series on optimizing the performance of a Ruby on Rails program, you'll learn how to use memcached to cache and store data. This article is excerpted from chapter 13 of the book Practical Rails Projects, written by Eldon Alameda (Apress; ISBN: 1590597818).
Memcached and Performance Optimization - Storing Sessions with Memcached (Page 2 of 2 )
In Rails, you can use memcached for both caching and storing session data. The reason it would be a good idea to store sessions on memcached, too, is that the data is in a container that can be accessed through a network, in case you later scale the application horizontally by adding new servers. The default session store is file system, which makes scaling possible (using a networked file system), but certainly harder and not as efficient as with memcached.
Making Rails use memcached for storing sessions is another one-liner. Just add the following toconfig/environment/production.rb:
Other options for storing the session data are:active_record_store,:drb_store, and:memory_store, corresponding to the fragment cache store options described previously.
Caching ActiveRecord Objects
While the standard Rails caching mechanisms are useful in many ways, they have their limitations. Page and action caching in particular aren’t very useful in applications where the user is shown personalized and highly dynamic content. Fragment caching can be used in many of these cases, but it’s kind of cumbersome, and many feel it’s done in the wrong place—on the view level.
To address this in a real-world situation, The Robot Co-op has developed and released another library,cached_model.cached_modelcreates a new subclass ofActiveRecord::Base, which automatically caches the model in memcached.
In our application, an obvious model to cache isBook. Another one would be the shopping cart, but we already took care of it with fragment caching.
As usual, installing thecached_modelgem is simple:
cached_modelusesmemcache-client, a replacement client forruby-memcache. It should be a drop-in replacement and compatible with fragment caching in Rails. However, as of this writing, there were some compatibility issues, so we’ll keep the old library around as well.
Now restart the application server and make sure that everything is still working with the new setup.
Next, we need to make our application use the new gem. Add the following toconfig/ environments/production.rb:
In order to make other environments work withCachedModel, you need to add the preceding lines to all used environments inconfig/environments. Be sure to give them a different namespace name, though, so that the caches won’t clash.
Now all we need to do to make theBook model cached is to change the first line inapp/models/book.rb, and make the class inherit fromCachedModel instead ofActiveRecord::Base:
class Book < CachedModel acts_as_taggable ...
If you now restart the application server and load a book page a couple times in the browser, you should see (if you’re still running the memcached server in the foreground) that the book object is stored in memcached on the first request and fetched from there on the subsequent page loads:
<10 new client connection <10 get emporium_production:active_record:Book:15 >10 END <10 set emporium_production:active_record:Book:15 1 900 193 >10 STORED <8 get emporium.com:3000/cart/show/107 >8 sending key emporium.com:3000/cart/show/107 >8 END <10 get emporium_production:active_record:Book:15 >10 sending key emporium_production:active_record:Book:15 >10 END
On the second line, memcached checks whether book number 15 exists in the cache. It doesn’t, so on the fourth line, it caches the object and confirms this by outputtingSTORED. When the page is requested again, the book (as well as the shopping cart fragment) is found from the cache.
cached_modelexpires the cached model objects automatically every 15 minutes (you can adjust this by settingCachedModel.ttl). Since it’s tightly integrated with ActiveRecord, expiring objects when they are updated is taken care of automatically.
Tip For more information aboutcached_modeland how to usememcache-clientdirectly to cache arbitrary things like collections of objects (cached_modeldoesn’t help if you usefind(:all), for example), read Geoffrey Grosenbach’s excellent tutorial “memcached Basics for Rails” athttp://nubyonrails.com/ articles/2006/08/17/memcached-basics-for-rails.
Please check back for the conclusion to this series.
DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware.