mirror of
https://github.com/redis/go-redis.git
synced 2025-10-27 18:15:32 +03:00
@@ -1,5 +1,64 @@
|
||||
# Release Notes
|
||||
|
||||
# 9.16.0 (2025-10-23)
|
||||
|
||||
## 🚀 Highlights
|
||||
|
||||
### Maintenance Notifications Support
|
||||
|
||||
This release introduces comprehensive support for Redis maintenance notifications, enabling applications to handle server maintenance events gracefully. The new `maintnotifications` package provides:
|
||||
|
||||
- **RESP3 Push Notifications**: Full support for Redis RESP3 protocol push notifications
|
||||
- **Connection Handoff**: Automatic connection migration during server maintenance with configurable retry policies and circuit breakers
|
||||
- **Graceful Degradation**: Configurable timeout relaxation during maintenance windows to prevent false failures
|
||||
- **Event-Driven Architecture**: Background workers with on-demand scaling for efficient handoff processing
|
||||
- **Production-Ready**: Comprehensive E2E testing framework and monitoring capabilities
|
||||
|
||||
For detailed usage examples and configuration options, see the [maintenance notifications documentation](maintnotifications/README.md).
|
||||
|
||||
## ✨ New Features
|
||||
|
||||
- **Trace Filtering**: Add support for filtering traces for specific commands, including pipeline operations and dial operations ([#3519](https://github.com/redis/go-redis/pull/3519), [#3550](https://github.com/redis/go-redis/pull/3550))
|
||||
- New `TraceCmdFilter` option to selectively trace commands
|
||||
- Reduces overhead by excluding high-frequency or low-value commands from traces
|
||||
|
||||
## 🐛 Bug Fixes
|
||||
|
||||
- **Pipeline Error Handling**: Fix issue where pipeline repeatedly sets the same error ([#3525](https://github.com/redis/go-redis/pull/3525))
|
||||
- **Connection Pool**: Ensure re-authentication does not interfere with connection handoff operations ([#3547](https://github.com/redis/go-redis/pull/3547))
|
||||
|
||||
## 🔧 Improvements
|
||||
|
||||
- **Hash Commands**: Update hash command implementations ([#3523](https://github.com/redis/go-redis/pull/3523))
|
||||
- **OpenTelemetry**: Use `metric.WithAttributeSet` to avoid unnecessary attribute copying in redisotel ([#3552](https://github.com/redis/go-redis/pull/3552))
|
||||
|
||||
## 📚 Documentation
|
||||
|
||||
- **Cluster Client**: Add explanation for why `MaxRetries` is disabled for `ClusterClient` ([#3551](https://github.com/redis/go-redis/pull/3551))
|
||||
|
||||
## 🧪 Testing & Infrastructure
|
||||
|
||||
- **E2E Testing**: Upgrade E2E testing framework with improved reliability and coverage ([#3541](https://github.com/redis/go-redis/pull/3541))
|
||||
- **Release Process**: Improved resiliency of the release process ([#3530](https://github.com/redis/go-redis/pull/3530))
|
||||
|
||||
## 📦 Dependencies
|
||||
|
||||
- Bump `rojopolis/spellcheck-github-actions` from 0.51.0 to 0.52.0 ([#3520](https://github.com/redis/go-redis/pull/3520))
|
||||
- Bump `github/codeql-action` from 3 to 4 ([#3544](https://github.com/redis/go-redis/pull/3544))
|
||||
|
||||
## 👥 Contributors
|
||||
|
||||
We'd like to thank all the contributors who worked on this release!
|
||||
|
||||
[@ndyakov](https://github.com/ndyakov), [@htemelski-redis](https://github.com/htemelski-redis), [@Sovietaced](https://github.com/Sovietaced), [@Udhayarajan](https://github.com/Udhayarajan), [@boekkooi-impossiblecloud](https://github.com/boekkooi-impossiblecloud), [@Pika-Gopher](https://github.com/Pika-Gopher), [@cxljs](https://github.com/cxljs), [@huiyifyj](https://github.com/huiyifyj), [@omid-h70](https://github.com/omid-h70)
|
||||
|
||||
---
|
||||
|
||||
**Full Changelog**: https://github.com/redis/go-redis/compare/v9.14.0...v9.16.0
|
||||
|
||||
|
||||
# 9.15.0 was accidentally released. Please use version 9.16.0 instead.
|
||||
|
||||
# 9.15.0-beta.3 (2025-09-26)
|
||||
|
||||
## Highlights
|
||||
|
||||
@@ -5,7 +5,7 @@ go 1.18
|
||||
replace github.com/redis/go-redis/v9 => ../..
|
||||
|
||||
require (
|
||||
github.com/redis/go-redis/v9 v9.16.0-beta.1
|
||||
github.com/redis/go-redis/v9 v9.16.0
|
||||
go.uber.org/zap v1.24.0
|
||||
)
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ go 1.18
|
||||
|
||||
replace github.com/redis/go-redis/v9 => ../..
|
||||
|
||||
require github.com/redis/go-redis/v9 v9.16.0-beta.1
|
||||
require github.com/redis/go-redis/v9 v9.16.0
|
||||
|
||||
require (
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
|
||||
@@ -6,7 +6,7 @@ replace github.com/redis/go-redis/v9 => ../..
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/redis/go-redis/v9 v9.16.0-beta.1
|
||||
github.com/redis/go-redis/v9 v9.16.0
|
||||
)
|
||||
|
||||
require (
|
||||
|
||||
@@ -4,7 +4,7 @@ go 1.18
|
||||
|
||||
replace github.com/redis/go-redis/v9 => ../..
|
||||
|
||||
require github.com/redis/go-redis/v9 v9.16.0-beta.1
|
||||
require github.com/redis/go-redis/v9 v9.16.0
|
||||
|
||||
require (
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
|
||||
@@ -11,8 +11,8 @@ replace github.com/redis/go-redis/extra/redisotel/v9 => ../../extra/redisotel
|
||||
replace github.com/redis/go-redis/extra/rediscmd/v9 => ../../extra/rediscmd
|
||||
|
||||
require (
|
||||
github.com/redis/go-redis/extra/redisotel/v9 v9.16.0-beta.1
|
||||
github.com/redis/go-redis/v9 v9.16.0-beta.1
|
||||
github.com/redis/go-redis/extra/redisotel/v9 v9.16.0
|
||||
github.com/redis/go-redis/v9 v9.16.0
|
||||
github.com/uptrace/uptrace-go v1.21.0
|
||||
go.opentelemetry.io/otel v1.22.0
|
||||
)
|
||||
@@ -25,7 +25,7 @@ require (
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect
|
||||
github.com/redis/go-redis/extra/rediscmd/v9 v9.16.0-beta.1 // indirect
|
||||
github.com/redis/go-redis/extra/rediscmd/v9 v9.16.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/runtime v0.46.1 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.44.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 // indirect
|
||||
|
||||
@@ -4,7 +4,7 @@ go 1.18
|
||||
|
||||
replace github.com/redis/go-redis/v9 => ../..
|
||||
|
||||
require github.com/redis/go-redis/v9 v9.16.0-beta.1
|
||||
require github.com/redis/go-redis/v9 v9.16.0
|
||||
|
||||
require (
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
|
||||
@@ -6,7 +6,7 @@ replace github.com/redis/go-redis/v9 => ../..
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/redis/go-redis/v9 v9.16.0-beta.1
|
||||
github.com/redis/go-redis/v9 v9.16.0
|
||||
)
|
||||
|
||||
require (
|
||||
|
||||
@@ -7,8 +7,8 @@ replace github.com/redis/go-redis/v9 => ../..
|
||||
replace github.com/redis/go-redis/extra/rediscmd/v9 => ../rediscmd
|
||||
|
||||
require (
|
||||
github.com/redis/go-redis/extra/rediscmd/v9 v9.16.0-beta.1
|
||||
github.com/redis/go-redis/v9 v9.16.0-beta.1
|
||||
github.com/redis/go-redis/extra/rediscmd/v9 v9.16.0
|
||||
github.com/redis/go-redis/v9 v9.16.0
|
||||
go.opencensus.io v0.24.0
|
||||
)
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ replace github.com/redis/go-redis/v9 => ../..
|
||||
require (
|
||||
github.com/bsm/ginkgo/v2 v2.12.0
|
||||
github.com/bsm/gomega v1.27.10
|
||||
github.com/redis/go-redis/v9 v9.16.0-beta.1
|
||||
github.com/redis/go-redis/v9 v9.16.0
|
||||
)
|
||||
|
||||
require (
|
||||
|
||||
@@ -7,8 +7,8 @@ replace github.com/redis/go-redis/v9 => ../..
|
||||
replace github.com/redis/go-redis/extra/rediscmd/v9 => ../rediscmd
|
||||
|
||||
require (
|
||||
github.com/redis/go-redis/extra/rediscmd/v9 v9.16.0-beta.1
|
||||
github.com/redis/go-redis/v9 v9.16.0-beta.1
|
||||
github.com/redis/go-redis/extra/rediscmd/v9 v9.16.0
|
||||
github.com/redis/go-redis/v9 v9.16.0
|
||||
go.opentelemetry.io/otel v1.22.0
|
||||
go.opentelemetry.io/otel/metric v1.22.0
|
||||
go.opentelemetry.io/otel/sdk v1.22.0
|
||||
|
||||
@@ -6,7 +6,7 @@ replace github.com/redis/go-redis/v9 => ../..
|
||||
|
||||
require (
|
||||
github.com/prometheus/client_golang v1.14.0
|
||||
github.com/redis/go-redis/v9 v9.16.0-beta.1
|
||||
github.com/redis/go-redis/v9 v9.16.0
|
||||
)
|
||||
|
||||
require (
|
||||
|
||||
218
maintnotifications/FEATURES.md
Normal file
218
maintnotifications/FEATURES.md
Normal file
@@ -0,0 +1,218 @@
|
||||
# Maintenance Notifications - FEATURES
|
||||
|
||||
## Overview
|
||||
|
||||
The Maintenance Notifications feature enables seamless Redis connection handoffs during cluster maintenance operations without dropping active connections. This feature leverages Redis RESP3 push notifications to provide zero-downtime maintenance for Redis Enterprise and compatible Redis deployments.
|
||||
|
||||
## Important
|
||||
|
||||
Using Maintenance Notifications may affect the read and write timeouts by relaxing them during maintenance operations.
|
||||
This is necessary to prevent false failures due to increased latency during handoffs. The relaxed timeouts are automatically applied and removed as needed.
|
||||
|
||||
## Key Features
|
||||
|
||||
### Seamless Connection Handoffs
|
||||
- **Zero-Downtime Maintenance**: Automatically handles connection transitions during cluster operations
|
||||
- **Active Operation Preservation**: Transfers in-flight operations to new connections without interruption
|
||||
- **Graceful Degradation**: Falls back to standard reconnection if handoff fails
|
||||
|
||||
### Push Notification Support
|
||||
Supports all Redis Enterprise maintenance notification types:
|
||||
- **MOVING** - Slot moving to a new node
|
||||
- **MIGRATING** - Slot in migration state
|
||||
- **MIGRATED** - Migration completed
|
||||
- **FAILING_OVER** - Node failing over
|
||||
- **FAILED_OVER** - Failover completed
|
||||
|
||||
### Circuit Breaker Pattern
|
||||
- **Endpoint-Specific Failure Tracking**: Prevents repeated connection attempts to failing endpoints
|
||||
- **Automatic Recovery Testing**: Half-open state allows gradual recovery validation
|
||||
- **Configurable Thresholds**: Customize failure thresholds and reset timeouts
|
||||
|
||||
### Flexible Configuration
|
||||
- **Auto-Detection Mode**: Automatically detects server support for maintenance notifications
|
||||
- **Multiple Endpoint Types**: Support for internal/external IP/FQDN endpoint resolution
|
||||
- **Auto-Scaling Workers**: Automatically sizes worker pool based on connection pool size
|
||||
- **Timeout Management**: Separate timeouts for relaxed (during maintenance) and normal operations
|
||||
|
||||
### Extensible Hook System
|
||||
- **Pre/Post Processing Hooks**: Monitor and customize notification handling
|
||||
- **Built-in Hooks**: Logging and metrics collection hooks included
|
||||
- **Custom Hook Support**: Implement custom business logic around maintenance events
|
||||
|
||||
### Comprehensive Monitoring
|
||||
- **Metrics Collection**: Track notification counts, processing times, and error rates
|
||||
- **Circuit Breaker Stats**: Monitor endpoint health and circuit breaker states
|
||||
- **Operation Tracking**: Track active handoff operations and their lifecycle
|
||||
|
||||
## Architecture Highlights
|
||||
|
||||
### Event-Driven Handoff System
|
||||
- **Asynchronous Processing**: Non-blocking handoff operations using worker pool pattern
|
||||
- **Queue-Based Architecture**: Configurable queue size with auto-scaling support
|
||||
- **Retry Mechanism**: Configurable retry attempts with exponential backoff
|
||||
|
||||
### Connection Pool Integration
|
||||
- **Pool Hook Interface**: Seamless integration with go-redis connection pool
|
||||
- **Connection State Management**: Atomic flags for connection usability tracking
|
||||
- **Graceful Shutdown**: Ensures all in-flight handoffs complete before shutdown
|
||||
|
||||
### Thread-Safe Design
|
||||
- **Lock-Free Operations**: Atomic operations for high-performance state tracking
|
||||
- **Concurrent-Safe Maps**: sync.Map for tracking active operations
|
||||
- **Minimal Lock Contention**: Read-write locks only where necessary
|
||||
|
||||
## Configuration Options
|
||||
|
||||
### Operation Modes
|
||||
- **`ModeDisabled`**: Maintenance notifications completely disabled
|
||||
- **`ModeEnabled`**: Forcefully enabled (fails if server doesn't support)
|
||||
- **`ModeAuto`**: Auto-detect server support (recommended default)
|
||||
|
||||
### Endpoint Types
|
||||
- **`EndpointTypeAuto`**: Auto-detect based on current connection
|
||||
- **`EndpointTypeInternalIP`**: Use internal IP addresses
|
||||
- **`EndpointTypeInternalFQDN`**: Use internal fully qualified domain names
|
||||
- **`EndpointTypeExternalIP`**: Use external IP addresses
|
||||
- **`EndpointTypeExternalFQDN`**: Use external fully qualified domain names
|
||||
- **`EndpointTypeNone`**: No endpoint (reconnect with current configuration)
|
||||
|
||||
### Timeout Configuration
|
||||
- **`RelaxedTimeout`**: Extended timeout during maintenance operations (default: 10s)
|
||||
- **`HandoffTimeout`**: Maximum time for handoff completion (default: 15s)
|
||||
- **`PostHandoffRelaxedDuration`**: Relaxed period after handoff (default: 2×RelaxedTimeout)
|
||||
|
||||
### Worker Pool Configuration
|
||||
- **`MaxWorkers`**: Maximum concurrent handoff workers (auto-calculated if 0)
|
||||
- **`HandoffQueueSize`**: Handoff queue capacity (auto-calculated if 0)
|
||||
- **`MaxHandoffRetries`**: Maximum retry attempts for failed handoffs (default: 3)
|
||||
|
||||
### Circuit Breaker Configuration
|
||||
- **`CircuitBreakerFailureThreshold`**: Failures before opening circuit (default: 5)
|
||||
- **`CircuitBreakerResetTimeout`**: Time before testing recovery (default: 60s)
|
||||
- **`CircuitBreakerMaxRequests`**: Max requests in half-open state (default: 3)
|
||||
|
||||
## Auto-Scaling Formulas
|
||||
|
||||
### Worker Pool Sizing
|
||||
When `MaxWorkers = 0` (auto-calculate):
|
||||
```
|
||||
MaxWorkers = min(PoolSize/2, max(10, PoolSize/3))
|
||||
```
|
||||
|
||||
### Queue Sizing
|
||||
When `HandoffQueueSize = 0` (auto-calculate):
|
||||
```
|
||||
QueueSize = max(20 × MaxWorkers, PoolSize)
|
||||
Capped by: min(MaxActiveConns + 1, 5 × PoolSize)
|
||||
```
|
||||
|
||||
### Examples
|
||||
- **Pool Size 100**: 33 workers, 660 queue (capped at 500)
|
||||
- **Pool Size 100 + MaxActiveConns 150**: 33 workers, 151 queue
|
||||
- **Pool Size 50**: 16 workers, 320 queue (capped at 250)
|
||||
|
||||
## Performance Characteristics
|
||||
|
||||
### Throughput
|
||||
- **Non-Blocking Handoffs**: Client operations continue during handoffs
|
||||
- **Concurrent Processing**: Multiple handoffs processed in parallel
|
||||
- **Minimal Overhead**: Lock-free atomic operations for state tracking
|
||||
|
||||
### Latency
|
||||
- **Relaxed Timeouts**: Extended timeouts during maintenance prevent false failures
|
||||
- **Fast Path**: Connections not undergoing handoff have zero overhead
|
||||
- **Graceful Degradation**: Failed handoffs fall back to standard reconnection
|
||||
|
||||
### Resource Usage
|
||||
- **Memory Efficient**: Bounded queue sizes prevent memory exhaustion
|
||||
- **Worker Pool**: Fixed worker count prevents goroutine explosion
|
||||
- **Connection Reuse**: Handoff reuses existing connection objects
|
||||
|
||||
## Testing
|
||||
|
||||
### Unit Tests
|
||||
- Comprehensive unit test coverage for all components
|
||||
- Mock-based testing for isolation
|
||||
- Concurrent operation testing
|
||||
|
||||
### Integration Tests
|
||||
- Pool integration tests with real connection handoffs
|
||||
- Circuit breaker behavior validation
|
||||
- Hook system integration testing
|
||||
|
||||
### E2E Tests
|
||||
- Real Redis Enterprise cluster testing
|
||||
- Multiple scenario coverage (timeouts, endpoint types, stress tests)
|
||||
- Fault injection testing
|
||||
- TLS configuration testing
|
||||
|
||||
## Compatibility
|
||||
|
||||
### Requirements
|
||||
- **Redis Protocol**: RESP3 required for push notifications
|
||||
- **Redis Version**: Redis Enterprise or compatible Redis with maintenance notifications
|
||||
- **Go Version**: Go 1.18+ (uses generics and atomic types)
|
||||
|
||||
### Client Support
|
||||
#### Currently Supported
|
||||
- **Standalone Client** (`redis.NewClient`)
|
||||
|
||||
#### Planned Support
|
||||
- **Cluster Client** (not yet supported)
|
||||
|
||||
#### Will Not Support
|
||||
- **Failover Client** (no planned support)
|
||||
- **Ring Client** (no planned support)
|
||||
|
||||
## Migration Guide
|
||||
|
||||
### Enabling Maintenance Notifications
|
||||
|
||||
**Before:**
|
||||
```go
|
||||
client := redis.NewClient(&redis.Options{
|
||||
Addr: "localhost:6379",
|
||||
Protocol: 2, // RESP2
|
||||
})
|
||||
```
|
||||
|
||||
**After:**
|
||||
```go
|
||||
client := redis.NewClient(&redis.Options{
|
||||
Addr: "localhost:6379",
|
||||
Protocol: 3, // RESP3 required
|
||||
MaintNotificationsConfig: &maintnotifications.Config{
|
||||
Mode: maintnotifications.ModeAuto,
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
### Adding Monitoring
|
||||
|
||||
```go
|
||||
// Get the manager from the client
|
||||
manager := client.GetMaintNotificationsManager()
|
||||
if manager != nil {
|
||||
// Add logging hook
|
||||
loggingHook := maintnotifications.NewLoggingHook(2) // Info level
|
||||
manager.AddNotificationHook(loggingHook)
|
||||
|
||||
// Add metrics hook
|
||||
metricsHook := maintnotifications.NewMetricsHook()
|
||||
manager.AddNotificationHook(metricsHook)
|
||||
}
|
||||
```
|
||||
|
||||
## Known Limitations
|
||||
|
||||
1. **Standalone Only**: Currently only supported in standalone Redis clients
|
||||
2. **RESP3 Required**: Push notifications require RESP3 protocol
|
||||
3. **Server Support**: Requires Redis Enterprise or compatible Redis with maintenance notifications
|
||||
4. **Single Connection Commands**: Some commands (MULTI/EXEC, WATCH) may need special handling
|
||||
5. **No Failover/Ring Client Support**: Failover and Ring clients are not supported and there are no plans to add support
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
- Cluster client support
|
||||
- Enhanced metrics and observability
|
||||
@@ -63,38 +63,5 @@ client := redis.NewClient(&redis.Options{
|
||||
3. Active operations transfer to new connections
|
||||
4. Old connections close gracefully
|
||||
|
||||
## Supported Notifications
|
||||
|
||||
- `MOVING` - Slot moving to new node
|
||||
- `MIGRATING` - Slot in migration state
|
||||
- `MIGRATED` - Migration completed
|
||||
- `FAILING_OVER` - Node failing over
|
||||
- `FAILED_OVER` - Failover completed
|
||||
|
||||
## Hooks (Optional)
|
||||
|
||||
Monitor and customize maintenance notification operations:
|
||||
|
||||
```go
|
||||
type NotificationHook interface {
|
||||
PreHook(ctx, notificationCtx, notificationType, notification) ([]interface{}, bool)
|
||||
PostHook(ctx, notificationCtx, notificationType, notification, result)
|
||||
}
|
||||
|
||||
// Add custom hook
|
||||
manager.AddNotificationHook(&MyHook{})
|
||||
```
|
||||
|
||||
### Metrics Hook Example
|
||||
|
||||
```go
|
||||
// Create metrics hook
|
||||
metricsHook := maintnotifications.NewMetricsHook()
|
||||
manager.AddNotificationHook(metricsHook)
|
||||
|
||||
// Access collected metrics
|
||||
metrics := metricsHook.GetMetrics()
|
||||
fmt.Printf("Notification counts: %v\n", metrics["notification_counts"])
|
||||
fmt.Printf("Processing times: %v\n", metrics["processing_times"])
|
||||
fmt.Printf("Error counts: %v\n", metrics["error_counts"])
|
||||
```
|
||||
## For more information, see [FEATURES](FEATURES.md)
|
||||
|
||||
@@ -2,5 +2,5 @@ package redis
|
||||
|
||||
// Version is the current release version.
|
||||
func Version() string {
|
||||
return "9.16.0-beta.1"
|
||||
return "9.16.0"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user