I am always “playing around with new addons”:http://blog.nofail.de/2010/07/mongo-ruby-driver-mongoid-and-mongomapper/ offered by Heroku. My latest discovery was the “Redis addon”:http://addons.heroku.com/redistogo that is provided by “Redistogo”:http://redistogo.com/. The addon is probably in private beta (“docs”:http://docs-beta.heroku.com/redistogo are still on beta), but since they put up a link to it on their site, I managed to install it to my “personal website”:http://www.phoet.de that runs in the cloud.
“Redis”:http://code.google.com/p/redis/ is “an advanced key-value store” and has some features that make it a perfect match for a cache! I use caching extensively on my site and keep on “trying out new ways to do it”:http://blog.nofail.de/2010/02/simple-db-caching-for-heroku/ to circumvent Heroku’s readonly filesystem.
Like “Memcache”:http://memcached.org/, Redis provides the ability to set a time to live (ttl) on a key. This comes in handy, if you have data that expires in a short period of time, like 3rd party data from Twitter etc.
h2. Caching with Redis
Accessing Redis is very simple, since it is a text based protocol. The “command reference”:http://code.google.com/p/redis/wiki/CommandReference is straight forward and there is a “simple Ruby wrapper”:http://github.com/ezmobius/redis-rb/ available:
require "redis"
redis = Redis.new
redis.set "foo", "bar"
# => "OK"
redis.get "foo"
# => "bar"
The “redis-store gem”:http://github.com/jodosha/redis-store already provides a Rails 3 compatible Cache Store implementation, but I needed some more configuration points, especially the ttl.
That’s why I wrote my own “Rails 3 Redis Cache”:http://github.com/phoet/rails_redis_cache, also a great way to get used to the way of working with Redis and the Redistogo addon.
h2. Using Rails Redis Cache
There is some configuration needed for Rails to pick up the new cache store. If you want to use different or no caching for test, development and production, you should put the config in your environment files:
# config/environemnts/production.rb
config.action_controller.perform_caching = true
config.cache_store = ActiveSupport::Cache::RailsRedisCache.new(:url => ENV['REDISTOGO_URL'])
If there is a Redis server available in all environments, you can put it in your environment file:
# config/environment.rb
ActionController::Base.cache_store = ActiveSupport::Cache::RailsRedisCache.new(:url => ENV['REDISTOGO_URL'])
The caching parts are mostly in my controllers:
@tweets = cache("tweets", :expires_in => 30.seconds){ Twitter::Search.new(...) }
The store is using the “basic Rails cache store implementation”:http://github.com/rails/rails/blob/v3.0.0.beta1/activesupport/lib/active_support/cache.rb#L104 which is broken in the Rails 3.0.0.beta1 version that runs on Heroku, so “I added a monkey-patch”:http://github.com/phoet/basement/blob/master/config/rails_cache_fix.rb for that using edge Rails.
h2. Redis on localhost
Installing and running Redis on Mac OS X is really simple:
brew install redis
redis-server
There is also a commandline client available for direct access:
redis-cli
redis> set "foo" "bar"
OK
redis> get "foo"
"bar"
It’s key value stores, stupid!
Disclosure – I work at Garantia Data, makers of the Redis Cloud managed service.
Just wanted to mention that we also provide a managed “Redis service”:http://redis-cloud.com as a “Heroku add on”:https://addons.heroku.com/rediscloud. Our service has several advantages over Redis To Go, including self scaling, instant backups, no “noisy neighbors”, and pay-per-use according to actual database size.