# redisx **Repository Path**: atyichang/redisx ## Basic Information - **Project Name**: redisx - **Description**: RedisX 是一个基于官方 Redis SDK 的扩展库,旨在为 AI 应用(如 LLM Agents、RAG 系统)提供即插即用的基础设施支持。 - **Primary Language**: Go - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-04-05 - **Last Updated**: 2026-05-17 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # RedisX - AI-First Type-Safe Redis Client for Go **`redisx`** - An AI-optimized, type-safe Redis client library that provides comprehensive hash operations, multi-type support, and production-ready reliability. [![Go Version](https://img.shields.io/badge/Go-1.21+-00ADD8?style=flat&logo=go)](https://golang.org) [![Redis](https://img.shields.io/badge/Redis-5.0+-DC382D?style=flat&logo=redis)](https://redis.io) [![KVROCKS](https://img.shields.io/badge/KVROCKS-2.0+-orange?style=flat)](https://kvrocks.apache.org) [![Tests](https://img.shields.io/badge/Tests-51.1%25-brightgreen.svg)](testing) [![Integration](https://img.shields.io/badge/Integration-40.0%25-blue.svg)](integration) [![License](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE) --- ## 🎯 Quick Index - [**Features**](#-features) - Core capabilities and advantages - [**Installation**](#-installation) - Setup and configuration - [**Quick Start**](#-quick-start) - 5-minute getting started guide - [**API Reference**](#-api-reference) - Complete API documentation - [**Hash Operations**](#-hash-operations) - Multi-type hash support - [**Integration Tests**](#-integration-tests) - Real Redis testing - [**Performance**](#-performance) - Benchmarks and optimization - [**Best Practices**](#-best-practices) - Production recommendations --- ## ✨ Features ### Core Capabilities - **Type Safety**: Generics support for `string`, `[]byte`, `time.Time`, `int64`, `float64`, `bool` - **Hash Operations**: Complete Redis Hash support with mixed-type fields - **Time Handling**: Automatic UTC conversion, timezone-safe operations - **Batch Operations**: Lua-optimized atomic batch operations with TTL support - **Error Handling`: Distinguishes "key not found" vs actual errors - **Connection Pool**: Full Redis connection pool configuration - **Multi-Backend**: Compatible with Redis and KVROCKS - **Testing**: Comprehensive unit tests (51.1%) and integration tests (40.0%) ### Advanced Features - **Mixed-Type Hash**: Store different data types in the same Redis Hash - **HashValue Container**: Unified interface for type conversions - **Atomic Operations**: Lua scripting for complex operations - **Integration Testing**: Real Redis server testing with automatic cleanup - **Production Ready**: Battle-tested with comprehensive error handling --- ## 📦 Installation ```bash go get gitee.com/atyichang/redisx ``` **Dependencies:** - `github.com/redis/go-redis/v9` - Redis client library - `github.com/stretchr/testify` - Testing framework --- ## 🚀 Quick Start ### 5-Minute Setup ```go package main import ( "context" "fmt" "log" "gitee.com/atyichang/redisx" ) func main() { // 1. Create client client, err := redisx.NewRedisxClient("localhost:6379", "", 0) if err != nil { log.Fatal(err) } defer client.Close() ctx := context.Background() // 2. String operations err = client.SetString(ctx, "user:1001:name", "Alice") if err != nil { log.Fatal(err) } name, exists, err := client.GetString(ctx, "user:1001:name") if exists { fmt.Printf("User: %s\n", name) } // 3. Hash operations (mixed types) user := map[string]redisx.HashValue{ "name": redisx.HashValueFromString("Bob"), "age": redisx.HashValueFromInt64(25), "score": redisx.HashValueFromFloat64(95.5), "active": redisx.HashValueFromBool(true), } err = client.HSet(ctx, "user:1001:profile", user) if err != nil { log.Fatal(err) } // 4. Time operations err = client.SetTime(ctx, "user:1001:created", time.Now()) if err != nil { log.Fatal(err) } } ``` --- ## 📚 API Reference ### API Categories | Category | API Count | Description | |----------|-----------|-------------| | **Client Management** | 3 | Connection, ping, close | | **String Operations** | 6 | Set, get, batch string operations | | **Bytes Operations** | 6 | Binary data handling | | **Time Operations** | 6 | Time serialization and storage | | **Hash Operations** | 45+ | Complete Redis Hash support | | **Generic Operations** | 1 | Type-safe batch operations | | **Utility Methods** | 5 | Connection management, testing | **Total Public APIs: 72+** --- ## 🔗 String Operations ### API Overview ```go // Basic operations SetString(ctx, key, value) -> error GetString(ctx, key) -> (string, bool, error) // Expiration SetStringEx(ctx, key, value, ttl) -> error // Conditional operations SetStringNX(ctx, key, value, ttl) -> (bool, error) // Set if Not Exists SetStringXX(ctx, key, value, ttl) -> (bool, error) // Set if eXists // Batch operations MGetString(ctx, keys) -> (map[string]string, error) ``` ### Usage Examples ```go // Basic string operations client.SetString(ctx, "config:timeout", "30") value, exists, _ := client.GetString(ctx, "config:timeout") // With expiration client.SetStringEx(ctx, "session:token", "abc123", 1*time.Hour) // Conditional set (distributed locking) locked, _ := client.SetStringNX(ctx, "lock:resource", "locked", 30*time.Second) if locked { fmt.Println("Lock acquired!") } // Batch operations keys := []string{"user:1001:name", "user:1001:email"} resultMap, _ := client.MGetString(ctx, keys) ``` --- ## 📦 Bytes Operations ### API Overview ```go // Basic operations SetBytes(ctx, key, []byte) -> error GetBytes(ctx, key) -> ([]byte, bool, error) // Expiration and conditional SetBytesEx(ctx, key, []byte, ttl) -> error SetBytesNX(ctx, key, []byte, ttl) -> (bool, error) SetBytesXX(ctx, key, []byte, ttl) -> (bool, error) // Batch operations MGetBytes(ctx, keys) -> (map[string][]byte, error) ``` ### Usage Examples ```go // JSON data jsonData := []byte(`{"name":"Alice","age":30}`) client.SetBytes(ctx, "user:1001:profile", jsonData) // Protocol Buffers pbData, _ := proto.Marshal(&User{Name: "Bob"}) client.SetBytes(ctx, "user:1001:pb", pbData) // Retrieve and parse data, exists, _ := client.GetBytes(ctx, "user:1001:profile") if exists { var user User json.Unmarshal(data, &user) } ``` --- ## ⏰ Time Operations ### API Overview ```go // Basic operations SetTime(ctx, key, time.Time) -> error GetTime(ctx, key) -> (time.Time, bool, error) // Expiration and conditional SetTimeEx(ctx, key, time.Time, ttl) -> error SetTimeNX(ctx, key, time.Time, ttl) -> (bool, error) SetTimeXX(ctx, key, time.Time, ttl) -> (bool, error) // Batch operations MGetTime(ctx, keys) -> (map[string]time.Time, error) ``` ### Time Handling Principles 1. **Storage**: Auto-convert to UTC (`value.UTC().MarshalBinary()`) 2. **Retrieval**: Returns UTC time (`time.Time`) 3. **Display**: Caller decides timezone (`.Local()` or keep UTC) ### Usage Examples ```go // Store current time (auto-converts to UTC) client.SetTime(ctx, "task:created", time.Now()) // Retrieve time (returns UTC) created, exists, _ := client.GetTime(ctx, "task:created") if exists { fmt.Printf("UTC: %v\n", created) fmt.Printf("Local: %v\n", created.Local()) } // Distributed lock timeout timeout := time.Now().Add(30 * time.Minute) client.SetTimeEx(ctx, "lock:timeout", timeout, 30*time.Minute) // Batch time operations keys := []string{"task:created", "task:updated", "task:completed"} times, _ := client.MGetTime(ctx, keys) ``` --- ## 🗂️ Hash Operations **RedisX provides comprehensive Redis Hash support with 45+ APIs covering all data types.** ### HashValue - Unified Type Container ```go type HashValue struct { Data []byte } // Constructors HashValueFromString(string) -> HashValue HashValueFromInt64(int64) -> HashValue HashValueFromFloat64(float64) -> HashValue HashValueFromTime(time.Time) -> HashValue HashValueFromBool(bool) -> HashValue HashValueFromBytes([]byte) -> HashValue // Converters HashValue.ToString() -> (string, error) HashValue.ToInt64() -> (int64, error) HashValue.ToFloat64() -> (float64, error) HashValue.ToTime() -> (time.Time, error) HashValue.ToBool() -> (bool, error) HashValue.ToBytes() -> []byte ``` ### Hash API Categories #### **1. Mixed-Type Operations (Recommended)** ```go // Mixed-type hash operations (most flexible) HSet(ctx, key, map[string]HashValue, ttl...) -> error HMGet(ctx, key, fields...) -> (map[string]HashValue, error) HGetAll(ctx, key) -> (map[string]HashValue, error) ``` #### **2. String Hash Operations** ```go // Single field operations HSetString(ctx, key, field, value) -> error HGetString(ctx, key, field) -> (string, bool, error) // Batch operations HSetStringBatch(ctx, key, map[string]string) -> error HMGetString(ctx, key, fields...) -> (map[string]string, error) HGetAllString(ctx, key) -> (map[string]string, error) ``` #### **3. Int64 Hash Operations** ```go // Single field operations HSetInt64(ctx, key, field, int64) -> error HGetInt64(ctx, key, field) -> (int64, bool, error) // Batch operations HSetInt64Batch(ctx, key, map[string]int64) -> error HMGetInt64(ctx, key, fields...) -> (map[string]int64, error) HGetAllInt64(ctx, key) -> (map[string]int64, error) // Atomic increment HIncrBy(ctx, key, field, increment) -> (int64, error) ``` #### **4. Float64 Hash Operations** ```go // Single field operations HSetFloat64(ctx, key, field, float64) -> error HGetFloat64(ctx, key, field) -> (float64, bool, error) // Batch operations HSetFloat64Batch(ctx, key, map[string]float64) -> error HMGetFloat64(ctx, key, fields...) -> (map[string]float64, error) HGetAllFloat64(ctx, key) -> (map[string]float64, error) ``` #### **5. Time Hash Operations** ```go // Single field operations HSetTime(ctx, key, field, time.Time) -> error HGetTime(ctx, key, field) -> (time.Time, bool, error) // Batch operations HSetTimeBatch(ctx, key, map[string]time.Time) -> error HMGetTime(ctx, key, fields...) -> (map[string]time.Time, error) HGetAllTime(ctx, key) -> (map[string]time.Time, error) ``` #### **6. Bool Hash Operations** ```go // Single field operations HSetBool(ctx, key, field, bool) -> error HGetBool(ctx, key, field) -> (bool, bool, error) // Batch operations HSetBoolBatch(ctx, key, map[string]bool) -> error HMGetBool(ctx, key, fields...) -> (map[string]bool, error) HGetAllBool(ctx, key) -> (map[string]bool, error) ``` #### **7. Utility Operations** ```go // Field management HDel(ctx, key, fields...) -> (int64, error) HExists(ctx, key, field) -> (bool, error) HLen(ctx, key) -> (int64, error) HKeys(ctx, key) -> ([]string, error) HVals(ctx, key) -> ([]string, error) // Conditional operations HSetNXString(ctx, key, field, value) -> (bool, error) HSetNXInt64(ctx, key, field, int64) -> (bool, error) ``` ### Hash Operation Examples #### **Mixed-Type Hash (Recommended)** ```go // Store user profile with mixed types profile := map[string]redisx.HashValue{ "name": redisx.HashValueFromString("Alice"), "age": redisx.HashValueFromInt64(25), "score": redisx.HashValueFromFloat64(95.5), "active": redisx.HashValueFromBool(true), "created": redisx.HashValueFromTime(time.Now()), } // Set with optional TTL err := client.HSet(ctx, "user:1001", profile) // Get specific fields result, _ := client.HMGet(ctx, "user:1001", "name", "age", "score") name, _ := result["name"].ToString() age, _ := result["age"].ToInt64() score, _ := result["score"].ToFloat64() // Get all fields allFields, _ := client.HGetAll(ctx, "user:1001") ``` #### **Type-Specific Hash Operations** ```go // String hash client.HSetString(ctx, "user:1001", "name", "Alice") name, exists, _ := client.HGetString(ctx, "user:1001", "name") // Int64 hash with increment client.HSetInt64(ctx, "user:1001", "login_count", 1) count, _ := client.HIncrBy(ctx, "user:1001", "login_count", 1) // Float64 hash for coordinates coords := map[string]float64{"lat": 39.9042, "lng": 116.4074} client.HSetFloat64Batch(ctx, "location:beijing", coords) // Time hash for tracking timestamps := map[string]time.Time{ "created": time.Now(), "updated": time.Now(), } client.HSetTimeBatch(ctx, "timestamps:1001", timestamps) ``` #### **Hash Utility Operations** ```go // Check field existence exists, _ := client.HExists(ctx, "user:1001", "name") // Get hash length length, _ := client.HLen(ctx, "user:1001") // Get all keys/fields fields, _ := client.HKeys(ctx, "user:1001") values, _ := client.HVals(ctx, "user:1001") // Delete fields deleted, _ := client.HDel(ctx, "user:1001", "temp_field", "old_field") // Conditional set (only if field doesn't exist) created, _ := client.HSetNXString(ctx, "user:1001", "initialized", "true") ``` --- ## 🧪 Integration Tests ### Running Integration Tests ```bash # Run all integration tests (requires Redis/KVROCKS) go test -v -run TestIntegration # Run specific test categories go test -v -run TestIntegration_StringOperations go test -v -run TestIntegration_HashStringOperations go test -v -run TestIntegration_HashValueMixedTypes # Run with custom Redis configuration export REDIS_INTEGRATION_HOST="127.0.0.1" export REDIS_INTEGRATION_PORT="6666" go test -v -run TestIntegration ``` ### Integration Test Configuration | Environment Variable | Default | Description | |---------------------|---------|-------------| | `REDIS_INTEGRATION_HOST` | `127.0.0.1` | Redis server address | | `REDIS_INTEGRATION_PORT` | `6666` | Redis server port | | `REDIS_INTEGRATION_PASSWORD` | `""` | Redis password | | `REDIS_INTEGRATION_DB` | `0` | Redis database number | | `RUN_INTEGRATION_TESTS` | `true` | Enable integration tests | ### Test Coverage - **Unit Tests**: 51.1% statement coverage - **Integration Tests**: 40.0% statement coverage - **Test Categories**: 14+ comprehensive test suites - **Backend Support**: Redis 5.0+, KVROCKS 2.0+ **See**: [INTEGRATION_TEST_GUIDE.md](INTEGRATION_TEST_GUIDE.md) for detailed testing documentation. --- ## ⚡ Performance ### Benchmarks | Operation | Performance | Memory | Description | |-----------|-------------|---------|-------------| | **SetString** | ~15,000 ns/op | ~32 B/op | Basic string operations | | **GetString** | ~8,000 ns/op | ~16 B/op | String retrieval | | **SetTime** | ~24,710 ns/op | ~992 B/op | Time serialization | | **GetTime** | ~21,943 ns/op | ~376 B/op | Time deserialization | | **HSetString** | ~12,000 ns/op | ~256 B/op | Hash string operations | | **HGetString** | ~10,000 ns/op | ~128 B/op | Hash string retrieval | | **MSetEx (batch)** | ~50,000 ns/op | ~2 KB/op | Batch operations with Lua | ### Optimization Tips 1. **Use Batch Operations**: 10x faster than individual operations 2. **Connection Pooling**: Configure based on concurrency needs 3. **Pipeline for Bulk**: Use go-redis pipeline for massive operations 4. **Appropriate TTL**: Balance cache hit rate vs memory usage --- ## 🏗️ Client Configuration ### Development Environment ```go client, err := redisx.NewRedisxClient("localhost:6379", "", 0) ``` ### Production Environment ```go import "github.com/redis/go-redis/v9" client, err := redisx.NewRedisxClientWithOptions(&redis.Options{ // Connection Addr: "redis.prod.example.com:6379", Password: "your-password", DB: 0, // Connection Pool PoolSize: 100, MinIdleConns: 10, MaxRetries: 3, // Timeouts DialTimeout: 5 * time.Second, ReadTimeout: 1 * time.Second, WriteTimeout: 1 * time.Second, PoolTimeout: 4 * time.Second, // Connection Lifecycle ConnMaxIdleTime: 10 * time.Minute, ConnMaxLifetime: 30 * time.Minute, }) ``` ### High-Concurrency Configuration ```go client, err := redisx.NewRedisxClientWithOptions(&redis.Options{ Addr: "redis.example.com:6379", Password: "", DB: 0, // High-concurrency settings PoolSize: 200, MinIdleConns: 50, MaxRetries: 3, DialTimeout: 5 * time.Second, ReadTimeout: 100 * time.Millisecond, WriteTimeout: 100 * time.Millisecond, PoolTimeout: 4 * time.Second, ConnMaxIdleTime: 10 * time.Minute, ConnMaxLifetime: 30 * time.Minute, }) ``` --- ## 🎯 Use Cases ### 1. User Profile Caching ```go // Cache user data with mixed types profile := map[string]redisx.HashValue{ "name": redisx.HashValueFromString("Alice"), "age": redisx.HashValueFromInt64(25), "score": redisx.HashValueFromFloat64(95.5), "active": redisx.HashValueFromBool(true), "joined": redisx.HashValueFromTime(time.Now()), } client.HSet(ctx, "user:1001", profile, 1*time.Hour) // Retrieve user profile user, _ := client.HGetAll(ctx, "user:1001") name, _ := user["name"].ToString() age, _ := user["age"].ToInt64() ``` ### 2. Distributed Locking ```go // Acquire lock locked, _ := client.SetStringNX(ctx, "lock:resource", "locked", 30*time.Second) if !locked { return fmt.Errorf("resource already locked") } // Release lock defer client.rdb.Del(ctx, "lock:resource") // Critical section // ... perform operations ... ``` ### 3. Session Management ```go // Create session session := map[string]redisx.HashValue{ "user_id": redisx.HashValueFromString("1001"), "created": redisx.HashValueFromTime(time.Now()), "last_access": redisx.HashValueFromTime(time.Now()), "ip": redisx.HashValueFromString("192.168.1.1"), } client.HSet(ctx, "session:abc123", session, 24*time.Hour) // Validate session sessionData, exists, _ := client.HGetAll(ctx, "session:abc123") if !exists { return fmt.Errorf("invalid session") } ``` ### 4. Analytics Counter ```go // Increment counter newCount, _ := client.HIncrBy(ctx, "stats:daily:page_views", "2024-05-17", 1) // Batch update stats stats := map[string]int64{ "page_views": 1000, "unique_visitors": 500, "bounce_rate": 30, } client.HSetInt64Batch(ctx, "stats:daily:2024-05-17", stats) // Retrieve analytics dailyStats, _ := client.HGetAllInt64(ctx, "stats:daily:2024-05-17") ``` --- ## 🔍 Troubleshooting ### Common Issues **1. Connection Failure** ```bash # Check Redis connectivity redis-cli -h localhost -p 6379 ping # Verify address and port netstat -an | grep 6379 ``` **2. Timeout Errors** ```go // Increase timeout values client, err := redisx.NewRedisxClientWithOptions(&redis.Options{ DialTimeout: 10 * time.Second, ReadTimeout: 5 * time.Second, WriteTimeout: 5 * time.Second, }) ``` **3. Connection Pool Exhaustion** ```go // Increase pool size client, err := redisx.NewRedisxClientWithOptions(&redis.Options{ PoolSize: 200, MinIdleConns: 50, PoolTimeout: 10 * time.Second, }) ``` **4. Time Zone Issues** ```go // Remember: RedisX stores UTC, returns UTC storedTime, _, _ := client.GetTime(ctx, "mytime") localTime := storedTime.Local() // Convert to local timezone ``` --- ## 📈 Best Practices ### 1. Error Handling ```go // Always check the 'exists' flag value, exists, err := client.GetString(ctx, "key") if err != nil { // Real error (network, permission, etc.) log.Fatal(err) } if !exists { // Key doesn't exist (normal case) return fmt.Errorf("key not found") } ``` ### 2. Connection Management ```go // Create client once, reuse throughout application var globalClient *redisx.RedisxClient func init() { client, err := redisx.NewRedisxClient("localhost:6379", "", 0) if err != nil { log.Fatal(err) } globalClient = client } // Use in application defer globalClient.Close() ``` ### 3. Key Naming ```go // Use consistent key naming patterns "user:{id}:profile" // User profile "user:{id}:session" // User session "stats:daily:{date}" // Daily statistics "cache:page:{url}" // Page cache "lock:{resource}:{id}" // Distributed locks ``` ### 4. TTL Management ```go // Hot data: Short TTL client.SetStringEx(ctx, "hot:data", value, 5*time.Minute) // Warm data: Medium TTL client.SetStringEx(ctx, "warm:data", value, 1*time.Hour) // Cold data: Long TTL client.SetStringEx(ctx, "cold:data", value, 24*time.Hour) // Permanent: No TTL client.SetString(ctx, "permanent:data", value) ``` --- ## 🤝 Contributing We welcome contributions! Please see our contributing guidelines: 1. **Code Style**: Follow Go conventions and existing patterns 2. **Testing**: Add unit tests for new features 3. **Integration Tests**: Include integration tests for Redis operations 4. **Documentation**: Update API docs and examples 5. **Performance**: Benchmark critical paths --- ## 📄 License MIT License - see LICENSE file for details --- ## 🔗 Resources - **Documentation**: [INTEGRATION_TEST_GUIDE.md](INTEGRATION_TEST_GUIDE.md) - **Testing**: [QUICKSTART_INTEGRATION_TESTS.md](QUICKSTART_INTEGRATION_TESTS.md) - **Redis Docs**: [redis.io/documentation](https://redis.io/documentation) - **KVROCKS Docs**: [kvrocks.apache.org](https://kvrocks.apache.org/docs/) - **go-redis**: [redis.uptrace.dev](https://redis.uptrace.dev/) --- ## 📞 Support - **Issues**: [GitHub Issues](https://github.com/atyichang/redisx/issues) - **Discussions**: [GitHub Discussions](https://github.com/atyichang/redisx/discussions) --- **Made with ❤️ by Go developers, optimized for AI assistance**