Skip to content

Commit 553deca

Browse files
Merge pull request #728 from redis/DOC-4340-conn-pool-align
DOC-4340 more detail about connection pools and multiplexing
2 parents 812723f + ce150c1 commit 553deca

File tree

9 files changed

+539
-35
lines changed

9 files changed

+539
-35
lines changed

content/develop/connect/clients/dotnet.md

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ dotnet add package NRedisStack
3737

3838
Connect to localhost on port 6379.
3939

40-
```
40+
```csharp
4141
using NRedisStack;
4242
using NRedisStack.RedisStackCommands;
4343
using StackExchange.Redis;
@@ -70,7 +70,7 @@ Console.WriteLine(String.Join("; ", hashFields));
7070
// name: John; surname: Smith; company: Redis; age: 29
7171
```
7272

73-
To access Redis Stack capabilities, you should use appropriate interface like this:
73+
To access Redis Stack capabilities, use the appropriate interface like this:
7474

7575
```
7676
IBloomCommands bf = db.BF();
@@ -84,7 +84,7 @@ IJsonCommands json = db.JSON();
8484
ITimeSeriesCommands ts = db.TS();
8585
```
8686

87-
### Connect to a Redis cluster
87+
## Connect to a Redis cluster
8888

8989
To connect to a Redis cluster, you just need to specify one or all cluster endpoints in the client configuration:
9090

@@ -106,7 +106,7 @@ db.StringSet("foo", "bar");
106106
Console.WriteLine(db.StringGet("foo")); // prints bar
107107
```
108108

109-
### Connect to your production Redis with TLS
109+
## Connect to your production Redis with TLS
110110

111111
When you deploy your application, use TLS and follow the [Redis security]({{< relref "/operate/oss_and_stack/management/security/" >}}) guidelines.
112112

@@ -169,6 +169,23 @@ conn.StringSet("foo", "bar");
169169
Console.WriteLine(conn.StringGet("foo"));
170170
```
171171

172+
## Multiplexing
173+
174+
Although example code typically works with a single connection,
175+
real-world code often uses multiple connections at the same time.
176+
Opening and closing connections repeatedly is inefficient, so it is best
177+
to manage open connections carefully to avoid this.
178+
179+
Several other
180+
Redis client libraries use *connection pools* to reuse a set of open
181+
connections efficiently. NRedisStack uses a different approach called
182+
*multiplexing*, which sends all client commands and responses over a
183+
single connection. NRedisStack manages multiplexing for you automatically.
184+
This gives high performance without requiring any extra coding.
185+
See
186+
[Connection pools and multiplexing]({{< relref "/develop/connect/clients/pools-and-muxing" >}})
187+
for more information.
188+
172189
## Example: Indexing and querying JSON documents
173190

174191
This example shows how to convert Redis search results to JSON format using `NRedisStack`.

content/develop/connect/clients/java/jedis.md

Lines changed: 72 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -56,46 +56,36 @@ To include `Jedis` as a dependency in your application, edit the dependency file
5656

5757
## Connect
5858

59-
For many applications, it's best to use a connection pool. You can instantiate and use a `Jedis` connection pool like so:
59+
The following code opens a basic connection to a local Redis server:
6060

6161
```java
6262
package org.example;
63-
import redis.clients.jedis.Jedis;
64-
import redis.clients.jedis.JedisPool;
63+
import redis.clients.jedis.UnifiedJedis;
6564

6665
public class Main {
6766
public static void main(String[] args) {
68-
JedisPool pool = new JedisPool("localhost", 6379);
67+
UnifiedJedis jedis = new UnifiedJedis("redis://localhost:6379");
6968

70-
try (Jedis jedis = pool.getResource()) {
71-
// Store & Retrieve a simple string
72-
jedis.set("foo", "bar");
73-
System.out.println(jedis.get("foo")); // prints bar
74-
75-
// Store & Retrieve a HashMap
76-
Map<String, String> hash = new HashMap<>();;
77-
hash.put("name", "John");
78-
hash.put("surname", "Smith");
79-
hash.put("company", "Redis");
80-
hash.put("age", "29");
81-
jedis.hset("user-session:123", hash);
82-
System.out.println(jedis.hgetAll("user-session:123"));
83-
// Prints: {name=John, surname=Smith, company=Redis, age=29}
84-
}
69+
// Code that interacts with Redis...
70+
71+
jedis.close();
8572
}
8673
}
8774
```
8875

89-
Because adding a `try-with-resources` block for each command can be cumbersome, consider using `JedisPooled` as an easier way to pool connections.
76+
After you have connected, you can check the connection by storing and
77+
retrieving a simple string value:
9078

9179
```java
92-
import redis.clients.jedis.JedisPooled;
80+
...
9381

94-
//...
82+
String res1 = jedis.set("bike:1", "Deimos");
83+
System.out.println(res1); // OK
9584

96-
JedisPooled jedis = new JedisPooled("localhost", 6379);
97-
jedis.set("foo", "bar");
98-
System.out.println(jedis.get("foo")); // prints "bar"
85+
String res2 = jedis.get("bike:1");
86+
System.out.println(res2); // Deimos
87+
88+
...
9989
```
10090

10191
### Connect to a Redis cluster
@@ -313,15 +303,61 @@ The client will also flush the cache automatically
313303
if any connection (including one from a connection pool)
314304
is disconnected.
315305

316-
## Production usage
306+
## Connect with a connection pool
317307

318-
The following sections explain how to handle situations that may occur
319-
in your production environment.
308+
For production usage, you should use a connection pool to manage
309+
connections rather than opening and closing connections individually.
310+
A connection pool maintains several open connections and reuses them
311+
efficiently. When you open a connection from a pool, the pool allocates
312+
one of its open connections. When you subsequently close the same connection,
313+
it is not actually closed but simply returned to the pool for reuse.
314+
This avoids the overhead of repeated connecting and disconnecting.
315+
See
316+
[Connection pools and multiplexing]({{< relref "/develop/connect/clients/pools-and-muxing" >}})
317+
for more information.
318+
319+
Use the following code to connect with a connection pool:
320+
321+
```java
322+
package org.example;
323+
import redis.clients.jedis.Jedis;
324+
import redis.clients.jedis.JedisPool;
325+
326+
public class Main {
327+
public static void main(String[] args) {
328+
JedisPool pool = new JedisPool("localhost", 6379);
329+
330+
try (Jedis jedis = pool.getResource()) {
331+
// Store & Retrieve a simple string
332+
jedis.set("foo", "bar");
333+
System.out.println(jedis.get("foo")); // prints bar
334+
335+
// Store & Retrieve a HashMap
336+
Map<String, String> hash = new HashMap<>();;
337+
hash.put("name", "John");
338+
hash.put("surname", "Smith");
339+
hash.put("company", "Redis");
340+
hash.put("age", "29");
341+
jedis.hset("user-session:123", hash);
342+
System.out.println(jedis.hgetAll("user-session:123"));
343+
// Prints: {name=John, surname=Smith, company=Redis, age=29}
344+
}
345+
}
346+
}
347+
```
348+
349+
Because adding a `try-with-resources` block for each command can be cumbersome, consider using `JedisPooled` as an easier way to pool connections. `JedisPooled`, added in Jedis version 4.0.0, provides capabilities similar to `JedisPool` but with a more straightforward API.
350+
351+
```java
352+
import redis.clients.jedis.JedisPooled;
353+
354+
//...
320355

321-
### Configuring a connection pool
356+
JedisPooled jedis = new JedisPooled("localhost", 6379);
357+
jedis.set("foo", "bar");
358+
System.out.println(jedis.get("foo")); // prints "bar"
359+
```
322360

323-
As mentioned in the previous section, use `JedisPool` or `JedisPooled` to create a connection pool.
324-
`JedisPooled`, added in Jedis version 4.0.0, provides capabilities similar to `JedisPool` but with a more straightforward API.
325361
A connection pool holds a specified number of connections, creates more connections when necessary, and terminates them when they are no longer needed.
326362

327363
Here is a simplified connection lifecycle in a pool:
@@ -367,6 +403,11 @@ poolConfig.setTimeBetweenEvictionRuns(Duration.ofSeconds(1));
367403
JedisPooled jedis = new JedisPooled(poolConfig, "localhost", 6379);
368404
```
369405

406+
## Production usage
407+
408+
The following sections explain how to handle situations that may occur
409+
in your production environment.
410+
370411
### Timeouts
371412

372413
To set a timeout for a connection, use the `JedisPooled` or `JedisPool` constructor with the `timeout` parameter, or use `JedisClientConfig` with the `socketTimeout` and `connectionTimeout` parameters:

content/develop/connect/clients/java/lettuce.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,9 @@ try (RedisClient client = RedisClient.create(redisURI)) {
234234

235235
A typical approach with Lettuce is to create a single `RedisClient` instance and reuse it to establish connections to your Redis server(s).
236236
These connections are multiplexed; that is, multiple commands can be run concurrently over a single or a small set of connections, making explicit pooling less practical.
237+
See
238+
[Connection pools and multiplexing]({{< relref "/develop/connect/clients/pools-and-muxing" >}})
239+
for more information.
237240

238241
Lettuce provides pool config to be used with Lettuce asynchronous connection methods.
239242

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
---
2+
categories:
3+
- docs
4+
- develop
5+
- stack
6+
- oss
7+
- rs
8+
- rc
9+
- oss
10+
- kubernetes
11+
- clients
12+
description: Manage Redis connections efficiently
13+
linkTitle: Pooling/multiplexing
14+
title: Connection pools and multiplexing
15+
weight: 10
16+
---
17+
18+
Redis example code generally opens a connection, demonstrates
19+
a command or feature, and then closes. Real-world code typically
20+
has short bursts of communication with the server and periods of
21+
inactivity in between. Opening and closing connections
22+
involves some overhead and leads to inefficiency if you do
23+
it frequently. This means that you can improve the performance of production
24+
code by making as few separate connections as possible.
25+
26+
Managing connections in your own code can be tricky, so the Redis
27+
client libraries give you some help. The two basic approaches to
28+
connection management are called *connection pooling* and *multiplexing*.
29+
The [`redis-py`]({{< relref "/develop/connect/clients/python/redis-py" >}}),
30+
[`jedis`]({{< relref "/develop/connect/clients/java/jedis" >}}), and
31+
[`go-redis`]({{< relref "/develop/connect/clients/go" >}}) clients support
32+
connection pooling, while
33+
[`NRedisStack`]({{< relref "/develop/connect/clients/dotnet" >}})
34+
supports multiplexing.
35+
[`Lettuce`]({{< relref "/develop/connect/clients/java/lettuce" >}})
36+
supports both approaches.
37+
38+
## Connection pooling
39+
40+
When you initialize a connection pool, the client opens a small number
41+
of connections and adds them to the pool.
42+
43+
{{< image filename="/images/dev/connect/pool-and-mux/ConnPoolInit.drawio.svg" >}}
44+
45+
Each time you "open" a connection
46+
from the pool, the client returns one of these existing
47+
connections and notes the fact that it is in use.
48+
49+
{{< image filename="/images/dev/connect/pool-and-mux/ConnPoolInUse.drawio.svg" >}}
50+
51+
When you later "close"
52+
the connection, the client puts it back into the pool of available
53+
connections without actually closing it.
54+
55+
{{< image filename="/images/dev/connect/pool-and-mux/ConnPoolDiscon.drawio.svg" >}}
56+
57+
If all connections in the pool are in use but the app needs more, then
58+
the client can simply open new connections as necessary. In this way, the client
59+
eventually finds the right number of connections to satisfy your
60+
app's demands.
61+
62+
## Multiplexing
63+
64+
Instead of pooling several connections, a multiplexer keeps a
65+
single connection open and uses it for all traffic between the
66+
client and the server. The "connections" returned to your code are
67+
used to identify where to send the response data from your commands.
68+
69+
{{< image filename="/images/dev/connect/pool-and-mux/ConnMux.drawio.svg" >}}
70+
71+
Note that it is not a problem if the multiplexer receives several commands close
72+
together in time. When this happens, the multiplexer can often combine the commands into a
73+
[pipeline]({{< relref "/develop/use/pipelining" >}}), which
74+
improves efficiency.
75+
76+
Multiplexing offers high efficiency but works transparently without requiring
77+
any special code to enable it in your app. The main disadvantage of multiplexing compared to
78+
connection pooling is that it can't support the blocking "pop" commands (such as
79+
[`BLPOP`]({{< relref "/commands/blpop" >}})) since these would stall the
80+
connection for all callers.

content/develop/connect/clients/python/redis-py.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,40 @@ The client will also flush the cache automatically
232232
if any connection (including one from a connection pool)
233233
is disconnected.
234234

235+
## Connect with a connection pool
236+
237+
For production usage, you should use a connection pool to manage
238+
connections rather than opening and closing connections individually.
239+
A connection pool maintains several open connections and reuses them
240+
efficiently. When you open a connection from a pool, the pool allocates
241+
one of its open connections. When you subsequently close the same connection,
242+
it is not actually closed but simply returned to the pool for reuse.
243+
This avoids the overhead of repeated connecting and disconnecting.
244+
See
245+
[Connection pools and multiplexing]({{< relref "/develop/connect/clients/pools-and-muxing" >}})
246+
for more information.
247+
248+
Use the following code to connect with a connection pool:
249+
250+
```python
251+
import redis
252+
253+
pool = redis.ConnectionPool().from_url("redis://localhost")
254+
r1 = redis.Redis().from_pool(pool)
255+
r2 = redis.Redis().from_pool(pool)
256+
r3 = redis.Redis().from_pool(pool)
257+
258+
r1.set("wind:1", "Hurricane")
259+
r2.set("wind:2", "Tornado")
260+
r3.set("wind:3", "Mistral")
261+
262+
r1.close()
263+
r2.close()
264+
r3.close()
265+
266+
pool.close()
267+
```
268+
235269
## Example: Indexing and querying JSON documents
236270

237271
Make sure that you have Redis Stack and `redis-py` installed. Import dependencies:

0 commit comments

Comments
 (0)