go-redis

repository·master·Indexed 12 days ago

https://github.com/redis/go-redis

The official Redis client library for the Go programming language. It provides a high-performance interface for interacting with Redis servers, including support for Cluster, Sentinel, and advanced data types. Features include autopipelining (blocking and async), client-side caching via RESP3, and support for Redis 8.4+ DIGEST commands for optimistic locking using SetIFDEQ and SetIFDNE.

Tokens
102K
Snippets
338
Records
469
Agent score
95%

What's inside go-redis

  1. Overview of go-redis features

    master

    The go-redis client provides a wide range of features for interacting with Redis:

    • Core Commands: Supports almost all Redis commands (except QUIT and SYNC).
    • Connection Management: Automatic connection pooling and customizable read/write buffer sizes.
    • High Throughput:
      • Pipelines and transactions: Standard Redis pipelining.
      • Automatic pipelining (experimental): Automatically batches concurrent commands into pipelines for high-load use cases.
    • Advanced Patterns:
      • Pub/Sub: Support for Redis publish/subscribe.
      • Scripting: Support for Lua scripting.
      • Client-side caching: Support for client-side caching mechanisms.
    • Topology Support: Native support for Redis Sentinel and Redis Cluster.
    • Authentication: Experimental support for StreamingCredentialsProvider (e.g., Entra ID, OAuth).
  2. Supported Redis versions

    master

    The go-redis library aims to support the last three releases of Redis.

    Currently supported versions:

    • Redis 8.0
    • Redis 8.2
    • Redis 8.4
    • Redis 8.8
    • Redis 8.10

    Compatibility Notes:

    • While go-redis/v9 is designed for these versions, it should also work with any Redis 7.0+ (though not officially supported).
    • The project requires at minimum Go 1.24 per go.mod.
  3. What is Redis DIGEST and how to use it for optimistic locking

    master

    The DIGEST command (available in Redis 8.4+) returns a 64-bit xxh3 hash of a key's value. This allows for efficient optimistic locking and change detection without transferring the entire value between the server and the client.

    Core Use Cases

    • Optimistic Locking: Update a value only if its current digest matches your expected digest (ensuring no one else changed it).
    • Change Detection: Update a value only if its current digest differs from your expected digest.
    • Conditional Deletion: Delete a key only if its current digest matches a specific value.

    Advantages over WATCH/MULTI/EXEC

    • Simpler: Uses single commands instead of complex transaction blocks.
    • Faster: Reduces network round trips and avoids transaction overhead.
    • Client-side friendly: You can calculate the expected digest locally if you already know the value, avoiding an extra DIGEST call to Redis.
    import "github.com/redis/go-redis/v9/helper"
    
    // For strings
    digest := helper.DigestString("myvalue")
    
    // For binary data
    digest := helper.DigestBytes([]byte{0x01, 0x02, 0x03})
  4. How Maintenance Notifications work

    master

    Maintenance Notifications provide zero-downtime connection handoffs during Redis cluster maintenance (like Redis Enterprise operations).

    Core Mechanism

    1. Push Notifications: The client listens for RESP3 push notifications (e.g., MOVING, MIGRATING, FAILING_OVER).
    2. Event-Driven Handoff: When a notification is received, an asynchronous worker pool handles the transition to new connections without blocking client operations.
    3. Timeout Relaxation: During maintenance, the client automatically relaxes read/write timeouts (RelaxedTimeout) to prevent false failures caused by increased latency during the handoff.
    4. Circuit Breaker: To prevent overwhelming failing endpoints, a circuit breaker tracks failures per endpoint and enters a 'half-open' state to test recovery gradually.

    Supported Notification Types

    • Standalone Client: Supports MOVING, MIGRATING, MIGRATED, FAILING_OVER, and FAILED_OVER.
    • Cluster Client: Supports SMIGRATING and SMIGRATED for hitless slot migrations.

    Architecture

    • Non-Blocking: Uses a worker pool and queue-based architecture to ensure client operations continue during handoffs.
    • Thread-Safe: Employs lock-free atomic operations and sync.Map for high-performance state tracking.
    • Auto-Scaling: If MaxWorkers or HandoffQueueSize are set to 0, the client automatically calculates optimal sizes based on the connection pool size.
  5. Important: Maintenance notification support limitations

    master

    Maintenance Notifications Support

    Maintenance notifications are currently supported only in standalone Redis clients.

    Clients such as ClusterClient, FailoverClient, and other cluster-aware clients do not yet support maintenance notifications functionality. Ensure you are using a standalone client if you require this feature.

  6. Configure authentication priority and methods

    master

    The client supports four authentication methods, applied in the following priority order:

    1. Streaming Credentials Provider (Highest Priority): An experimental feature for dynamic credential updates (e.g., managed identities). Implement the StreamingCredentialsProvider interface.
    2. Context-based Credentials Provider: Uses CredentialsProviderContext to determine credentials at the time of each operation via the context.
    3. Regular Credentials Provider: Uses CredentialsProvider to return static credentials via a function.
    4. Username/Password Fields (Lowest Priority): Uses the Username and Password fields in redis.Options.
  7. Use step-based pipelines with FTAggregateOptions.Steps

    master

    The FTAggregateOptions.Steps field allows you to construct complex FT.AGGREGATE pipelines where commands like LOAD, APPLY, GROUPBY, and SORTBY can appear multiple times and in any order.

    A primary use case for this is shard-level trimming: by placing a SORTBY ... MAX N command before a GROUPBY command, you ensure that each shard only sends its top-N rows to the next stage of the pipeline, reducing data transfer and improving performance.

    Important Configuration Note: Because the RESP3 response shape for FT.AGGREGATE is currently marked as unstable, you should configure your client with Protocol: 2. If you prefer to use RESP3, set UnstableResp3: true instead.

    // Example logic flow described in the documentation:
    // 1. SORTBY @rating DESC MAX 5
    // 2. GROUPBY @category
    // 3. SORTBY @price_total DESC
  8. Use HIMPORT for fast hash ingestion

    master

    The HIMPORT command family (available in Redis 8.10+) allows for fast hash ingestion using hinted hash templates. This process involves two steps:

    1. HIMPORT PREPARE: Registers an ordered list of field names (a fieldset) within a connection's session.
    2. HIMPORT SET: Creates hashes by sending only the values, which are paired positionally with the prepared fields. This allows the server to store hashes using a memory-efficient template encoding where shared field names are stored only once.

    Client-side Management

    go-redis manages fieldsets automatically for pooled callers using the following typed methods:

    • HImportPrepare: Registers a fieldset.
    • HImportSet: Performs the ingestion using the prepared fieldset.
    • HImportDiscard: Discards a specific fieldset.
    • HImportDiscardAll: Discards all fieldsets.

    go-redis remembers fieldsets client-side and replays the PREPARE command lazily (at most once per connection session) on whichever pooled connection executes an HImportSet. If a connection loses its session state (due to RESET or a reconnect), the client transparently re-prepares the fieldset.

    Warning: These guarantees apply only to the typed methods listed above. If you use generic command interfaces like Do or raw Cmd values, the client-side registry is bypassed. In those cases, PREPARE commands will not be replayed on other connections, and no such fieldset errors may occur. For low-level HIMPORT usage, use a dedicated connection via client.Conn().

    // Conceptual usage of the typed API
    err := client.HImportPrepare(ctx, fieldset).Err()
    err = client.HImportSet(ctx, key, values).Err()
  9. How ClusterClient manages Redis Cluster operations

    master

    The ClusterClient is a specialized client designed to interact with a Redis Cluster. It abstracts the following responsibilities from the developer:

    • Key Distribution: Automatically distributes keys across cluster nodes based on their hash slots.
    • Redirect Handling: Follows cluster redirects (MOVED/ASK) to ensure commands reach the correct node.
    • Connection Management: Maintains active connections to all nodes in the cluster topology.
    • Topology Awareness: Retries operations automatically when the cluster topology changes.

    When performing bulk operations like MGET, the ClusterClient is responsible for identifying which keys belong to which nodes and managing the multi-node communication required to fulfill the request.

  10. Use Automatic Pipelining (Experimental)

    master

    Autopipelining automatically batches concurrent commands from multiple goroutines into Redis pipelines. This is intended for high-throughput/high-load scenarios.

    Two modes of operation:

    1. AutoPipeline() (Blocking): A drop-in replacement for a normal client. Each command call blocks until it executes and returns its own value/error. Per-goroutine ordering is preserved.
    2. AsyncAutoPipeline() (Deferred): Highest throughput. Command calls return immediately (returning a command object), and you read the results later. This keeps pipelines deep.

    Important Caveats:

    • Contexts: A command's context is NOT honored once it is queued; batches execute on the autopipeliner's own context. Use a plain client if you need per-command deadlines.
    • Non-idempotent commands: On a dropped connection, a batch is retried as a whole. Non-idempotent commands might execute twice.
    • Bypassed commands: Blocking commands (BLPOP, WAIT), SHUTDOWN, MONITOR, and Do bypass batching.
    // Blocking face: drop-in for a normal client, batched under the hood.
    ap, err := rdb.AutoPipeline()
    if err != nil {
        log.Fatal(err)
    }
    defer ap.Close()
    
    var wg sync.WaitGroup
    for i := 0; i < 1000; i++ {
        wg.Add(1)
        go func(i int) {
            defer wg.Done()
            key := fmt.Sprintf("key:%d", i)
            if err := ap.Set(ctx, key, i, 0).Err(); err != nil { // blocks until executed
                log.Printf("set %s: %v", key, err)
            }
        }(i)
    }
    wg.Wait()
    
    // Async face: for maximum throughput
    ctx := context.Background()
    ap, err := rdb.AsyncAutoPipeline()
    if err != nil {
        log.Fatal(err)
    }
    defer ap.Close()
    
    cmds := make([]*redis.StatusCmd, 0, 200)
    for i := 0; i < 200; i++ {
        cmds = append(cmds, ap.Set(ctx, fmt.Sprintf("key:%d", i), i, 0)) // returns immediately
    }
    for _, cmd := range cmds {
        if err := cmd.Err(); err != nil { // blocks until executed
            log.Printf("set: %v", err)
        }
    }
  11. Enable Client-side caching

    master

    go-redis supports server-assisted client-side caching for standalone clients using RESP3. This stores eligible read replies in application memory to avoid Redis round trips.

    Requirements:

    • Must use Protocol: 3.
    • Must be a standalone client (not Cluster).
    • Must use database 0.
    • Username and Password must be fixed (dynamic credentials disable caching).

    Limitations:

    • Certain commands like SELECT, AUTH, HELLO, RESET, CLIENT TRACKING, and raw SUBSCRIBE are rejected as they change connection state.
    • Invalidations are processed asynchronously via DrainInterval and MaxStaleness settings.
    rdb := redis.NewClient(&redis.Options{
        Addr:     "localhost:6379",
        Protocol: 3,
        DB:       0,
        ClientSideCacheConfig: &redis.ClientSideCacheConfig{
            MaxEntries: 10_000,
        },
    })
    defer rdb.Close()
  12. Access the Array data type (Redis 8.8+)

    master

    Starting with Redis 8.8, go-redis provides experimental support for the new array data type via the AR* command family.

    Warning: This API is experimental and subject to change in future releases.

    Available command families include:

    • ARSET, ARGET, ARGETRANGE, ARMSET, ARMGET, ARINSERT, ARDEL, ARDELRANGE, ARLEN, ARCOUNT, ARNEXT, ARSEEK, ARSCAN, ARGREP, ARRING, ARLASTITEMS, ARINFO/ARINFOFULL, and AROP* reducers.