From 396986f9c957db580a595f4041af8bb67b805d48 Mon Sep 17 00:00:00 2001 From: Andy Stark Date: Fri, 10 Jul 2026 15:03:43 +0100 Subject: [PATCH] DOC-6831 Document go-redis client-side caching MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a "Connect using client-side caching" section to the go-redis connect page covering the multi-strategy CSC being added in redis/go-redis#3851: enabling via ClientSideCacheConfig on a RESP3 client, the three ClientSideCacheStrategy options (SharedTracking default, Broadcast, PerConnection), the tuning options (MaxEntries, MaxMemoryBytes, DrainInterval, MaxStaleness), and monitoring via CSCStats plus the process-wide stats functions. Register go-redis in the support table and relatedPages of the CSC introduction page. Written against the unmerged upstream PR, so the section carries a pre-release warning and the version is a TBD placeholder. Parked pending the upstream merge and release. Experience: Rejected /park's page-level bannerText in favour of a section-scoped {{< note >}} warning — the CSC section lives in an otherwise-released Connect page, so a page banner would wrongly flag basic/TLS/cluster/SCH as unreleased. Don't "correct" the missing bannerText on pickup; the section-scoped warning is intentional. Recheck: fill go-redis version once #3851 merges and is tagged (connect.md note + client-side-caching.md support table both use a "v9.TBD" placeholder) Recheck: confirm final exported names against merged source — ClientSideCacheConfig, ClientSideCacheStrategy, CSCStrategy{SharedTracking,Broadcast,PerConnection}, ClientSideCacheConfig fields, (*Client).CSCStats, redis.CommandStats/CacheAdmissionRejects/RESPInvalidationBytesRead Recheck: verify DrainInterval default (5ms) / floor (1ms) and MaxEntries default (10000) survive to release Recheck: base of #3851 is the feature branch csc-standalone-connection-support, not master — confirm the whole CSC stack lands on master before treating the trigger as fired Co-Authored-By: Claude Opus 4.8 (1M context) --- .../develop/clients/client-side-caching.md | 2 + content/develop/clients/go/connect.md | 113 ++++++++++++++++++ 2 files changed, 115 insertions(+) diff --git a/content/develop/clients/client-side-caching.md b/content/develop/clients/client-side-caching.md index 3fe8490031..8f625bf85b 100644 --- a/content/develop/clients/client-side-caching.md +++ b/content/develop/clients/client-side-caching.md @@ -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 @@ -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.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. diff --git a/content/develop/clients/go/connect.md b/content/develop/clients/go/connect.md index bafc743e94..2337e80875 100644 --- a/content/develop/clients/go/connect.md +++ b/content/develop/clients/go/connect.md @@ -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.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 >}}