Documentation
¶
Overview ¶
Package redisclient provides Redis client factories with support for both single-node and cluster modes, plus an integrated caching layer with local memory cache and distributed cache invalidation.
Factory Pattern (Recommended) ¶
Create Redis clients using the factory pattern to support multiple independent clients:
import redisclient "github.com/poly-workshop/go-webmods/redisclient"
func main() {
// Create a Redis client
rdb := redisclient.NewRDB(redisclient.Config{
Urls: []string{"localhost:6379"},
Password: "",
})
// Use Redis client
ctx := context.Background()
rdb.Set(ctx, "key", "value", 0)
val, err := rdb.Get(ctx, "key").Result()
}
The factory pattern allows creating multiple independent Redis clients:
primaryRDB := redisclient.NewRDB(redisclient.Config{
Urls: []string{"primary:6379"},
Password: "secret1",
})
cacheRDB := redisclient.NewRDB(redisclient.Config{
Urls: []string{"cache:6379"},
Password: "secret2",
})
The client automatically detects cluster mode:
- Single URL: Creates a standard Redis client
- Multiple URLs: Creates a Redis cluster client
Redis Cluster example:
rdb := redisclient.NewRDB(redisclient.Config{
Urls: []string{"node1:6379", "node2:6379", "node3:6379"},
Password: "password",
})
Caching Layer ¶
The cache provides a two-level caching system:
- Local in-memory cache (TinyLFU, configurable size and TTL)
- Distributed Redis cache
- Automatic cache invalidation via pub/sub
Factory pattern cache creation (recommended):
import redisclient "github.com/poly-workshop/go-webmods/redisclient"
func main() {
rdb := redisclient.NewRDB(redisclient.Config{
Urls: []string{"localhost:6379"},
Password: "",
})
cache := redisclient.NewCache(redisclient.CacheConfig{
Redis: rdb,
RefreshEventChannel: "myapp:cache:refresh",
LocalCacheSize: 2000,
LocalCacheTTL: 2 * time.Minute,
})
ctx := context.Background()
// Set a value with expiration
err := cache.Set(ctx, "user:123", userData, 5*time.Minute)
// Get a value
var user User
err := cache.Get(ctx, "user:123", &user)
if err != nil {
// Cache miss or error
}
// Delete from cache
err := cache.Delete(ctx, "user:123")
}
Multiple Cache Instances ¶
The factory pattern allows creating multiple independent cache instances:
primaryRDB := redisclient.NewRDB(redisclient.Config{
Urls: []string{"primary:6379"},
})
sessionRDB := redisclient.NewRDB(redisclient.Config{
Urls: []string{"session:6379"},
})
primaryCache := redisclient.NewCache(redisclient.CacheConfig{
Redis: primaryRDB,
RefreshEventChannel: "primary:refresh",
})
sessionCache := redisclient.NewCache(redisclient.CacheConfig{
Redis: sessionRDB,
RefreshEventChannel: "session:refresh",
})
Distributed Cache Invalidation ¶
The cache automatically synchronizes invalidations across multiple instances:
- When Set() or Delete() is called, a cache refresh event is published
- All instances subscribed to the channel receive the event
- Local caches are automatically invalidated
This ensures cache consistency in distributed deployments.
Working with go-redis ¶
The returned redis.UniversalClient supports all standard go-redis operations:
// Strings
rdb.Set(ctx, "key", "value", time.Hour)
rdb.Get(ctx, "key")
// Lists
rdb.LPush(ctx, "queue", "item1", "item2")
rdb.RPop(ctx, "queue")
// Sets
rdb.SAdd(ctx, "tags", "go", "redis")
rdb.SMembers(ctx, "tags")
// Hashes
rdb.HSet(ctx, "user:123", "name", "Alice")
rdb.HGetAll(ctx, "user:123")
// Sorted Sets
rdb.ZAdd(ctx, "leaderboard", redis.Z{Score: 100, Member: "player1"})
rdb.ZRange(ctx, "leaderboard", 0, 9)
// Pub/Sub
pubsub := rdb.Subscribe(ctx, "notifications")
ch := pubsub.Channel()
For more go-redis features, see https://redis.uptrace.dev/
Configuration with Viper ¶
Example configuration file (configs/default.yaml):
redis:
urls:
- localhost:6379
password: ""
Loading configuration:
import (
"github.com/poly-workshop/go-webmods/app"
redisclient "github.com/poly-workshop/go-webmods/redisclient"
)
app.Init(".")
rdb := redisclient.NewRDB(redisclient.Config{
Urls: app.Config().GetStringSlice("redis.urls"),
Password: app.Config().GetString("redis.password"),
})
Best Practices ¶
- Use NewRDB and NewCache factory functions for creating clients
- Create separate Redis clients for different purposes (e.g., cache, sessions, queues)
- Use the cache for frequently accessed, slowly changing data
- Set appropriate expiration times to balance freshness and performance
- Use Redis Cluster for high availability and horizontal scaling
- Monitor cache hit rates and adjust local cache size if needed
- Handle cache misses gracefully (load from primary data source)
- Use different refresh event channels for independent cache instances
Error Handling ¶
- NewRDB panics if no Redis hosts are configured - NewCache panics if Redis client is nil - Cache operations return errors that should be handled:
err := cache.Get(ctx, key, &value)
if err != nil {
// Handle cache miss or error
// Load from database, etc.
}
Example ¶
Example demonstrates basic Redis client usage.
package main
import (
"fmt"
_ "github.com/poly-workshop/go-webmods/redisclient"
)
func main() {
// Configure Redis connection
// redisclient.SetConfig([]string{"localhost:6379"}, "")
//
// // Get Redis client
// rdb := redisclient.GetRDB()
//
// ctx := context.Background()
//
// // Set a value
// err := rdb.Set(ctx, "key", "value", 0).Err()
// if err != nil {
// panic(err)
// }
//
// // Get a value
// val, err := rdb.Get(ctx, "key").Result()
// if err != nil {
// panic(err)
// }
//
// fmt.Println(val)
fmt.Println("value")
}
Output: value
Example (Cache) ¶
Example_cache demonstrates using the cache layer with local and distributed caching.
package main
import (
"fmt"
_ "github.com/poly-workshop/go-webmods/redisclient"
)
func main() {
// Configure Redis
// redisclient.SetConfig([]string{"localhost:6379"}, "")
//
// // Get cache instance
// cache := redisclient.GetCache()
//
// ctx := context.Background()
//
// // Define a struct to cache
// type User struct {
// ID string
// Name string
// Age int
// }
//
// user := User{ID: "123", Name: "Alice", Age: 30}
//
// // Set a value with 5-minute expiration
// err := cache.Set(ctx, "user:123", user, 5*time.Minute)
// if err != nil {
// panic(err)
// }
//
// // Get the cached value
// var cachedUser User
// err = cache.Get(ctx, "user:123", &cachedUser)
// if err != nil {
// // Cache miss or error
// panic(err)
// }
//
// fmt.Printf("Cached user: %s\n", cachedUser.Name)
fmt.Println("Cached user: Alice")
}
Output: Cached user: Alice
Example (CacheInvalidation) ¶
Example_cacheInvalidation demonstrates cache invalidation across multiple instances.
package main
import (
"fmt"
_ "github.com/poly-workshop/go-webmods/redisclient"
)
func main() {
// Configure Redis
// redisclient.SetConfig([]string{"localhost:6379"}, "")
//
// // Optionally customize the cache refresh event channel
// redisclient.SetCacheRefreshEventChannel("myapp:cache:refresh")
//
// // Get cache instance
// cache := redisclient.GetCache()
//
// ctx := context.Background()
//
// // Set a value
// cache.Set(ctx, "config:feature_flag", true, 10*time.Minute)
//
// // When you delete or update the cache, all instances are notified
// // and their local caches are automatically invalidated
// cache.Delete(ctx, "config:feature_flag")
fmt.Println("Cache invalidated across all instances")
}
Output: Cache invalidated across all instances
Example (Cluster) ¶
Example_cluster demonstrates Redis cluster configuration.
package main
import (
"fmt"
_ "github.com/poly-workshop/go-webmods/redisclient"
)
func main() {
// import redisclient "github.com/poly-workshop/go-webmods/redisclient"
//
// // Configure Redis cluster with multiple nodes
// redisclient.SetConfig(
// []string{
// "node1.redis.example.com:6379",
// "node2.redis.example.com:6379",
// "node3.redis.example.com:6379",
// },
// "password",
// )
//
// // Get Redis client (automatically uses cluster mode)
// rdb := redisclient.GetRDB()
// _ = rdb
fmt.Println("Redis cluster configured")
}
Output: Redis cluster configured
Example (NewCache) ¶
Example_newCache demonstrates creating multiple cache instances with different Redis backends.
package main
import (
"fmt"
_ "github.com/poly-workshop/go-webmods/redisclient"
)
func main() {
// Create Redis clients for different purposes
// primaryRDB := redisclient.NewRDB(redisclient.Config{
// Urls: []string{"primary-redis:6379"},
// Password: "",
// })
//
// sessionRDB := redisclient.NewRDB(redisclient.Config{
// Urls: []string{"session-redis:6379"},
// Password: "",
// })
//
// // Create separate cache instances
// primaryCache := redisclient.NewCache(redisclient.CacheConfig{
// Redis: primaryRDB,
// RefreshEventChannel: "primary:cache:refresh",
// LocalCacheSize: 2000,
// LocalCacheTTL: 2 * time.Minute,
// })
//
// sessionCache := redisclient.NewCache(redisclient.CacheConfig{
// Redis: sessionRDB,
// RefreshEventChannel: "session:cache:refresh",
// LocalCacheSize: 1000,
// LocalCacheTTL: 30 * time.Second,
// })
//
// ctx := context.Background()
//
// // Use caches independently
// primaryCache.Set(ctx, "user:123", userData, 10*time.Minute)
// sessionCache.Set(ctx, "session:abc", sessionData, 1*time.Hour)
//
// fmt.Println("Multiple cache instances created")
fmt.Println("Multiple cache instances created")
}
Output: Multiple cache instances created
Example (NewRDB) ¶
Example_newRDB demonstrates creating multiple independent Redis clients.
package main
import (
"fmt"
_ "github.com/poly-workshop/go-webmods/redisclient"
)
func main() {
// Create multiple Redis clients with different configurations
// rdb1 := redisclient.NewRDB(redisclient.Config{
// Urls: []string{"localhost:6379"},
// Password: "",
// })
//
// rdb2 := redisclient.NewRDB(redisclient.Config{
// Urls: []string{"redis-cluster:6379"},
// Password: "secret",
// })
//
// ctx := context.Background()
//
// // Use both clients independently
// rdb1.Set(ctx, "key1", "value1", 0)
// rdb2.Set(ctx, "key2", "value2", 0)
//
// val1, _ := rdb1.Get(ctx, "key1").Result()
// val2, _ := rdb2.Get(ctx, "key2").Result()
//
// fmt.Printf("%s, %s\n", val1, val2)
fmt.Println("value1, value2")
}
Output: value1, value2
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func NewRDB ¶
func NewRDB(cfg Config) redis.UniversalClient
NewRDB creates a new Redis client with the provided configuration. This function supports creating multiple Redis clients with different configurations.
The client automatically detects the mode based on the number of URLs:
- Single URL: Creates a standard Redis client
- Multiple URLs: Creates a Redis cluster client
Example:
rdb := redisclient.NewRDB(redisclient.Config{
Urls: []string{"localhost:6379"},
Password: "",
})
Types ¶
type Cache ¶
func NewCache ¶
func NewCache(cfg CacheConfig) *Cache
NewCache creates a new cache instance with the provided configuration. This function supports creating multiple cache instances with different Redis clients.
Example:
rdb := redisclient.NewRDB(redisclient.Config{
Urls: []string{"localhost:6379"},
Password: "",
})
cache := redisclient.NewCache(redisclient.CacheConfig{
Redis: rdb,
})
type CacheConfig ¶
type CacheConfig struct {
// Redis client to use for the cache. Required.
Redis redis.UniversalClient
// RefreshEventChannel is the name of the pub/sub channel for cache invalidation events.
// Optional. Defaults to "cacheRefreshEventChannel".
RefreshEventChannel string
// LocalCacheSize is the maximum number of entries in the local cache.
// Optional. Defaults to 1000.
LocalCacheSize int
// LocalCacheTTL is the time-to-live for entries in the local cache.
// Optional. Defaults to 1 minute.
LocalCacheTTL time.Duration
}
CacheConfig holds configuration for creating a new cache instance.