In this page listing the redis clients, I counted 8 asynchronous libraries. My understanding is that frameworks like as node.js or tornado only make sense when the asynchronous callback functions are not fighting with each other for I/O, otherwise you might as well go synchronous.
But Redis is single-threaded. So they are actually fighting for I/O. Doesn't the single-threaded nature of Redis cancel all the potential benefits of asynchronous callbacks? Why does it make sense to use asynchronous clients with Redis?
Redis uses asynchronous replication, with asynchronous replica-to-master acknowledges of the amount of data processed. A master can have multiple replicas.
Redis, an in-memory database that stores data in the server memory, is a popular tool to cache data. You can connect to Redis in Node. js using the node-redis module, which gives you methods to retrieve and store data in Redis.
The single-threaded nature of Redis is irrelevant regarding the potential benefits of an asynchronous client. Despite its unique event loop, Redis is able to concurrently manage a good number of client connections. I have seen benchmarks with up to 30000 connections on a single Redis instance.
Just consider that with in-memory key/value stores like Redis or memcached, the performance and latencies are dominated by the network roundtrips rather than server-side CPU consumption. Granted, the latency of network roundtrips increases when the network links are saturated, but it does not mean it becomes negligible when the network is far from saturation. For instance, on a very lightly loaded 1 GbE network, it is not uncommon to see the RTT latency close to 200 us.
The consequence is, except when the network links are close to saturation, client connections (or asynchronous callback functions) are rarely competing with each other for I/Os. Sockets are associated to buffers which amortize the cost of read and write operations on the network. Most of the time, the wait states are not due to I/O competition, but to the latency of the network.
There are various ways to decrease the impact of network latency:
pipelining: grouping multiple commands together so that network roundtrips are payed once per group of commands (actually, this is synchronous pipelining).
non blocking I/Os: while it does not reduce the number of roundtrips (or their individual cost), an asynchronous client can manage them concurrently. The consequence is the network latency has less (or no) impact on the application throughput.
multiple client connections: each client connection has its own socket, and therefore its own buffer. More buffers often means better throughput. More connections increases the opportunity to process things concurrently and/or asynchronously, with positive impacts on the overall performance.
These solutions are all supported by the Redis ecosystem, and can be combined to maximize the performance. Asynchronous clients typically allows this kind of combinations. What are the use cases of an asynchronous client? Here are a few examples:
implementing asynchronous pipelining, to minimize the wait states on a single connection.
integrating Redis connection(s) with an existing event loop (such as libevent, Node.js, Tornado, Twisted, etc ...) without relying on an extra thread pool.
supporting data sharding with multiple Redis instances. In that case, the client application will probably want to parallelize the accesses to the various instances. With an asynchronous client, it can be conveniently done from a unique thread.
supporting the HA resiliency models based on the pre-connection of the client application to the various master/slaves instances.
Event loops, asynchronous libraries, and/or coroutine-like mechanisms are one of the corner stones of a majority of the efficient NoSQL engines out there.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With