Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions content/develop/clients/client-side-caching.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ relatedPages:
- /develop/clients/redis-py/connect#connect-using-client-side-caching
- /develop/clients/nodejs/connect#connect-using-client-side-caching
- /develop/clients/jedis/connect#connect-using-client-side-caching
- /develop/clients/go/connect#connect-using-client-side-caching
topics:
- client-side-caching
- performance
Expand Down Expand Up @@ -92,6 +93,7 @@ The following client libraries support CSC from the stated version onwards:
| [`redis-py`]({{< relref "/develop/clients/redis-py/connect#connect-using-client-side-caching" >}}) | v5.1.0 |
| [`Jedis`]({{< relref "/develop/clients/jedis/connect#connect-using-client-side-caching" >}}) | v5.2.0 |
| [`node-redis`]({{< relref "/develop/clients/nodejs/connect#connect-using-client-side-caching" >}}) | v5.1.0 |
| [`go-redis`]({{< relref "/develop/clients/go/connect#connect-using-client-side-caching" >}}) | v9.<!-- DOC-6831: set on merge -->TBD |

Note that some other clients support the [`CLIENT TRACKING`]({{< relref "/commands/client-tracking" >}}) command to configure CSC on the server, but this does not mean they support the
features required for CSC themselves.
Expand Down
113 changes: 113 additions & 0 deletions content/develop/clients/go/connect.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,3 +183,116 @@ either [AWS PrivateLink]({{< relref "/operate/rc/security/aws-privatelink" >}})
To use relaxed timeouts with these services, you should set `EndpointType: maintnotifications.EndpointTypeNone`
when you connect. All other configurations have full support for both relaxed timeouts and pre-handoffs.
{{< /note >}}

## 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]({{< relref "/develop/clients/client-side-caching" >}})
for more information about how client-side caching works and how to use it effectively.

{{< note >}}This feature is not yet released and its API is subject to change.
It is being added in [go-redis PR #3851](https://github.com/redis/go-redis/pull/3851).

Client-side caching requires go-redis v9.<!-- DOC-6831: set on merge -->TBD or later.
To maximize compatibility with all Redis products, client-side caching
is supported by Redis v7.4 or later.

Client-side caching requires the [RESP3]({{< relref "/develop/reference/protocol-spec#resp-versions" >}})
protocol, so you must set `Protocol: 3` explicitly when you connect. On a RESP2
connection, client-side caching silently does nothing. It also works on logical
database 0 only; on any other database it is disabled with a log warning.
{{< /note >}}

To enable client-side caching, pass a `ClientSideCacheConfig` object when you
connect on a `Protocol: 3` client. Passing an empty `ClientSideCacheConfig{}`
enables caching with the default settings:

```go
import (
"context"
"fmt"
"github.com/redis/go-redis/v9"
)

func main() {
ctx := context.Background()

client := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Protocol: 3, // RESP3 required for client-side caching
ClientSideCacheConfig: &redis.ClientSideCacheConfig{},
})

client.Set(ctx, "city", "New York", 0)
client.Get(ctx, "city") // Retrieved from the server and cached
client.Get(ctx, "city") // Retrieved from the cache
}
```

You can see the cache working if you connect to the same Redis database
with [`redis-cli`]({{< relref "/develop/tools/cli" >}}) and run the
[`MONITOR`]({{< relref "/commands/monitor" >}}) command. With caching enabled,
the server sees the first `Get("city")` call but not the second, which the
client satisfies from the cache.

### Caching strategies

go-redis supports three client-side caching strategies, selected with the
`ClientSideCacheStrategy` option. All three share the same cache interface,
the same cacheable-command allow-list, and the same RESP3 and database-0
requirements; they differ in how invalidation messages reach the cache.

| Strategy | Cache | Tracking | Best for |
| :-- | :-- | :-- | :-- |
| `CSCStrategySharedTracking` (default) | One shared, sharded cache | Every pool connection issues `CLIENT TRACKING ON`; a background drainer applies invalidations | General use. Works wherever RESP3 does (including managed or proxied environments) and needs no extra connection. |
| `CSCStrategyBroadcast` | One shared, sharded cache | A dedicated out-of-pool "sidecar" connection issues `CLIENT TRACKING ON BCAST` and owns all invalidation traffic | Highest throughput and lowest tail latency, where broadcasting mode is available. Uses one extra connection and receives invalidations for every write in the database. |
| `CSCStrategyPerConnection` | One private cache per pool connection | Every pool connection issues `CLIENT TRACKING ON` and owns its own cache | Small, long-lived pools (≲10 connections) that want hard isolation between connections. Cache memory multiplies by pool size, so avoid it at high concurrency. |

If you don't set `ClientSideCacheStrategy`, the zero value
`CSCStrategySharedTracking` is used. The example below opts into broadcasting
mode instead:

```go
client := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Protocol: 3,
ClientSideCacheConfig: &redis.ClientSideCacheConfig{},
ClientSideCacheStrategy: redis.CSCStrategyBroadcast,
})
```

### Configuration options

The `ClientSideCacheConfig` object accepts the following options to tune the
cache:

| Name | Description |
| :-- | :-- |
| `MaxEntries` | The maximum number of entries the cache can hold. Zero or negative means unlimited. If both `MaxEntries` and `MaxMemoryBytes` are unlimited, `MaxEntries` defaults to 10,000 so the cache cannot grow without bound. |
| `MaxMemoryBytes` | An approximate memory limit for the cache. Zero means unlimited. |
| `DrainInterval` | (`CSCStrategySharedTracking` only) How often the background drainer scans idle connections and applies buffered invalidations to the shared cache. The default is 5ms and the minimum is 1ms. |
| `MaxStaleness` | The hard upper bound on how long a cached entry can be served after the underlying data has changed. Zero means no explicit bound (the drain interval still applies). |

### Monitoring the cache

Use the `CSCStats()` method to read the cumulative cache hit and miss counts
for a client:

```go
hits, misses := client.CSCStats()
fmt.Printf("Cache hits: %d, misses: %d\n", hits, misses)
```

Process-wide totals are also available via the package-level functions
`redis.CommandStats()` (served-command hits and misses),
`redis.CacheAdmissionRejects()` (entries rejected on admission), and
`redis.RESPInvalidationBytesRead()` (bytes of invalidation key names read).

{{< note >}}To supply your own cache implementation, set the `ClientSideCache`
option instead of `ClientSideCacheConfig`. An explicit `ClientSideCache` is
honoured by the `CSCStrategySharedTracking` and `CSCStrategyBroadcast`
strategies. `CSCStrategyPerConnection` always builds a private cache per
connection from `ClientSideCacheConfig` and ignores an explicit
`ClientSideCache` (with a log warning).
{{< /note >}}
Loading