Connection per Thread vs single connection to Redis server

1,455 views
Skip to first unread message

Mikhail Mikheev

unread,
May 27, 2011, 11:06:02 AM5/27/11
to Redis DB
I've evaluated two C# Redis clients (Sider and Booksleeve) and found
that except other discrepancies they have different implementation of
socket utilization logic:
- one of them uses connection pool and creates a connection per
thread.
- another uses single TCP connection with blocking queue (single
consumet and a number of producers) from which only one separated
thread reads and sends commands to Redis and any other threads are
only allowed to enqueue commands. So there is always only one active
connection but there is thread synchronization overhead required for
blocking queue.

After reading a few discussions here on Redis DB group I've realized
that having a lot of TCP connections to Redis server is generally not
a good idea. In my situation if I used a connection per thread
approach it is more likely that under highest load there would be
about 1200 connections Redis instance. (In detail, there would be 12
servers with client application each running about 100 threads and 8
instances of Redis process on each of the same servers so it would be
actually about 1200*8 connections per physical server and 1200 per
Redis process regardless some of them would be through loopback
adapter as client and Redis are on the same server). At moderate load
much less number of threads is expected, say about 10

So here are the questions: which approach is better in general and
particularly for my situation?
If someone has experience with it what is the connection limit to a
single Redis process (and physical server running on Windows) after
which it is worth to restrict the number of connections?

Thanks in advance!

Mikhail Mikheev

unread,
May 27, 2011, 11:14:48 AM5/27/11
to Redis DB
Guys, if anyone know how hiredis does that stuff please write a few
word about it it will save me an hour or two from investigating its
source code as i'm also interested how that client deals with TCP
connections.

Thanks!

Didier Spezia

unread,
May 27, 2011, 2:24:40 PM5/27/11
to Redis DB
Hi,

IMO, there is no better approach in general. It is a tradeoff
between latency and scalability.

One connection per thread (or a pool of connections) will usually
provide the best latencies, but past a given number of connections,
it will not scale. I think this limit is much higher than 1200
connections though. Redis is able to support thousands of
connections thanks to epoll/kqueue usage.

Using a thread to multiplex Redis I/Os will be a bit slower (more
context switches, more synchronization required, more kernel
scheduler activity), but it will scale more if you have enough
processes. Also it offers some possibilities for deduplication
(if two processes get the same key at the same time, the
multiplexer thread can optimize away one of the operations).

IMO the choice depends on how active you client threads will
be regarding Redis accesses. If the Redis activity is moderate
then the multiplexer implementation looks fine. It the activity
is high, a 1->100 ratio sounds a bit high, and a connection
per thread model will be better.

Regards,
Didier.

Didier Spezia

unread,
May 27, 2011, 2:27:10 PM5/27/11
to Redis DB

Hiredis is a low level library, there is no connection pooling
or thread-based multiplexing strategy implemented. However, you
can certainly build them using the provided features (async API
for instance).

Regards,
Didier.

Marc Gravell

unread,
May 31, 2011, 7:54:07 AM5/31/11
to Redis DB
As a side-note, one of the other considerations in Booksleeve is that
it is inherently designed to be async throughout. Using a connection
per thread would be troublesome when the work is already being bounced
between threads (so the UI can get on with doing UI-related things,
rather than waiting on redis). The time acquiring any locks is to all
intents and purposes *nothing* compared to any time spent on network
operations - barely measurable, but if you think this is significant I
suspect it could be reformulated using a chain of pending messages and
some "interlocked" love to enqueue/dequeue (rather than a full lock).
I might look into that at some point. But to emphasise - the main
focus is to provide a fully pipelined API, allowing you to send any
number of requests (from any number of threads), and do what you
choose with the completions:

- have them call-back on a worker when convenient
- block on the result
- ignore the result completely

Additionally, you can of course have more than one client object
(there is one connection per client) with any basic or sophisticated
pooling you choose.

Marc Gravell
(Booksleeve)
Reply all
Reply to author
Forward
0 new messages