Summary
The Stack Exchange Redis client for C# is fast and reliable. Unfortunately, it’s difficult to find quality information on the details of this client. In this blog post I’m going to demonstrate how to setup a Redis connection in C# using the Stack Exchange Redis client. This connection technique will reuse connections instead of constantly creating new connections for each thread communicating with the Redis server.
My Test Setup
I’m using Redis for windows, which you can download from here:
https://github.com/ServiceStack/redis-config/tree/master/bin/windows.
I just downloaded a zip copy of the program, then installed it as a service on my PC, using this command (from inside the bin/windows directory of the unzipped redis source):
redis-server --service-install
Notice that there are two minus signs in front of the “service-install” command switch. Then I startup up the windows service manager and clicked on the “Start” button. The windows service name is “redis” (as expected).
The Test Program
I setup a test program consisting of a parallel for loop that will simulate a system that uses asynchronous processes. An example would be a website where each connection would read from Redis to retrieve cached data. Your first step is to use NuGet to install the StackExchange Redis client.
My first connection object looks like this:
public class RedisConnection { private static ConnectionMultiplexer redis; private static IDatabase db; public static IDatabase RedisServerDB { get { if (db == null) { redis = ConnectionMultiplexer.Connect("localhost:6379"); db = redis.GetDatabase(); } return db; } } }
I used a lazy loading scheme to connect to the redis server if the connection is not already created. Then I called this from this code:
static void Main(string[] args) { for (int i = 0; i < 100000; i++) { string[] redisKeyList = new string[] { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" }; Parallel.ForEach(redisKeyList, currentKey => { RedisConnection.RedisServerDB.StringSet(currentKey, "some data to store at this location in redis"); string ignoreMe = RedisConnection.RedisServerDB.StringGet(currentKey); }); } }
Before you run this program, start a command window and use the following netstat command to see the number of concurrent connections:
netstat -n | find "ESTABLISHED" | find "6379"
Now run the program and run the above command in the command window a few times. You’ll see the number of connections increase until there are two per parallel process in progress (one outbound and one inbound connection)
One issue with this method is that IIS will keep connections open for a few seconds before clearing the connection. As web traffic increases, the number of connections will increase and tie up resources on your web server
Many articles explain that Stack Exchange Redis does not have a connection pooling capability. However, there is a work-around for this problem and it’s simple and involves the “Lazy” keyword. Here’s an example of using the lazy load method
public static class RedisConnectionPool { private static Lazy<ConnectionMultiplexer> Connection = new Lazy<ConnectionMultiplexer>( () => ConnectionMultiplexer.Connect("localhost:6379")); public static IDatabase RedisServerDB { get { return Connection.Value.GetDatabase(); } } }
Change the “RedisConnection” calls in the main code above into “RedisConnectionPool” and run the program. Now execute your netstat command and look at the number of connections. There should be 4:
TCP 127.0.0.1:6379 127.0.0.1:51835 ESTABLISHED TCP 127.0.0.1:6379 127.0.0.1:51836 ESTABLISHED TCP 127.0.0.1:51835 127.0.0.1:6379 ESTABLISHED TCP 127.0.0.1:51836 127.0.0.1:6379 ESTABLISHED
Hat tip and more information of this technique, go here:
http://gigi.nullneuron.net/gigilabs/setting-up-a-connection-with-stackexchange-redis/
Where to get the Sample Code
As normal, I have posted the test code used for this blog post on my GitHub account. You can click here to download it.