ruby on rails, single global connection or per request?

2,269 views
Skip to first unread message

S Ahmed

unread,
Apr 13, 2011, 11:19:02 PM4/13/11
to redi...@googlegroups.com
What is the best practice in terms of making a connection to redis, is it to create a connection per request or do it somewhere else globally?

I'm guessing creating it per request is the right way to do things.

Bryce Baril

unread,
Apr 13, 2011, 11:41:12 PM4/13/11
to redi...@googlegroups.com, S Ahmed
I've always found the connection takes on the order of at least 10x as
long as a request. It wasn't with Ruby, but I doubt it matters. Our
best results were keep a global connection per process and always
assume it is connected. If the read fails, then you reconnect and try
again.

-Bryce

> --
> You received this message because you are subscribed to the Google Groups
> "Redis DB" group.
> To post to this group, send email to redi...@googlegroups.com.
> To unsubscribe from this group, send email to
> redis-db+u...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/redis-db?hl=en.
>

deepthawtz

unread,
Apr 15, 2011, 4:43:36 PM4/15/11
to Redis DB
What I've done in the past is add a redis.rb in config/initializers
that looks like this:

# redis.rb
REDIS_CONFIG = YAML.load(File.read(File.dirname(__FILE__) + "/
redis.yml")).symbolize_keys
$redis = Redis.new(REDIS_CONFIG)

# redis.yml
hostname: localhost # or wherever

So a global $redis connection is available to the entire application.

If a single connection is not enough, and you are using Ruby 1.9, and
are comfortable
with evented style code you might want to look at https://github.com/igrigorik/em-synchrony
for creating a Redis connection pool.

S Ahmed

unread,
May 22, 2011, 2:03:49 PM5/22/11
to redi...@googlegroups.com
So to recap (I'm finally at a point where I am adding redis to my app):

I googled around and I often find people saying to create a single connection in an initializer.

This just doesn't sit well with me for some reason.

Not all my web requests will need a connection to redis.

Does it make sense to make a single connection like this?

How expensive of a call is this?

I was thinking, if the current request needs to connect to redis, it opens the connection, and any subsequent redis command would re-use this open connection (or open it if it is closed).

How would I go about doing something like this?  OR, if its a bad idea, please tell me why?

thanks!

syrnick

unread,
May 22, 2011, 2:15:54 PM5/22/11
to redi...@googlegroups.com
It's a lazy connection, so it won't actually connect to redis until you try to do something. It basically does exactly what you want.

A word of caution. Be careful with timeouts. If you use timeout blocks, make sure to reset the global redis connection, because subsequent calls via the same connection may have weird state.

Alex

S Ahmed

unread,
May 22, 2011, 2:19:38 PM5/22/11
to redi...@googlegroups.com
Is this the case then, that if my site is being hit with say 1K request per second, they will all be sharing the same global connection?

Well I am using Phussion passenger, which will create different pools of rails servers so I guess I will have mutiple application servers and thus multiple global connectsion per rails app server.



--

syrnick

unread,
May 22, 2011, 6:16:17 PM5/22/11
to redi...@googlegroups.com
I don't know what exactly passenger does. If ruby workers are forked, you'll have separate connection per fork (if you somehow use the connection before forking, make sure to close it). 

Alex

Ezra Zygmuntowicz

unread,
May 23, 2011, 1:25:20 AM5/23/11
to redi...@googlegroups.com

On May 22, 2011, at 11:19 AM, S Ahmed wrote:

> Is this the case then, that if my site is being hit with say 1K request per second, they will all be sharing the same global connection?
>
> Well I am using Phussion passenger, which will create different pools of rails servers so I guess I will have mutiple application servers and thus multiple global connectsion per rails app server.


If you are using passenger then you will end up with 1 redfis connection per forked child. But you need to take care to make sure the forked childrten *do not* share or inherit the redis connection from the main parent. This means you need to use one of the passenger sp[ecial 'hooks' that let you perform code *after* the child is forked.

if defined?(PhusionPassenger)
PhusionPassenger.on_event(:starting_worker_process) do |forked|
$redis = Redis.new :thread_safe => true, etc...
end
end


Put that somewhere in one of your initializers and it will fire only after the passenger child worker is forked and therefor will not share $redis file descriptors between children.


Cheers-
Ezra Zygmuntowicz
ezmo...@gmail.com

S Ahmed

unread,
May 23, 2011, 8:07:25 PM5/23/11
to redi...@googlegroups.com
How can I test to see if it is indeed sharing/inheriting from the main parent connection?

syrnick

unread,
May 24, 2011, 1:03:50 PM5/24/11
to redi...@googlegroups.com
Option 1: look at the #connections in redis-cli info.
Option 2: Write an ~ 10-second for loop in the page /hit_redis_hard and hit the web server with many requests to that URL. If it works, you have separate connections :)

Alex

S Ahmed

unread,
Jun 6, 2011, 10:30:50 PM6/6/11
to redi...@googlegroups.com
When using the ruby redis client, another issue came up that I need some clarifications on.

The client connects to redis, how do you jump between different redis databases?  

I'm still a little confused as to the global connection, will changing databases effect other requests if they come in at the same time?



--
Reply all
Reply to author
Forward
0 new messages