I want to use redis cache store (using redis-store gem).
It works fine locally but when going on production where Passenger forks multiple instances of Rails workers we’re getting Redis errors which indicate synchronization problems between the different instances regarding Redis access.
An example for such an error is
Got '7' as initial reply byte. If you're running in a multi-threaded environment, make sure you pass the :thread_safe option when initializing the connection. If you're in a forking environment, such as Unicorn, you need to connect to Redis after forking.
redis (2.2.2) lib/redis/connection/ruby.rb:78:in `format_reply'
I have done some reading and learned that each Passenger worker instance must create its own Redis connection. This might be implemented using the following code
#config/initializers/redis_fork_init.rb
if defined?(PhusionPassenger)
PhusionPassenger.on_event(:starting_worker_process) do |forked|
if forked
$redis = Redis.new
end
end
end
Assuming Redis access is done through $redis all over the code – this solution is great.
My question is – how can I create a new Redis connection that will be used when I do Rails.cache operations such as read, write etc… ?
my config/environments/production.rb includes the following:
config.cache_store = :redis_store, { :host => 'localhost', :port => 6379, :thread_safe => true }
Using Rails 3.2.3, Redis 2.2.2, redis-store 1.1.1, Passenger 3.0
Take a look on reconnect method of redis store:
https://github.com/jodosha/redis-store/blob/master/redis-activesupport/lib/active_support/cache/redis_store.rb
So basically your fork block should look like: