Redis Cache Store is a new feature on Rails 5.2 although support for caching in Rails has been around for some time. A few cache stores already exist like MemCacheStore, FileStore, and MemoryStore. You can also use a custom store so no doubt some people are already using Redis as a cache store.
The new feature on Rails 5.2 is the built-in Redis Cache Store. You don’t need to use a custom cache store anymore. All you need is to add a Redis client gem.
This post has the following sections:
Caching in Rails
Redis Cache Store
Multiple Redis Servers
Redis in Development
Deploying in Production
Key Value Store
Feedback
Caching in Rails
Let’s review how caching in Rails works. Rails
<% @messages.each do |message| %>
<% cache message do %>
<%= render message %>
<% end %>
<% end %>
This is typical view code. We iterate @messages
cache message
render
Redis Cache Store
To use Redis Cache Store, put this config/environments/production.rb
config/environments/development.rb
config.cache_store = :redis_cache_store
This uses Redis running on localhost on port 6379. This is mostly
config.cache_store = :redis_cache_store, {url: 'redis://192.168.0.10:6379/0'}
In this example, all Rails servers should have access to port 6379 192.168.0.10
You also have to install redis
gem 'redis', '~> 4.0'
When trying this on your development environment, you should also have
config.action_controller.perform_caching = true
Hiredis
Aside from redis
driver
as one of the options
config.cache_store = :redis_cache_store, {driver: :hiredis, url: 'redis://192.168.0.10:6379/0'}
You also need to hiredis
gem 'hiredis'
gem 'redis', '~> 4.0'
Note that you need to add hiredis
redis
require
gem 'redis', '~> 4.0', :require => ['redis', 'redis/connection/hiredis']
redis/connection/hiredis
Multiple Redis Servers
You can use multiple Redis servers for
To specify multiple servers, pass url
redis_servers = %w[
redis://hostname-1:6379/0
redis://hostname-2:6379/0
redis://hostname-3:6379/0
redis://hostname-4:6379/0
]
config.cache_store = :redis_cache_store, {driver: :hiredis, url: redis_servers}
By specifying multiple servers, Redis::Distributed
is used, which is part of redis
Redis in Development
You can use the package manager of your OS to install Redis. If you’re using Homebrew on MacOS, you can run
brew install redis
You can also use Docker on any OS which proves to be convenient when testing multiple Redis servers.
docker run --rm -p 6379:6379 redis
To run multiple Redis processes, you can run the same command using different ports
docker run --rm -p 6379:6379 redis
docker run --rm -p 6380:6379 redis
docker run --rm -p 6381:6379 redis
development.rb
redis_servers = %w[
redis://localhost:6379/0
redis://localhost:6380/0
redis://localhost:6381/0
]
config.cache_store = :redis_cache_store, {driver: :hiredis, url: redis_servers}
Deploying in Production
It is recommended to use a dedicated Redis server for cache purposes. If you’re already using Redis in your application, you should get a separate server or start a second Redis process.
Redis Cache Store is fault tolerant so even if you only have a single Redis server, your app won’t go down if Redis goes down. It is important to make sure your app will be responsive during this time of cache misses. To avoid this problem, use multiple Redis servers. You would still have cache misses for some keys but they will be less than if you only have one server.
If you need advice on your Redis setup in production, please contact us here at Engine Yard. We have experience supporting Redis and Rails in production.
Key Value Store
Redis is a key-value store. In the context of the Redis Cache Store, keys are unique identifiers that are generated by Rails. The values are the cache entries. You don’t need to know these to use the Redis Cache Store but it would be good to have an idea about how it works under the hood.
Here’s a sample key that Rails used with the fragment caching above.
views/messages/index:51aef83ac5cf0aaa40efdd8640257171/messages/1
You can see the name of the views/messages/index
51aef83ac5cf0aaa40efdd8640257171
1
You can check the keys on the Rails console.
pp Rails.cache.redis.keys
['views/messages/index:51aef83ac5cf0aaa40efdd8640257171/messages/10',
'views/messages/index:51aef83ac5cf0aaa40efdd8640257171/messages/7',
'views/messages/index:51aef83ac5cf0aaa40efdd8640257171/messages/1',
'views/messages/index:51aef83ac5cf0aaa40efdd8640257171/messages/6',
'views/messages/index:51aef83ac5cf0aaa40efdd8640257171/messages/2',
'views/messages/index:51aef83ac5cf0aaa40efdd8640257171/messages/8',
'views/messages/index:51aef83ac5cf0aaa40efdd8640257171/messages/5',
'views/messages/index:51aef83ac5cf0aaa40efdd8640257171/messages/3',
'views/messages/index:51aef83ac5cf0aaa40efdd8640257171/messages/11',
'views/messages/index:51aef83ac5cf0aaa40efdd8640257171/messages/4',
'views/messages/index:51aef83ac5cf0aaa40efdd8640257171/messages/9']
You’ll get the same output when using the redis-cli
tool,
$ redis-cli
127.0.0.1:6379> keys *
1) 'views/messages/index:51aef83ac5cf0aaa40efdd8640257171/messages/10'
2) 'views/messages/index:51aef83ac5cf0aaa40efdd8640257171/messages/7'
3) 'views/messages/index:51aef83ac5cf0aaa40efdd8640257171/messages/1'
4) 'views/messages/index:51aef83ac5cf0aaa40efdd8640257171/messages/6'
5) 'views/messages/index:51aef83ac5cf0aaa40efdd8640257171/messages/2'
6) 'views/messages/index:51aef83ac5cf0aaa40efdd8640257171/messages/8'
7) 'views/messages/index:51aef83ac5cf0aaa40efdd8640257171/messages/5'
8) 'views/messages/index:51aef83ac5cf0aaa40efdd8640257171/messages/3'
9) 'views/messages/index:51aef83ac5cf0aaa40efdd8640257171/messages/11'
10) 'views/messages/index:51aef83ac5cf0aaa40efdd8640257171/messages/4'
11) 'views/messages/index:51aef83ac5cf0aaa40efdd8640257171/messages/9'
To check the values, you can also use the Rails console redis-cli
Rails.cache.fetch 'views/messages/index:51aef83ac5cf0aaa40efdd8640257171/messages/1'
=> ' <li>Test 1</li>\n\n'
127.0.0.1:6379> get views/messages/index:51aef83ac5cf0aaa40efdd8640257171/messages/1
'\x04\bo: ActiveSupport::Cache::Entry\t:\x0b@valueI\'\x1a <li>Test 1</li>\n\n\x06:\x06ET:\r@versionI\'\x1920171218054020526607\x06;\aT:\x10@created_atf\x151517986248.75312:\x10@expires_in0'
You can see from
Feedback
Are you using Rails caching and thinking of trying out the Redis Cache Store? Let us know if have any questions or feedback.