BookSleeve (project site, author blog post) provides a native async Redis client for .NET with effortless multiplex support, as an alternative to the famous ServiceStack.Redis.
In BookSleeve Redis commands are always pipelined and handled by async tasks. One single BookSleeve connection can handle numerous commands in one go. For example,
1 2 3 4 |
var connection = _balancer.GetConnection(); var task1 = connection.Strings.Set(_db, "key1", "value1"); var task2 = connection.Strings.Set(_db, "key2", "value2"); var task3 = connection.Strings.Set(_db, "key3", "value3"); |
In this example, the three commands to set three keys with a single connection are multiplexed and put into a single pipeline to execute on the Redis server. The tasks end when the commands complete.
Without pipelining, on Redis these commands are individual requests. Each request has to wait for the response to come back and they incur a round trip each time to the Redis server.
1 2 3 4 5 6 |
client: SET "key1" "value1" server: ok client: SET "key2" "value2" server: ok client: SET "key3" "value3" server: ok |
With pipelining, these commands are grouped together as one request and sent to Redis in one go. So the network wait time is much less than the previous scenario by cutting 2/3 of the network round trip wait time.
1 2 3 4 5 6 |
client: SET "key1" "value1" client: SET "key2" "value2" client: SET "key3" "value3" server: ok server: ok server: ok |
If a separate method executes different Redis commands with the same connection simultaneously,
1 2 3 4 5 6 |
var connection = _balancer.GetConnection(); var resultTask1 = connection.Strings.GetString(_db, "key6"); var resultTask2 = connection.Strings.GetString(_db, "key9"); var result1 = await resultTask1; var result2 = await resultTask2; |
All the commands are then multiplexed together and executed on Redis in one of several possibilities of execution order,
1 2 3 4 5 6 7 8 9 10 |
client: SET "key1" "value1" client: SET "key2" "value2" client: GET "key7" client: SET "key3" "value3" client: GET "key9" server: ok server: ok server: "value7" server: ok server: "value9" |
In this scenario, the network wait time is cut by 4/5 of requests being sent individually, with a slight bigger request sent to the Redis server in one go.
On .NET side, since BookSleeve’s connection is always async and returns tasks, the caller can await the tasks to get the actual results, while the tasks are executed without blocking each other. Commands from different method calls and different threads can be multiplexed together and sent to Redis in one request. Above all, this approach should improve Redis performance by cutting the round trip time of individual requests with less connections to Redis.