# Connect to the server

```json metadata
{
  "schema_version": 2,
  "title": "Connect to the server",
  "description": "Connect your Python application to a Redis database",
  "categories": ["docs","develop","stack","oss","rs","rc","oss","kubernetes","clients"],
  "tableOfContents": {"sections":[{"id":"basic-connection","title":"Basic connection"},{"id":"connect-to-a-redis-cluster","title":"Connect to a Redis cluster"},{"id":"connect-to-your-production-redis-with-tls","title":"Connect to your production Redis with TLS"},{"children":[{"id":"removing-items-from-the-cache","title":"Removing items from the cache"}],"id":"connect-using-client-side-caching","title":"Connect using client-side caching"},{"id":"connect-with-a-connection-pool","title":"Connect with a connection pool"},{"id":"retrying-connections","title":"Retrying connections"},{"id":"connect-using-smart-client-handoffs-sch","title":"Connect using Smart client handoffs (SCH)"}]}

,
  "codeExamples": []
}
```


## Basic connection

Connect to localhost on port 6379, set a value in Redis, and retrieve it. All responses are returned as bytes in Python. To receive decoded strings, set `decode_responses=True`. For more connection options, see [these examples](https://redis.readthedocs.io/en/stable/examples.html).

```python
r = redis.Redis(host='localhost', port=6379, decode_responses=True)
```

Store and retrieve a simple string.

```python
r.set('foo', 'bar')
# True
r.get('foo')
# bar
```

Store and retrieve a dict.

```python
r.hset('user-session:123', mapping={
    'name': 'John',
    "surname": 'Smith',
    "company": 'Redis',
    "age": 29
})
# True

r.hgetall('user-session:123')
# {'surname': 'Smith', 'name': 'John', 'company': 'Redis', 'age': '29'}
```

## Connect to a Redis cluster

To connect to a Redis cluster, use `RedisCluster`.

```python
from redis.cluster import RedisCluster

rc = RedisCluster(host='localhost', port=16379)

print(rc.get_nodes())
# [[host=127.0.0.1,port=16379,name=127.0.0.1:16379,server_type=primary,redis_connection=Redis<ConnectionPool<Connection<host=127.0.0.1,port=16379,db=0>>>], ...

rc.set('foo', 'bar')
# True

rc.get('foo')
# b'bar'
```
For more information, see [redis-py Clustering](https://redis.readthedocs.io/en/stable/clustering.html).

## Connect to your production Redis with TLS

When you deploy your application, use TLS and follow the [Redis security](https://redis.io/docs/latest/operate/oss_and_stack/management/security) guidelines.

```python
import redis

r = redis.Redis(
    host="my-redis.cloud.redislabs.com", port=6379,
    username="default", # use your Redis user. More info https://redis.io/docs/latest/operate/oss_and_stack/management/security/acl/
    password="secret", # use your Redis password
    ssl=True,
    ssl_certfile="./redis_user.crt",
    ssl_keyfile="./redis_user_private.key",
    ssl_ca_certs="./redis_ca.pem",
)
r.set('foo', 'bar')
# True

r.get('foo')
# b'bar'
```
For more information, see [redis-py TLS examples](https://redis.readthedocs.io/en/stable/examples/ssl_connection_examples.html).

## Connect using client-side caching

Client-side caching is a technique to reduce network traffic between
the client and server, resulting in better performance. See
[Client-side caching introduction](https://redis.io/docs/latest/develop/clients/client-side-caching)
for more information about how client-side caching works and how to use it effectively.

To enable client-side caching, add some extra parameters when you connect
to the server:

-   `protocol`: (Required) You must pass a value of `3` here because
    client-side caching requires the [RESP3](https://redis.io/docs/latest/develop/reference/protocol-spec#resp-versions)
    protocol.
-   `cache_config`: (Required) Pass `cache_config=CacheConfig()` here to enable client-side caching.

The example below shows the simplest client-side caching connection to the default host and port,
`localhost:6379`.
All of the connection variants described above accept these parameters, so you can
use client-side caching with a connection pool or a cluster connection in exactly the same way.

> [!NOTE]
> Client-side caching requires redis-py v5.1.0 or later.
> To maximize compatibility with all Redis products, client-side caching
> is supported by Redis v7.4 or later.
>
> The [Redis server products](https://redis.io/docs/latest/operate) support
> [opt-in/opt-out](https://redis.io/docs/latest/develop/reference/client-side-caching#opt-in-and-opt-out-caching) mode
> and [broadcasting mode](https://redis.io/docs/latest/develop/reference/client-side-caching#broadcasting-mode)
> for CSC, but these modes are not currently implemented by `redis-py`.

```python
import redis
from redis.cache import CacheConfig

r = redis.Redis(
    protocol=3,
    cache_config=CacheConfig(),
    decode_responses=True
)

r.set("city", "New York")
cityNameAttempt1 = r.get("city")    # Retrieved from Redis server and cached
cityNameAttempt2 = r.get("city")    # Retrieved from cache
```

You can see the cache working if you connect to the same Redis database
with [`redis-cli`](https://redis.io/docs/latest/develop/tools/cli) and run the
[`MONITOR`](https://redis.io/docs/latest/commands/monitor) command. If you run the
code above with the `cache_config` line commented out, you should see
the following in the CLI among the output from `MONITOR`:

```
1723109720.268903 [...] "SET" "city" "New York"
1723109720.269681 [...] "GET" "city"
1723109720.270205 [...] "GET" "city"
```

The server responds to both `get("city")` calls.
If you run the code again with `cache_config` uncommented, you will see

```
1723110248.712663 [...] "SET" "city" "New York"
1723110248.713607 [...] "GET" "city"
```

The first `get("city")` call contacted the server but the second
call was satisfied by the cache.

### Removing items from the cache

You can remove individual keys from the cache with the
`delete_by_redis_keys()` method. This removes all cached items associated
with the keys, so all results from multi-key commands (such as
[`MGET`](https://redis.io/docs/latest/commands/mget)) and composite data structures
(such as [hashes](https://redis.io/docs/latest/develop/data-types/hashes)) will be
cleared at once. The example below shows the effect of removing a single
key from the cache:

```python
r.hget("person:1", "name") # Read from the server
r.hget("person:1", "name") # Read from the cache

r.hget("person:2", "name") # Read from the server
r.hget("person:2", "name") # Read from the cache

cache = r.get_cache()
cache.delete_by_redis_keys(["person:1"])

r.hget("person:1", "name") # Read from the server
r.hget("person:1", "name") # Read from the cache

r.hget("person:2", "name") # Still read from the cache
```

You can also clear all cached items using the `flush()`
method:

```python
r.hget("person:1", "name") # Read from the server
r.hget("person:1", "name") # Read from the cache

r.hget("person:2", "name") # Read from the cache
r.hget("person:2", "name") # Read from the cache

cache = r.get_cache()
cache.flush()

r.hget("person:1", "name") # Read from the server
r.hget("person:1", "name") # Read from the cache

r.hget("person:2", "name") # Read from the server
r.hget("person:2", "name") # Read from the cache
```

The client will also flush the cache automatically
if any connection (including one from a connection pool)
is disconnected.

## Connect with a connection pool

For production usage, you should use a connection pool to manage
connections rather than opening and closing connections individually.
A connection pool maintains several open connections and reuses them
efficiently. When you open a connection from a pool, the pool allocates
one of its open connections. When you subsequently close the same connection,
it is not actually closed but simply returned to the pool for reuse.
This avoids the overhead of repeated connecting and disconnecting.
See
[Connection pools and multiplexing](https://redis.io/docs/latest/develop/clients/pools-and-muxing)
for more information.

Use the following code to connect with a connection pool:

```python
import redis

pool = redis.ConnectionPool().from_url("redis://localhost")
r1 = redis.Redis().from_pool(pool)
r2 = redis.Redis().from_pool(pool)
r3 = redis.Redis().from_pool(pool)

r1.set("wind:1", "Hurricane")
r2.set("wind:2", "Tornado")
r3.set("wind:3", "Mistral")

r1.close()
r2.close()
r3.close()

pool.close()
```

## Retrying connections

A connection will sometimes fail because of a transient problem, such as a
network outage or a server that is temporarily unavailable. In these cases,
retrying the connection after a short delay will usually succeed. `redis-py` uses
a simple retry strategy by default, but there are various ways you can customize
this behavior to suit your use case. See
[Retries](https://redis.io/docs/latest/develop/clients/redis-py/produsage#retries)
for more information about custom retry strategies, with example code.

## Connect using Smart client handoffs (SCH)

*Smart client handoffs (SCH)* is a feature of Redis Cloud and
Redis Software servers that lets them actively notify clients
about planned server maintenance shortly before it happens. This
lets a client take action to avoid disruptions in service.
See [Smart client handoffs](https://redis.io/docs/latest/develop/clients/sch)
for more information about SCH.

> [!NOTE]
> Using SCH with redis-py requires v7.0.0 or later for
> basic connections, and v7.2.0 or later for
> [OSS Cluster API](https://redis.io/docs/latest/operate/rs/databases/configure/oss-cluster-api) connections.

By default, `redis-py` always attempts to connect via SCH but falls back to
a non-SCH connection if the server doesn't support it. However, you can configure SCH
explicitly by passing a `MaintNotificationsConfig` object during the connection,
as shown in the following example:

```py
import redis
from redis.maint_notifications import MaintNotificationsConfig, EndpointType

r = redis.Redis(
    decode_responses=True,
    protocol=3,
    maint_notifications_config=MaintNotificationsConfig(
        proactive_reconnect=True,
        relaxed_timeout=10,
        endpoint_type=EndpointType.EXTERNAL_IP
    ),
    ...
)
```

To disable SCH, pass `enabled=False` in the `MaintNotificationsConfig` object:

```python
r = redis.Redis(
    maint_notifications_config=MaintNotificationsConfig(
        enabled=False,
    ),
    ...
)
```

> [!NOTE]
> SCH requires the [RESP3](https://redis.io/docs/latest/develop/reference/protocol-spec#resp-versions)
> protocol, so you must set `protocol=3` explicitly when you connect.

The `MaintNotificationsConfig` constructor accepts the following parameters:

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `enabled` | `bool` | `True` | Whether or not to enable SCH. |
| `proactive_reconnect` | `bool` | `True` | Whether or not to automatically reconnect when a node is replaced. |
| `endpoint_type` | `EndpointType` | Auto-detect | The type of endpoint to use for the connection. The options are `EndpointType.EXTERNAL_IP`, `EndpointType.INTERNAL_IP`, `EndpointType.EXTERNAL_FQDN`, `EndpointType.INTERNAL_FQDN`, and `EndpointType.NONE`. |
| `relaxed_timeout` | `int` | `20` | The timeout (in seconds) to use while the server is performing maintenance. A value of `-1` disables the relax timeout and just uses the normal timeout during maintenance. |

> [!NOTE]
> Redis Cloud supports relaxed timeouts *only* (and not pre-handoffs) for SCH if you are using
> either [AWS PrivateLink](https://redis.io/docs/latest/operate/rc/security/aws-privatelink) or
> [Google Cloud Private Service Connect](https://redis.io/docs/latest/operate/rc/security/private-service-connect)
> (see [Smart client handoffs](https://redis.io/docs/latest/develop/clients/sch#redis-cloud) for more information).
> To use relaxed timeouts with these services, you should set `endpoint_type=EndpointType.NONE`
> when you connect. All other configurations have full support for both relaxed timeouts and pre-handoffs.

