Redis Provider¶
The Redis provider offers a robust Redis client implementation with connection management, secure credential handling, TLS support, and key-value operations with TTL management.
Features¶
- Connection Management: Automatic connection handling with health checking
- Secure Credentials: Support for password encryption and secure storage
- TLS Support: Optional TLS encryption for secure connections
- Key Prefixing: Automatic key prefixing for namespace isolation
- TTL Management: Configurable time-to-live for keys with custom TTL support
- Context-Aware: All operations support context for timeout and cancellation
- KV Interface: Compatible with Blueprint's key-value interface
Installation¶
Configuration¶
Basic Configuration¶
package main
import (
"github.com/oddbit-project/blueprint/provider/redis"
)
func main() {
// Create default configuration
config := redis.NewConfig()
config.Address = "localhost:6379"
config.DB = 0
config.Password = "your-redis-password"
config.TTL = 3600 // 1 hour default TTL
config.TimeoutSeconds = 10
config.KeyPrefix = "myapp:"
// Create client
client, err := redis.NewClient(config)
if err != nil {
panic(err)
}
defer client.Close()
}
JSON Configuration¶
{
"redis": {
"address": "localhost:6379",
"db": 0,
"keyPrefix": "myapp:",
"ttl": 3600,
"timeoutSeconds": 10,
"password": "your-redis-password"
}
}
Configuration with Secure Credentials¶
config := redis.NewConfig()
config.Address = "redis.example.com:6379"
config.DefaultCredentialConfig = secure.DefaultCredentialConfig{
PasswordEnvVar: "REDIS_PASSWORD", // Read from environment
PasswordFile: "/secrets/redis_pwd", // Or read from file
}
TLS Configuration¶
The TLS settings are a tls.ClientConfig embedded in the Redis Config; they are applied to the
connection only when TLSEnable is true, and setting any of them (TLSCA, TLSCert, TLSKey,
TLSInsecureSkipVerify or a key password) without it makes Validate() fail with
tls.ErrTLSNotEnabled, instead of connecting without them in plaintext (#116).
With TLSEnable, TLSCert and TLSKey must be set together, and a key password requires both:
otherwise Validate() fails with tls.ErrTLSIncompleteKeyPair, instead of connecting without the
client certificate (#115).
config := redis.NewConfig()
config.Address = "redis.example.com:6380"
config.ClientConfig = tls.ClientConfig{
TLSEnable: true,
TLSCA: "/path/to/ca.crt", // CA used to verify the server certificate
TLSCert: "/path/to/client.crt", // optional client certificate (mTLS)
TLSKey: "/path/to/client.key", // optional client key (mTLS)
}
Configuration Options¶
| Field | Type | Default | Description |
|---|---|---|---|
Address |
string |
"localhost:6379" |
Redis server address |
DB |
int |
0 |
Redis database number |
KeyPrefix |
string |
"" |
Prefix for all keys |
TTL |
uint |
2592000 (30 days) |
Default TTL in seconds |
TimeoutSeconds |
uint |
10 |
Operation timeout in seconds |
Password |
string |
"" |
Redis password |
PasswordEnvVar |
string |
"" |
Environment variable for password |
PasswordFile |
string |
"" |
File path containing password |
TLSEnable |
bool |
false |
Enable TLS encryption |
TLSCA |
string |
"" |
CA certificate file used to verify the server |
TLSCert |
string |
"" |
Client certificate file (mTLS) |
TLSKey |
string |
"" |
Client key file (mTLS) |
TLSInsecureSkipVerify |
bool |
false |
Skip server certificate verification (testing only) |
The JSON keys for the TLS fields are tlsEnable, tlsCa, tlsCert, tlsKey, tlsInsecureSkipVerify,
and tlsKeyPassword/tlsKeyPasswordEnvVar/tlsKeyPasswordFile for an encrypted client key.
Usage Examples¶
Basic Key-Value Operations¶
package main
import (
"fmt"
"log"
"github.com/oddbit-project/blueprint/provider/redis"
)
func main() {
config := redis.NewConfig()
config.Address = "localhost:6379"
client, err := redis.NewClient(config)
if err != nil {
log.Fatal(err)
}
defer client.Close()
// Connect to Redis
if err := client.Connect(); err != nil {
log.Fatal("Failed to connect:", err)
}
// Set a value
err = client.Set("user:123", []byte("John Doe"))
if err != nil {
log.Fatal("Failed to set:", err)
}
// Get a value
data, err := client.Get("user:123")
if err != nil {
log.Fatal("Failed to get:", err)
}
if data != nil {
fmt.Printf("Retrieved: %s\n", string(data))
} else {
fmt.Println("Key not found")
}
// Delete a key
err = client.Delete("user:123")
if err != nil {
log.Fatal("Failed to delete:", err)
}
}
Custom TTL Operations¶
import "time"
// Set with custom TTL (5 minutes)
err := client.SetTTL("session:abc123", []byte("session-data"), 5*time.Minute)
if err != nil {
log.Fatal(err)
}
// Check default TTL
defaultTTL := client.TTL()
fmt.Printf("Default TTL: %v\n", defaultTTL)
Key Prefixing¶
config := redis.NewConfig()
config.KeyPrefix = "myapp:"
client, _ := redis.NewClient(config)
// This will store the key as "myapp:user:123"
client.Set("user:123", []byte("data"))
// You can also manually construct keys
key := client.Key("custom:key") // Returns "myapp:custom:key"
Using as KV Backend¶
The Redis client implements Blueprint's kv.KV interface, and kv.AtomicSetter (SetNX), so it can
be passed to any component that takes a kv.KV backend:
import (
"time"
"github.com/oddbit-project/blueprint/provider/hmacprovider/store"
"github.com/oddbit-project/blueprint/provider/kv"
"github.com/oddbit-project/blueprint/provider/redis"
)
client, err := redis.NewClient(redis.NewConfig())
if err != nil {
log.Fatal(err)
}
var backend kv.KV = client
// e.g. as the backend of a generic KV nonce store; SetNX makes the nonce check atomic
nonceStore := store.NewKvStore(backend, time.Hour)
Connection Health Checking¶
client, _ := redis.NewClient(config)
// Test connection
if err := client.Connect(); err != nil {
log.Printf("Redis connection failed: %v", err)
// Handle connection failure
} else {
log.Println("Redis connection successful")
}
Expiration and Prune¶
Redis expires keys itself, so Prune() is a no-op that always returns nil; it exists only to satisfy
the kv.KV interface (the session store calls it on every cleanup tick). Use SetTTL to control
expiry per key; a TTL of 0 stores the key without expiry. Set uses the configured default TTL.
Security Considerations¶
Credential Management¶
// Use environment variables
config.PasswordEnvVar = "REDIS_PASSWORD"
// Use secure file storage
config.PasswordFile = "/run/secrets/redis_password"
The password is decrypted once in NewClient and handed to the go-redis client, which keeps it in its
options to authenticate new pool connections.
TLS Security¶
config.ClientConfig = tls.ClientConfig{
TLSEnable: true,
TLSCA: "/path/to/ca.crt", // verify the server against this CA
}
The server certificate is verified against TLSCA (or the system roots when empty) and the host in
Address. Leave TLSInsecureSkipVerify off outside of testing. Minimum version and cipher suites use the
Go crypto/tls client defaults; they are not configurable on the Redis client.
Key Security¶
- Use key prefixes to isolate different applications
- Implement appropriate TTL values to prevent key accumulation
- Consider using Redis AUTH for additional security
Integration Examples¶
With HTTP Server Session Storage¶
import (
"github.com/oddbit-project/blueprint/log"
"github.com/oddbit-project/blueprint/provider/httpserver"
"github.com/oddbit-project/blueprint/provider/httpserver/session"
"github.com/oddbit-project/blueprint/provider/redis"
)
logger := log.New("app")
// Use Redis as session backend
redisClient, err := redis.NewClient(redis.NewConfig())
if err != nil {
logger.Fatal(err, "failed to create redis client")
}
server, err := httpserver.NewServer(httpserver.NewServerConfig(), logger)
if err != nil {
logger.Fatal(err, "failed to create server")
}
// UseSession registers the session middleware and returns the session manager
sessionManager, err := server.UseSession(session.NewConfig(), redisClient, logger)
if err != nil {
logger.Fatal(err, "failed to enable sessions")
}
The session store calls Prune() on every cleanup tick; with Redis this is a no-op, and sessions
expire through the TTL set on each key.
With HMAC Provider for Nonce Storage¶
import (
"time"
"github.com/oddbit-project/blueprint/provider/hmacprovider"
"github.com/oddbit-project/blueprint/provider/hmacprovider/store"
"github.com/oddbit-project/blueprint/provider/redis"
)
redisClient, err := redis.NewClient(redis.NewConfig())
if err != nil {
log.Fatal(err)
}
// SetNX-based nonce store; keys are "nonce:<nonce>" by default (see store.WithPrefix)
nonceStore := store.NewRedisNonceStore(redisClient, time.Hour)
hmacProvider := hmacprovider.NewHmacProvider(keyProvider, hmacprovider.WithNonceStore(nonceStore))
Error Handling¶
The Redis provider handles various error conditions:
data, err := client.Get("nonexistent")
if err != nil {
log.Fatal("Error:", err)
}
if data == nil {
fmt.Println("Key not found")
} else {
fmt.Printf("Data: %s\n", data)
}
Best Practices¶
- Connection Management: Always call
Close()to properly cleanup connections - Error Handling: Check for connection errors and implement retry logic
- TTL Management: Set appropriate TTL values to prevent memory bloat
- Key Naming: Use consistent key naming conventions and prefixes
- Security: Use TLS for production deployments and secure credential storage
- Monitoring: Implement connection health checks in production
Performance Considerations¶
- Connection Pooling: The underlying go-redis library handles connection pooling automatically
- TTL Setting: Configure appropriate default TTL to balance data persistence and memory usage
- Key Prefixing: Use prefixes to organize keys and enable efficient pattern matching
- Timeout Configuration: Set reasonable timeouts to prevent hanging operations
Troubleshooting¶
Connection Issues¶
if err := client.Connect(); err != nil {
log.Printf("Redis connection failed: %v", err)
// Check network connectivity, credentials, and Redis server status
}
Common Errors¶
- Missing Address: Ensure
Addressis properly configured - Authentication Failure: Verify password configuration
- Network Timeout: Adjust
TimeoutSecondsfor slow networks - TLS Handshake: Check certificate configuration for TLS connections
See Also¶
- Secure Credentials - For secure password management
- TLS Configuration - For TLS setup and security
- HMAC Provider - For using Redis as nonce storage
- HTTP Server Sessions - For session management integration