Connections¶
Connection Pools¶
Both Redis and RedisCluster are backed by a connection
pool that manages the underlying connections to the Redis server(s). coredis connection
pools are blocking and multiplex most kinds of commands over a few connections, while
allocating dedicated connections to blocking commands, pubsub instances, and pipelines.
To explicitly select the type of connection pool used pass in the appropriate class as
coredis.Redis.connection_pool_cls or coredis.RedisCluster.connection_pool_cls.
Pool parameters¶
- Standalone
- Cluster
Connection limits¶
Connection pools will only allow up to max_connections`
connections to be running concurrently, and if more are requested the command will block until one becomes
available. Since most commands can be multiplexed over a few connections this is rare
in practice unless you’re using many pipelines/blocking commands/pubsubs simultaneously.
In the following example, a client is created with max_connections set to 8,
however 10 blocking requests are concurrently started. This means 2 requests will
block and only start after 2 other requests complete. In terms of wall clock time this means
all requests will complete in 6 seconds:
import asyncio
import coredis
async def test():
client = coredis.Redis(max_connections=8)
# or with cluster
# client = coredis.RedisCluster(
# "localhost", 7000,
# max_connections=8, max_connections_per_node=True
# )
async with client:
results = await asyncio.gather(
*[client.blpop(["fubar"], 3) for _ in range(10)],
)
asyncio.run(test())
Changing max_connections to 10 will result in all requests starting immediately
Timeouts¶
Connection pools can be created with an optional blocking timeout
parameter that will control how long to wait for an available connection before raising an TimeoutError.
Important
To configure the timeout when using an implicit connection pool owned by the Redis or
RedisCluster clients, use the pool_timeout argument.
Reusing the previous example with a low timeout will result in the 2 blocked requests actually failing
before they can even get a chance to send the request to redis:
import asyncio
import coredis
async def test():
client = coredis.Redis(max_connections=8, pool_timeout=1)
async with client:
result = await asyncio.gather(
*[client.blpop(["fubar"], 3) for _ in range(10)],
)
asyncio.run(test())
Connection types¶
coredis ships with three types of connections.
The default,
coredis.connection.TCPConnection, is a normal TCP socket-based connection.UnixDomainSocketConnectionallows for clients running on the same device as the server to connect via a Unix domain socket. To use aUnixDomainSocketConnectionconnection, simply pass theunix_socket_pathargument, which is a string to the unix domain socket file.Additionally, make sure the parameter is defined in your redis.conf file. It’s commented out by default.
r = coredis.Redis(unix_socket_path='/tmp/redis.sock')
ClusterConnectionconnection which is essentially justConnectionwith the exception of ensuring appropriateREADONLYhandling is set if configured (coredis.RedisCluster.readonly)
Custom connection classes¶
You can create your own connection subclasses by deriving from
BaseConnection as well. This may be useful if
you want to control the socket behavior within an async framework. To
instantiate a client class using your own connection, you need to create
a connection pool, passing your class to the connection_class argument.
Other keyword parameters you pass to the pool will be passed to the class
specified during initialization.
pool = coredis.pool.ConnectionPool(connection_class=YourConnectionClass, ...)