9.21.0
This is a minor release adding new features and bug fixes. There are no breaking changes; upgrading from 9.20.x is a drop-in replacement.
Two new StringCmdable methods let callers read and write Redis string values directly into and from pre-allocated byte buffers, eliminating the per-call payload allocation that Get/Set incur:
GetToBuffer(ctx, key, buf) *ZeroCopyStringCmd // reads into buf; ZeroCopyStringCmd { Val() int; Bytes() []byte; Result() (int, error) }
SetFromBuffer(ctx, key, buf) *StatusCmd
GetToBuffer decodes the bulk reply straight into the caller-owned buf (no intermediate allocation); a buffer that is too small returns an error after draining the payload, so the connection stays aligned for the next reply. SetFromBuffer is provided for API symmetry — it dispatches to the same []byte writer path as Set(ctx, key, buf, 0) and produces byte-identical output on the wire. Available on *Client, *ClusterClient, *Ring, *Conn and Pipeliner.
Redis treats XTRIM/XADD approximate-trim (~) LIMIT 0 as "disable the trimming effort cap entirely", which differs from omitting LIMIT (the implicit 100 * stream-node-max-entries default). The command builders previously only emitted LIMIT when limit > 0, so callers could never send an explicit LIMIT 0. Following the KeepTTL = -1 precedent, the new XTrimLimitDisabled = -1 sentinel now emits an explicit LIMIT 0; limit == 0 keeps the historical no-LIMIT behavior, so existing callers produce byte-identical commands.
(#3848) by @TheRealMal
- Zero-copy buffer string commands: new
GetToBuffer/SetFromBufferonStringCmdableand theZeroCopyStringCmdresult type, reading/writing string values into caller-owned buffers without per-call payload allocation (#3834) by @ndyakov XTrimLimitDisabledsentinel:XTRIM/XADDapproximate trimming can now send an explicitLIMIT 0to disable the trim effort cap, via the newXTrimLimitDisabled = -1sentinel (#3848) by @TheRealMal- PubSub health-check timeouts:
channel.initHealthChecknow bounds thePingit issues with a fresh per-check timeout context (the exportedpingTimeout/reconnectTimeout) instead ofcontext.TODO(), so a stuck health-check Ping can no longer block indefinitely (#3819) by @abdellani - Skip redundant
UNWATCHinTx.Close: a transaction now tracks whether aWATCHis still active (watchArmed) and only issuesUNWATCHonClosewhen it is, removing an extra round trip on the commonWATCH/.../EXECand no-keyWatchpaths while never returning a connection to the pool with an active watch (#3854) by @fcostaoliveira
maintnotificationsModeAutofail-open:ModeAutonow stays fail-open when the server does not support maintenance notifications — connections are retired and tracking is guarded during downgrade so the client keeps working instead of erroring (#3853) by @terrorobe
We'd like to thank all the contributors who worked on this release!
@abdellani, @fcostaoliveira, @ndyakov, @terrorobe, @TheRealMal
9.20.1
This is a patch release containing bug fixes only. There are no new features or breaking changes; upgrading from 9.20.0 is a drop-in replacement.
PeekPushNotificationName previously inspected only the bytes already buffered by bufio, so when a push frame header straddled a buffer fill boundary it could return a truncated notification name (e.g. "messa" instead of "message"). The push processor then mis-routed the frame and ReadReply silently dropped it, causing intermittent RESP3 pub/sub message loss. The peek now grows its window (36 bytes → up to 4 KiB) and reads more from the connection until the header is complete, cleanly separating incomplete prefixes from corrupt frames (including overflow-safe bulk-length handling). Fixes #3839.
- RESP3 push peeking:
PeekPushNotificationNameno longer returns a truncated notification name when a push frame header spans a buffer boundary, preventing silent RESP3 pub/sub message loss (fixes #3839) (#3842) by @ndyakov FT.HYBRIDvector params: Vector data is now always sent viaPARAMSwith auto-generated param names (__vector_param_N, with collision avoidance) whenVectorParamNameis omitted, since Redis no longer accepts inline vector blobs; theFTHybridOptions.Paramsmap is no longer mutated, so the same options struct can be reused across calls (#3844) by @ndyakovCLUSTER SHARDSforward compatibility: Unknown shard- and node-level attributes in theCLUSTER SHARDSreply are now skipped viaDiscardNext()instead of erroring, so clients keep working when the server introduces new fields (#3843) by @madolson- PubSub double reconnect:
PubSub.releaseConnno longer reconnects twice when a connection is both unusable (or pending handoff) and reports a bad-connection error, avoiding a wasted connection establish-then-close cycle (#3833) by @cxljs
We'd like to thank all the contributors who worked on this release!
Full Changelog: https://github.com/redis/go-redis/compare/v9.20.0...v9.20.1
9.20.0
This release adds support for Redis 8.8. The README's supported-versions list now includes Redis 8.8 alongside 8.0/8.2/8.4, and CI exercises the 8.8 client-libs-test image across the full suite (Makefile, build workflow, doctests, run-tests action, and docker-compose).
Coverage for the new commands that ship in the 8.x line, rounded out in this release:
AR*array data type (#3813) — new array data structure, exposed via theArrayCmdableinterface (see the experimental-features highlight below).INCREX(#3816) — atomic increment with expiration in a single round-trip.XNACK(#3790) — explicit negative-acknowledge of pending stream entries.XAUTOCLAIMPEL deletes (#3798) —XAUTOCLAIM/XAUTOCLAIMJUSTIDnow return the list of deleted message IDs from the pending entries list.TS.RANGEmultiple aggregators (#3791) —TS.RANGE/TS.REVRANGE/TS.MRANGE/TS.MREVRANGEaccept multiple aggregators in a single call.Z(UNION|INTER|DIFF)COUNTaggregator (#3802) —COUNTreducer for sorted-set set operations.JSON.SET FPHA(#3797) — newFPHAargument that specifies the floating-point type for homogeneous FP arrays.
CI image bump (#3814) by @ofekshenawa. Command coverage contributions by @cxljs, @elena-kolevska, @Khukharr, @ndyakov, and @ofekshenawa.
FT.SEARCH, FT.AGGREGATE, FT.INFO, FT.SPELLCHECK, and FT.SYNDUMP now parse RESP3 (map) responses into the same typed result objects as RESP2 — Val() and Result() work uniformly on both protocols, no flag required. Previously, RESP3 search responses required UnstableResp3: true and were returned as opaque maps accessible only via RawResult() / RawVal().
As a result, the UnstableResp3 option is now a no-op across every options struct (Options, ClusterOptions, UniversalOptions, FailoverOptions, RingOptions) and has been marked // Deprecated:. The field is retained for backwards compatibility — existing code that sets UnstableResp3: true will continue to compile and behave identically — but it will be removed in a future release and new code should not set it. RawResult() / RawVal() continue to work for callers that prefer the raw RESP payload.
Adds an experimental ArrayCmdable interface with the AR* command family (ARSet, ARGet, ARGetRange, ARMSet, ARMGet, ARDel, ARDelRange, ARScan, ARSeek, ARNext, ARLastItems, ARGrep, ARGrepWithValues, ARInfo/ARInfoFull, and typed reducers AROpSum/AROpMin/AROpMax/AROpAnd/AROpOr/AROpXor/AROpMatch/AROpUsed) for working with Redis 8.8's new array data type. API is experimental and may change in a future release.
- RESP3 search parser: First-class RESP3 parsing for
FT.SEARCH/FT.AGGREGATE/FT.INFO/FT.SPELLCHECK/FT.SYNDUMPresponses with backwards compatibility for RESP2 (#3741) by @ndyakov - INCREX: New
INCREXcommand support — atomic increment with expiration (#3816) by @ndyakov - XNACK: Client support for the
XNACKstream command for explicitly negative-acknowledging pending entries (#3790) by @elena-kolevska - TS range multiple aggregators:
TS.RANGE/TS.REVRANGE/TS.MRANGE/TS.MREVRANGEnow accept multiple aggregators in a single call (#3791) by @elena-kolevska XAutoClaimdeleted IDs:XAUTOCLAIM/XAUTOCLAIMJUSTIDnow return the list of deleted message IDs from the PEL (#3798) by @KhukharrJSON.SET FPHA:JSON.SETaccepts a newFPHAargument that specifies the floating-point type for homogeneous floating-point arrays (#3797) by @ndyakov- Sorted-set union/intersection COUNT:
ZUNION/ZINTER/ZDIFFaggregator now supportsCOUNT(#3802) by @ofekshenawa FT.HYBRIDvector validation: Validates hybrid-search vector input types and adds proper typed vector parameters (#3756) by @DengY11- Cluster pool wait stats:
ClusterClient.PoolStats()now accumulatesWaitCountandWaitDurationNsacross all node pools (previously always zero) (#3809) by @LINKIWI
- TLS-only Cluster PubSub:
CLUSTER SLOTSport-0 entries now fall back to the origin endpoint's port, fixingdial tcp <ip>:0: connection refusedon TLS-only clusters started with--port 0 --tls-port <port>(fixes #3726) (#3828) by @ndyakov - Sharded PubSub reconnect routing:
PubSub.conn()now passes both regular (c.channels) and sharded (c.schannels) channels into the per-PubSubnewConnclosure. Previously,ClusterClient.SSubscribe-only PubSubs reconnected to a random node (because the routing closure saw an empty channel list), theSSUBSCRIBEwas sent to the wrong shard, and the resultingMOVEDreply was silently dropped (#3829) by @ndyakov - ClusterClient
Watchretry: User errors returned from aWatchcallback are no longer subjected to cluster-retry classification; transient cluster errors still retry, but a callback returning e.g.net.ErrClosedshort-circuits immediately (#3821) by @obiyang - Sentinel concurrent-probe leak:
MasterAddr's concurrent sentinel probe now closes the non-winning sentinel clients instead of leaking them (#3827) by @cxljs - Sentinel rediscovery loop on master-only setups:
replicaAddrsno longer tears down the cached sentinel client when the replica list is empty, eliminating a continuous rediscovery loop on master-only Sentinel deployments that flooded logs and added per-operation latency (#3795) by @shahyash2609 - Pool
CloseConnhooks:Pool.CloseConnnow triggers registered hooks, fixing a memory leak when connections are closed explicitly rather than via the normal removal path (#3818) by @ndyakov - Dial TCP error redirection: Wrapped
dial tcperrors are now correctly classified as redirectable so cluster routing can recover from a single unreachable node (#3810) by @vladisa88 - Pool
Closehealth checks:ConnPool.Closenow only runs health checks against idle connections, avoiding spurious activity on connections still in use (#3805) by @ndyakov - VLinks return type: Fixed the return type of
VLINKS/VLINKSWITHSCORESvector-set replies (#3820) by @romanpovol
- Flaky tests: Stabilized several flaky tests in the sentinel and pool suites (#3815) by @ndyakov
- Sentinel failover metric race: Fixed a data race in the sentinel failover metric test (#3824) by @cxljs
waitForSentinelClusterStablepost-conditions: The sentinel test harness now waits for replicas to be fully connected (not just present in the count) and is robust to randomized spec ordering after failover specs, eliminating an intermittentExpected master to equal slaveflake (#3830) by @ndyakovgovulncheckworkflow: New scheduled GitHub Actions workflow runsgovulncheckon every push, PR, and weekly, surfacing newly disclosed Go vulnerabilities even when no code changes (#3779) by @solardome- CI Redis 8.8-rc1: CI now exercises the 8.8-rc1 Redis image (#3814) by @ofekshenawa
Cmd.Slot()lookup refactor: Caches the per-commandCommandInfoand short-circuits keyless commands before the switch dispatch, removing redundantPeekcalls (#3804) by @retr0-kernel- stdlib
math/rand: Replacedinternal/randwithmath/randfrom the standard library now that the minimum Go version is 1.24 (#3823) by @cxljs - ConnPool queue channel: Removed the unused queue channel from
ConnPool, trimming the pool's footprint (#3826) by @cxljs - Extra packages LICENSE: Added a LICENSE file to each
extra/*package (#3817) by @ndyakov - README & CI image: Documentation refresh and bumped the default CI image tag (#3822) by @ndyakov
We'd like to thank all the contributors who worked on this release!
@cxljs, @DengY11, @elena-kolevska, @Khukharr, @LINKIWI, @ndyakov, @obiyang, @ofekshenawa, @retr0-kernel, @romanpovol, @shahyash2609, @solardome, @vladisa88
Full Changelog: https://github.com/redis/go-redis/compare/v9.19.0...v9.20.0
9.19.0
Script now supports a FIPS-safe execution mode that avoids client-side SHA-1 computation, which is blocked in strict FIPS environments. A new NewScriptServerSHA constructor uses SCRIPT LOAD to obtain and cache the digest from the server, then runs commands via EVALSHA/EVALSHA_RO. Falls back to EVAL/EVALRO if loading fails, and transparently retries once on NOSCRIPT. The default behavior is unchanged for existing users.
(#3700) by @chaitanyabodlapati
Added a new step-based FT.AGGREGATE pipeline API via FTAggregateOptions.Steps, allowing LOAD, APPLY, GROUPBY, and SORTBY (with per-step MAX) to be repeated and interleaved in arbitrary order — matching Redis's native multi-stage aggregation semantics. The legacy Load/Apply/GroupBy/SortBy/SortByMax fields are now deprecated.
Added DoRaw and DoRawWriteTo methods for executing arbitrary commands and reading the raw RESP response. Useful for proxying, custom protocol inspection, and working with commands not yet wrapped by go-redis.
(#3713) by @ofekshenawa
Added DialerRetryBackoff option (plumbed through Options, ClusterOptions, RingOptions, FailoverOptions) to let callers customize the delay between failed dial attempts. Helpers DialRetryBackoffConstant and DialRetryBackoffExponential (with jitter and cap) are provided out of the box. Dial timeout is now also applied per attempt rather than across all retries.
- FT.AGGREGATE Steps: Step-based pipeline builder for
FT.AGGREGATEwith support for repeated/interleavedLOAD,APPLY,GROUPBY, andSORTBYstages (#3782) by @ndyakov - VectorSet commands: Added
VISMEMBERandWITHATTRIBSsupport (#3753) by @romanpovol - FIPS-safe Script:
NewScriptServerSHAusesSCRIPT LOADto obtain the digest from the server, avoiding client-side SHA-1 (#3700) by @chaitanyabodlapati - Raw RESP access:
DoRawandDoRawWriteTofor raw RESP protocol access (#3713) by @ofekshenawa - Dial retry backoff:
DialerRetryBackofffunction option with constant and exponential helpers (#3706) by @mwhooker - Typed NOSCRIPT error: Redis
NOSCRIPTreplies are now surfaced as a typed error for easier handling (#3738) by @LINKIWI - PubSub ClientSetName: Added
ClientSetNamemethod toPubSub(#3727) by @Flack74 - ReplicaOf: New
ReplicaOfmethod replaces the deprecatedSlaveOf(#3720) by @Copilot - HSCAN BinaryUnmarshaler:
HScannow supports types implementingencoding.BinaryUnmarshaler(#3768) by @Aaditya-dubey1
- Auto hostname type detection: Improved endpoint type detection for maintenance notifications using DNS-based classification; handles empty hosts and expanded private-IP ranges (#3789) by @ndyakov
- HELLO fallback: Don't send
CLIENT MAINT_NOTIFICATIONShandshake whenHELLOfails and connection falls back to RESP2; fail fast when explicitly enabled with RESP3 (#3788) by @ndyakov - Dial TCP retry:
ShouldRetrynow treatsnet.OpErrorwithOp == "dial"timeout errors as safe to retry since no command was sent (#3787) by @vladisa88 - wrappedOnClose leak: Fixed resource leak caused by repeatedly wrapping
baseClientclose logic; replaced with a bounded, concurrency-safe named-hook registry (#3785) by @ndyakov - Pool Close() on stale connections: Suppress close errors (e.g., TLS
closeNotifytimeouts) for connections already dropped by the server due to idle timeout (#3778) by @ofekshenawa - FIFO waiter ordering: Fixed race in
ConnStateMachine.notifyWaitersthat could wake multiple waiters under a single mutex hold and violate FIFO ordering (#3777) by @0x48core - Lua READONLY detection: Detect
READONLYerrors embedded in Lua script error messages on read-only replicas so commands are correctly retried (#3769) by @zhengjilei - VectorScoreSliceCmd RESP2: Fixed
VSimWithScores,VSimWithArgsWithScores, andVLinksWithScoreswhich were broken on RESP2 connections returning flat arrays instead of maps (#3767) by @Copilot - Closed connection handling: Two fixes for closed connection handling in the pool (#3764) by @cxljs
- ZRangeArgs Rev: Fixed
ZRangeArgswithRev+ByScore/ByLexincorrectly swappingStart/Stop, breakingZRANGESTORE(#3751) by @Copilot - OTel metric instrument types: Fixed metric instrument types in
redisotel-native(#3743) by @ofekshenawa - Options.clone() data race: Fixed data race when cloning
Options(#3739) by @rubensayshi - Connection closure metrics: Fixed connection closure metrics and enabled all metric groups by default in
redisotel-native(#3735) by @ofekshenawa - OTel semconv v1.38.0: Use metric definition from
otel/semconv/v1.38.0inredisotel-native(#3731) by @wzy9607 - SETNX semantics: Use
SET ... NXinstead of the deprecatedSETNXcommand (#3723) by @ndyakov - TIME keyless routing: Mark
TIMEas a keyless command for correct cluster routing (#3722) by @fatal10110 - Dial timeout per retry: Dial timeout now applies per attempt instead of across all retry attempts combined (#3705) by @mwhooker
- Cluster metrics attributes: Fixed
pool.namebeing appended per node, which corrupted and dropped user-provided custom attributes (#3699) by @Jesse-Bonfire - initConn nil dereference: Fixed nil pointer dereference and potential deadlock in
*baseClient.initConn(); added explicit nil option guards to client constructors (#3676) by @olde-ducke
- RESP reader: Optimized RESP reader by eliminating intermediate string allocations (#3774) by @Aaditya-dubey1
- Inline rendezvous hashing: Replaced
github.com/dgryski/go-rendezvousdependency with an in-repo implementation ininternal/hashtag, reducing the dependency graph while preserving algorithm parity (#3762) by @bigsk05
- Release automation: Added
repository,ref, andclient-libs-test-image-taginputs to therun-testscomposite action;redis-versionis now optional so unstable builds useREDIS_VERSIONfrom the Makefile (#3749) by @dariaguy - Go 1.24: Updated minimum Go version to 1.24 and use
-compat=1.24in release scripts (#3714, #3754) by @ndyakov, @cxljs
- Pool state machine: Removed redundant
Conn.closedatomic field in favor of the state machine'sStateClosed(#3783) by @cxljs - OTel SDK: Updated OpenTelemetry SDK dependencies in
redisotel/redisotel-native(#3770) by @ndyakov - Go 1.21+ built-ins: Use
maps.Keys,slices.Collect,slices.Contains,clear(), andslices.SortFuncinstead of custom helpers (#3758, #3746) by @cxljs - HGetAll docs: Added Go doc comment to
HGetAlldescribing behavior and complexity (#3776) by @0x48core - Docs links: Fixed irrelevant docs links (#3724) by @olzhas-sabiyev
- Examples cleanup: Removed throughput binary from examples (#3733) by @ndyakov
We'd like to thank all the contributors who worked on this release!
@0x48core, @Aaditya-dubey1, @Copilot, @Flack74, @Jesse-Bonfire, @LINKIWI, @bigsk05, @chaitanyabodlapati, @cxljs, @dariaguy, @fatal10110, @mwhooker, @ndyakov, @ofekshenawa, @olde-ducke, @olzhas-sabiyev, @romanpovol, @rubensayshi, @vladisa88, @wzy9607, @zhengjilei
Full Changelog: https://github.com/redis/go-redis/compare/v9.18.0...v9.19.0
9.18.0
Added support for Redis 8.6, including new commands and features for streams idempotent production and HOTKEYS.
note: Pending RS version release
This release introduces comprehensive support for Redis Enterprise Cluster maintenance notifications via SMIGRATING/SMIGRATED push notifications. The client now automatically handles slot migrations by:
- Relaxing timeouts during migration (SMIGRATING) to prevent false failures
- Triggering lazy cluster state reloads upon completion (SMIGRATED)
- Enabling seamless operations during Redis Enterprise maintenance windows
Added comprehensive OpenTelemetry metrics support following the OpenTelemetry Database Client Semantic Conventions. The implementation uses a Bridge Pattern to keep the core library dependency-free while providing optional metrics instrumentation through the new extra/redisotel-native package.
Metric groups include:
- Command metrics: Operation duration with retry tracking
- Connection basic: Connection count and creation time
- Resiliency: Errors, handoffs, timeout relaxation
- Connection advanced: Wait time and use time
- Pubsub metrics: Published and received messages
- Stream metrics: Processing duration and maintenance notifications
(#3637) by @ofekshenawa
- HOTKEYS Commands: Added support for Redis HOTKEYS feature for identifying hot keys based on CPU consumption and network utilization (#3695) by @ofekshenawa
- Streams Idempotent Production: Added support for Redis 8.6+ Streams Idempotent Production with
ProducerID,IdempotentID,IdempotentAutoinXAddArgsand newXCFGSETcommand (#3693) by @ofekshenawa - NaN Values for TimeSeries: Added support for NaN (Not a Number) values in Redis time series commands (#3687) by @ofekshenawa
- DialerRetries Options: Added
DialerRetriesandDialerRetryTimeouttoClusterOptions,RingOptions, andFailoverOptions(#3686) by @naveenchander30 - ConnMaxLifetimeJitter: Added jitter configuration to distribute connection expiration times and prevent thundering herd (#3666) by @cyningsun
- Digest Helper Functions: Added
DigestStringandDigestByteshelper functions for client-side xxh3 hashing compatible with Redis DIGEST command (#3679) by @ofekshenawa - SMIGRATED New Format: Updated SMIGRATED parser to support new format and remember original host:port (#3697) by @ndyakov
- Cluster State Reload Interval: Added cluster state reload interval option for maintenance notifications (#3663) by @ndyakov
- PubSub nil pointer dereference: Fixed nil pointer dereference in PubSub after
WithTimeout()-pubSubPoolis now properly cloned (#3710) by @Copilot - MaintNotificationsConfig nil check: Guard against nil
MaintNotificationsConfigininitConn(#3707) by @veeceey - wantConnQueue zombie elements: Fixed zombie
wantConnelements accumulation inwantConnQueue(#3680) by @cyningsun - XADD/XTRIM approx flag: Fixed XADD and XTRIM to use
=when approx is false (#3684) by @ndyakov - Sentinel timeout retry: When connection to a sentinel times out, attempt to connect to other sentinels (#3654) by @cxljs
- Fuzz test optimization: Eliminated repeated string conversions, used functional approach for cleaner operation selection (#3692) by @feiguoL
- Pre-allocate capacity: Pre-allocate slice capacity to prevent multiple capacity expansions (#3689) by @feelshu
- Comprehensive TLS tests: Added comprehensive TLS tests and example for standalone, cluster, and certificate authentication (#3681) by @ndyakov
- Redis 8.6: Updated CI to use Redis 8.6-pre (#3685) by @ndyakov
- Deprecation warnings: Added deprecation warnings for commands based on Redis documentation (#3673) by @ndyakov
- Use errors.Join(): Replaced custom error join function with standard library
errors.Join()(#3653) by @cxljs - Use Go 1.21 min/max: Use Go 1.21's built-in min/max functions (#3656) by @cxljs
- Proper formatting: Code formatting improvements (#3670) by @12ya
- Set commands documentation: Added comprehensive documentation to all set command methods (#3642) by @iamamirsalehi
- MaxActiveConns docs: Added default value documentation for
MaxActiveConns(#3674) by @codykaup - README example update: Updated README example (#3657) by @cxljs
- Cluster maintnotif example: Added example application for cluster maintenance notifications (#3651) by @ndyakov
We'd like to thank all the contributors who worked on this release!
@12ya, @Copilot, @codykaup, @cxljs, @cyningsun, @feelshu, @feiguoL, @iamamirsalehi, @naveenchander30, @ndyakov, @ofekshenawa, @veeceey
9.17.3
- Connection Pool: Fixed zombie
wantConnelements accumulation inwantConnQueuethat could cause resource leaks in high concurrency scenarios with dial failures (#3680) by @cyningsun - Stream Commands: Fixed
XADDandXTRIMcommands to use exact threshold (=) whenApproxis false, ensuring precise stream trimming behavior (#3684) by @ndyakov - Connection Pool: Added
ConnMaxLifetimeJitterconfiguration to distribute connection expiration times and prevent the thundering herd problem when many connections expire simultaneously (#3666) by @cyningsun - Client Options: Added
DialerRetriesandDialerRetryTimeoutfields toClusterOptions,RingOptions, andFailoverOptionsto allow configuring connection retry behavior for cluster, ring, and sentinel clients (#3686) by @naveenchander30
We'd like to thank all the contributors who worked on this release!
@cyningsun, @naveenchander30, and @ndyakov
Full Changelog: https://github.com/redis/go-redis/compare/v9.17.2...v9.17.3
9.18.0-beta.2
This release updates the minimum required Go version to 1.21. This is part of a gradual migration strategy where the minimum supported Go version will be three versions behind the latest release. With each new Go version release, we will bump the minimum version by one, ensuring compatibility while staying current with the Go ecosystem.
This release includes several important stability fixes:
- Fixed a critical panic in the handoff worker manager that could occur when handling nil errors
- Improved test reliability for Smart Client Handoff functionality
- Fixed logging format issues that could cause runtime errors
- Fixed panic on nil error in handoffWorkerManager closeConnFromRequest (#3633) by @ccoVeille
- Fixed bad sprintf syntax in logging (#3632) by @ccoVeille
- Updated minimum Go version to 1.21 (#3640) by @ndyakov
- Use Go 1.20 idiomatic string<->byte conversion (#3435) by @justinhwang
- Reduce flakiness of Smart Client Handoff test (#3641) by @kiryazovi-redis
- Revert PR #3634 (Observability metrics phase1) (#3635) by @ofekshenawa
We'd like to thank all the contributors who worked on this release!
@justinhwang, @ndyakov, @kiryazovi-redis, @fengve, @ccoVeille, @ofekshenawa
9.18.0-beta.1
This beta release introduces comprehensive support for Redis COMMAND-based request and response policy routing for cluster clients. This feature enables intelligent command routing and response aggregation based on Redis command metadata.
Key Features:
- Command Policy Loader: Automatically parses and caches COMMAND metadata with routing/aggregation hints
- Enhanced Routing Engine: Supports all request policies including:
default(keyless)- Commands without keysdefault(hashslot)- Commands with hash slot routingall_shards- Commands that need to run on all shardsall_nodes- Commands that need to run on all nodesmulti_shard- Commands that span multiple shardsspecial- Commands with custom routing logic
- Response Aggregator: Intelligently combines multi-shard replies based on response policies:
all_succeeded- All shards must succeedone_succeeded- At least one shard must succeedagg_sum- Aggregate numeric responsesspecial- Custom aggregation logic (e.g., FT.CURSOR)
- Raw Command Support: Policies are enforced on
Client.Do(ctx, args...)
This feature is particularly useful for Redis Stack commands like RediSearch that need to operate across multiple shards in a cluster.
Fixed a critical defect in the connection pool's turn management mechanism that could lead to connection leaks under certain conditions. The fix ensures proper 1:1 correspondence between turns and connections.
- Request and Response Policy Based Routing in Cluster Mode (#3422) by @ofekshenawa
- Fixed connection pool turn management to prevent connection leaks (#3626) by @cyningsun
- chore(deps): bump rojopolis/spellcheck-github-actions from 0.54.0 to 0.55.0 (#3627)
We'd like to thank all the contributors who worked on this release!
9.17.2
- Connection Pool: Fixed critical race condition in turn management that could cause connection leaks when dial goroutines complete after request timeout (#3626) by @cyningsun
- Context Timeout: Improved context timeout calculation to use minimum of remaining time and DialTimeout, preventing goroutines from waiting longer than necessary (#3626) by @cyningsun
- chore(deps): bump rojopolis/spellcheck-github-actions from 0.54.0 to 0.55.0 (#3627)
We'd like to thank all the contributors who worked on this release!
@cyningsun and @ndyakov
9.17.1
- add wait to keyless commands list (#3615) by @marcoferrer
- fix(time): remove cached time optimization (#3611) by @ndyakov
- chore(deps): bump golangci/golangci-lint-action from 9.0.0 to 9.1.0 (#3609)
- chore(deps): bump actions/checkout from 5 to 6 (#3610)
- chore(script): fix help call in tag.sh (#3606) by @ndyakov
We'd like to thank all the contributors who worked on this release!
@marcoferrer and @ndyakov