# ixRedis **Repository Path**: ixgo/redis ## Basic Information - **Project Name**: ixRedis - **Description**: redis帮助类 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-09-19 - **Last Updated**: 2026-03-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ixRedis - 高性能 Redis 客户端库 基于 `github.com/garyburd/redigo/redis` 实现的高性能 Redis 客户端库,支持多实例管理、连接池、管道操作等特性。 ## 📁 文件结构 库采用模块化设计,按功能拆分为多个文件: - `config.go` - 配置相关(Config 结构体、配置选项函数) - `client.go` - 客户端相关(Client 结构体、连接管理) - `manager.go` - 管理器相关(Manager 结构体、多实例管理) - `basic.go` - 基础操作(SET、GET、DEL、EXISTS 等) - `hash.go` - 哈希操作(HSET、HGET、HGETALL 等) - `list.go` - 列表操作(LPUSH、RPUSH、LPOP、RPOP 等) - `set.go` - 集合操作(SADD、SREM、SMEMBERS 等) - `sorted_set.go` - 有序集合操作(ZADD、ZRANGE、ZCARD 等) - `pubsub.go` - 发布订阅操作(PUBLISH) - `transaction.go` - 事务操作(MULTI、EXEC、DISCARD) - `pipeline.go` - 管道操作(Pipeline 结构体) - `utils.go` - 工具方法(KEYS、FLUSHDB、INFO 等) - `helpers.go` - 便捷方法(NewClient、NewClientWithOptions) - `batch.go` - 批量操作(BatchSet、BatchGet 等) - `cache.go` - 缓存装饰器(CacheDecorator、StatsCacheDecorator) - `lock.go` - 分布式锁(DistributedLock、LockManager) - `rate_limit.go` - 限流功能(RateLimiter、TokenBucketRateLimiter) - `metrics.go` - 监控指标(Metrics、MetricsClient、HealthCheck) - `index.go` - 主文件(包声明和说明) ## ✨ 特性 - 🚀 **高性能**: 基于连接池,支持并发操作 - 🔧 **多实例**: 支持管理多个 Redis 实例 - 🛡️ **安全**: 线程安全,不会引起程序崩溃 - 📦 **简单**: 使用方式简单直观 - 🔄 **管道**: 支持管道操作,提高批量操作性能 - 💾 **连接池**: 自动管理连接池,支持连接复用 - ⏰ **超时控制**: 支持连接、读取、写入超时设置 - 🏗️ **模块化**: 按功能拆分为多个文件,便于维护和扩展 - 🎯 **类型化**: 支持任何类型的数据存储和类型安全的获取 - 📊 **批量操作**: 支持批量设置和获取,提高性能 - 🗄️ **缓存装饰器**: 提供缓存装饰器,简化缓存逻辑 - 🔒 **分布式锁**: 支持分布式锁,解决并发问题 - 🚦 **限流**: 支持滑动窗口和令牌桶限流算法 - 📈 **监控**: 内置监控和指标统计功能 - ✅ **配置验证**: 自动验证配置参数的有效性 - 🏷️ **全局前缀**: 支持为所有键自动添加前缀,便于多应用隔离 - 🗄️ **数据库隔离**: 完善的数据库选择机制,确保多实例正确隔离 ## 📦 安装 ```bash go get gitee.com/ixgo/redis ``` ## 🚀 快速开始 ### 基本使用 ```go package main import ( "fmt" "log" "gitee.com/ixgo/redis" ) func main() { // 创建 Redis 客户端 client, err := ixRedis.NewClientWithOptions("localhost", 6379, ixRedis.WithPassword(""), ixRedis.WithDB(0), ) if err != nil { log.Fatal(err) } defer client.Close() // 设置不同类型的键值 err = client.Set("hello", "world") // 字符串 err = client.Set("count", 42) // 整数 err = client.Set("price", 99.99) // 浮点数 err = client.Set("active", true) // 布尔值 if err != nil { log.Fatal(err) } // 获取不同类型的键值 var str string var count int64 var price float64 var active bool client.Get("hello", &str) // 字符串 client.Get("count", &count) // 整数 client.Get("price", &price) // 浮点数 client.Get("active", &active) // 布尔值 fmt.Printf("字符串: %s\n", str) // 输出: world fmt.Printf("整数: %d\n", count) // 输出: 42 fmt.Printf("浮点数: %.2f\n", price) // 输出: 99.99 fmt.Printf("布尔值: %t\n", active) // 输出: true } ``` ### 全局前缀功能 支持为所有键自动添加前缀,便于多应用隔离: ```go package main import ( "fmt" "log" "time" ixRedis "gitee.com/ixgo/redis" ) func main() { // 创建带前缀的 Redis 客户端 client, err := ixRedis.NewClientWithOptions("localhost", 6379, ixRedis.WithKeyPrefix("myapp"), // 设置键前缀 ixRedis.WithPassword(""), ixRedis.WithDB(0), ) if err != nil { log.Fatal(err) } defer client.Close() // 所有操作都会自动加上前缀 "myapp:" client.Set("user:123", "张三") // 实际键: myapp:user:123 client.HSet("user:profile", "name", "李四") // 实际键: myapp:user:profile client.LPush("user:messages", "消息1") // 实际键: myapp:user:messages // 获取值时使用原始键名 var result string client.Get("user:123", &result) // 自动查找 myapp:user:123 fmt.Printf("用户: %s\n", result) // 输出: 张三 // 批量操作也支持前缀 batchData := map[string]interface{}{ "batch1": "value1", "batch2": "value2", } client.BatchSet(batchData) // 键会自动加上前缀 // 带过期时间的操作 client.SetWithExpire("temp:data", "临时数据", 10*time.Second) // 清理数据 client.Del("user:123", "user:profile", "user:messages", "batch1", "batch2", "temp:data") } ``` **前缀功能特点:** - 🏷️ **自动前缀**: 所有键操作都会自动加上配置的前缀 - 🔄 **透明使用**: 开发者使用原始键名,库自动处理前缀 - 📊 **全支持**: 支持所有Redis操作类型(字符串、哈希、列表、集合、有序集合等) - 🚀 **高性能**: 前缀处理在客户端完成,不影响Redis性能 - 🛡️ **隔离性**: 不同应用使用不同前缀,避免键冲突 ### 多实例管理 ```go package main import ( "fmt" "log" "gitee.com/ixgo/redis" ) func main() { // 创建管理器 manager := ixRedis.NewManager() // 添加配置 config1 := &ixRedis.Config{ Host: "localhost", Port: 6379, Password: "", DB: 0, } manager.AddConfig("redis1", config1) config2 := &ixRedis.Config{ Host: "localhost", Port: 6379, Password: "", DB: 1, // 使用不同的数据库 } manager.AddConfig("redis2", config2) // 获取不同的客户端 client1, _ := manager.GetClient("redis1") client2, _ := manager.GetClient("redis2") // 在不同数据库中操作 client1.Set("key1", "value1") client2.Set("key1", "value2") value1, _ := client1.Get("key1") // "value1" value2, _ := client2.Get("key1") // "value2" fmt.Println(value1, value2) } ``` ### 数据库隔离 支持多个Redis客户端实例正确隔离到不同的数据库中: ```go package main import ( "fmt" "log" ixRedis "gitee.com/ixgo/redis" ) func main() { // 创建三个不同数据库的客户端 client1, err := ixRedis.NewClientWithOptions("localhost", 6379, ixRedis.WithDB(1), // 数据库1 ixRedis.WithPassword("123456"), ) if err != nil { log.Fatal(err) } defer client1.Close() client2, err := ixRedis.NewClientWithOptions("localhost", 6379, ixRedis.WithDB(2), // 数据库2 ixRedis.WithPassword("123456"), ) if err != nil { log.Fatal(err) } defer client2.Close() client3, err := ixRedis.NewClientWithOptions("localhost", 6379, ixRedis.WithDB(3), // 数据库3 ixRedis.WithPassword("123456"), ) if err != nil { log.Fatal(err) } defer client3.Close() // 每个客户端在各自的数据库中操作 client1.Set("user:123", "数据库1的用户") client2.Set("user:123", "数据库2的用户") client3.Set("user:123", "数据库3的用户") // 验证数据库隔离 var result1, result2, result3 string client1.Get("user:123", &result1) // "数据库1的用户" client2.Get("user:123", &result2) // "数据库2的用户" client3.Get("user:123", &result3) // "数据库3的用户" fmt.Printf("客户端1 (DB1): %s\n", result1) fmt.Printf("客户端2 (DB2): %s\n", result2) fmt.Printf("客户端3 (DB3): %s\n", result3) // 清理数据 client1.Del("user:123") client2.Del("user:123") client3.Del("user:123") } ``` **数据库隔离特点:** - 🗄️ **独立配置**: 每个客户端都有独立的配置和连接池 - 🔒 **状态保持**: 连接池重用时自动重新选择正确的数据库 - 🛡️ **完全隔离**: 不同数据库的客户端无法访问彼此的数据 - ⚡ **高性能**: 数据库选择在客户端完成,不影响Redis性能 ## 📚 API 文档 ### 基础操作 #### Set - 设置键值 **函数签名:** ```go func (c *Client) Set(key string, value interface{}) error ``` **参数说明:** - `key` (string): Redis 键名 - `value` (interface{}): 要存储的值,支持任何类型 **使用场景:** - 存储用户会话信息 - 缓存计算结果 - 存储配置数据 - 临时数据存储 **示例:** ```go // 存储不同类型的数据 err := client.Set("username", "张三") // 字符串 err := client.Set("user_id", 12345) // 整数 err := client.Set("balance", 99.99) // 浮点数 err := client.Set("is_vip", true) // 布尔值 // 存储复杂类型(自动JSON序列化) user := User{ID: 1, Name: "张三", Age: 25} err := client.Set("user:1", user) // 结构体 config := map[string]interface{}{ "max_connections": 1000, "timeout": 30, "debug": true, } err := client.Set("app_config", config) // map items := []string{"apple", "banana", "orange"} err := client.Set("shopping_cart", items) // slice ``` #### SetWithExpire - 设置键值并指定过期时间 **函数签名:** ```go func (c *Client) SetWithExpire(key string, value interface{}, expiration time.Duration) error ``` **参数说明:** - `key` (string): Redis 键名 - `value` (interface{}): 要存储的值 - `expiration` (time.Duration): 过期时间 **使用场景:** - 临时验证码存储 - 会话超时管理 - 缓存自动过期 - 限时优惠券 **示例:** ```go // 存储验证码,5分钟后过期 err := client.SetWithExpire("sms_code:13800138000", "123456", 5*time.Minute) // 存储用户会话,30分钟后过期 session := map[string]interface{}{ "user_id": 12345, "login_time": time.Now(), "permissions": []string{"read", "write"}, } err := client.SetWithExpire("session:abc123", session, 30*time.Minute) // 存储限时优惠券 coupon := map[string]interface{}{ "code": "SAVE20", "discount": 20, "min_amount": 100, } err := client.SetWithExpire("coupon:SAVE20", coupon, 24*time.Hour) ``` #### Get - 获取键值 **函数签名:** ```go func (c *Client) Get(key string, dest interface{}) (bool, error) ``` **参数说明:** - `key` (string): Redis 键名 - `dest` (interface{}): 目标变量的指针,用于接收数据 - 返回值: `(bool, error)` - 第一个bool表示键是否存在,第二个error表示操作是否成功 **使用场景:** - 读取缓存数据 - 获取用户信息 - 读取配置参数 - 数据反序列化 **示例:** ```go // 获取字符串 var username string exists, err := client.Get("username", &username) if err != nil { log.Printf("获取用户名失败: %v", err) } else if !exists { log.Println("用户名不存在") } else { fmt.Printf("用户名: %s\n", username) } // 获取数字 var userID int64 exists, err = client.Get("user_id", &userID) if exists && err == nil { fmt.Printf("用户ID: %d\n", userID) } // 获取结构体 var user User exists, err = client.Get("user:1", &user) if exists && err == nil { fmt.Printf("用户信息: %+v\n", user) } // 获取map var config map[string]interface{} exists, err = client.Get("app_config", &config) if exists && err == nil { fmt.Printf("配置信息: %+v\n", config) } ``` #### GetString - 获取字符串值(兼容方法) **函数签名:** ```go func (c *Client) GetString(key string) (string, error) ``` **参数说明:** - `key` (string): Redis 键名 - 返回值: `(string, error)` - 字符串值和错误 **使用场景:** - 简单字符串获取 - 兼容旧代码 - 快速原型开发 **示例:** ```go // 获取字符串(简单方式) value, err := client.GetString("greeting") if err != nil { log.Printf("获取失败: %v", err) } else { fmt.Printf("问候语: %s\n", value) } ``` #### GetBytes - 获取字节数组 **函数签名:** ```go func (c *Client) GetBytes(key string) ([]byte, error) ``` **参数说明:** - `key` (string): Redis 键名 - 返回值: `([]byte, error)` - 字节数组和错误 **使用场景:** - 二进制数据存储 - 图片缓存 - 文件内容存储 **示例:** ```go // 存储和获取图片数据 imageData := []byte{0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A} // PNG文件头 err := client.Set("avatar:user1", imageData) // 获取图片数据 data, err := client.GetBytes("avatar:user1") if err != nil { log.Printf("获取图片失败: %v", err) } else { fmt.Printf("图片大小: %d 字节\n", len(data)) } ``` #### Del - 删除键 **函数签名:** ```go func (c *Client) Del(keys ...string) (int64, error) ``` **参数说明:** - `keys` (...string): 要删除的键名(可变参数) - 返回值: `(int64, error)` - 删除的键数量和错误 **使用场景:** - 清理过期数据 - 用户登出时删除会话 - 批量清理缓存 - 数据重置 **示例:** ```go // 删除单个键 deleted, err := client.Del("temp_data") if err != nil { log.Printf("删除失败: %v", err) } else { fmt.Printf("删除了 %d 个键\n", deleted) } // 批量删除 deleted, err = client.Del("user:1", "user:2", "user:3") if err != nil { log.Printf("批量删除失败: %v", err) } else { fmt.Printf("批量删除了 %d 个键\n", deleted) } // 删除用户相关数据 userKeys := []string{ "user:123:profile", "user:123:settings", "user:123:session", } deleted, err = client.Del(userKeys...) ``` #### Exists - 检查键是否存在 **函数签名:** ```go func (c *Client) Exists(key string) (bool, error) ``` **参数说明:** - `key` (string): Redis 键名 - 返回值: `(bool, error)` - 键是否存在和错误 **使用场景:** - 缓存命中检查 - 数据存在性验证 - 条件判断 - 幂等性检查 **示例:** ```go // 检查用户是否存在 exists, err := client.Exists("user:123") if err != nil { log.Printf("检查失败: %v", err) } else if exists { fmt.Println("用户存在") } else { fmt.Println("用户不存在") } // 检查缓存是否有效 cacheKey := "expensive_calculation:param1:param2" exists, err = client.Exists(cacheKey) if exists { // 使用缓存 var result string client.Get(cacheKey, &result) } else { // 执行计算并缓存结果 result := performExpensiveCalculation() client.Set(cacheKey, result) } ``` #### Expire - 设置过期时间 **函数签名:** ```go func (c *Client) Expire(key string, expiration time.Duration) error ``` **参数说明:** - `key` (string): Redis 键名 - `expiration` (time.Duration): 过期时间 **使用场景:** - 动态调整过期时间 - 延长会话时间 - 临时数据管理 - 缓存刷新 **示例:** ```go // 延长用户会话时间 err := client.Expire("session:abc123", 30*time.Minute) if err != nil { log.Printf("延长会话失败: %v", err) } // 设置临时数据的过期时间 err = client.Set("temp_data", "some_value") err = client.Expire("temp_data", 1*time.Hour) // 根据用户活动动态调整过期时间 if userIsActive { err = client.Expire("user:123:last_activity", 15*time.Minute) } ``` #### TTL - 获取剩余生存时间 **函数签名:** ```go func (c *Client) TTL(key string) (time.Duration, error) ``` **参数说明:** - `key` (string): Redis 键名 - 返回值: `(time.Duration, error)` - 剩余生存时间和错误 **使用场景:** - 显示缓存剩余时间 - 过期提醒 - 监控缓存状态 - 调试过期问题 **示例:** ```go // 检查缓存的剩余时间 ttl, err := client.TTL("cache:expensive_result") if err != nil { log.Printf("获取TTL失败: %v", err) } else if ttl > 0 { fmt.Printf("缓存还有 %v 过期\n", ttl) } else { fmt.Println("缓存已过期或不存在") } // 监控会话状态 sessionTTL, err := client.TTL("session:abc123") if err == nil && sessionTTL > 0 { if sessionTTL < 5*time.Minute { // 会话即将过期,提醒用户 notifyUser("您的会话即将过期,请重新登录") } } ``` #### 其他快捷操作 除了上述主流命令,`ixRedis` 还为您提供了诸多高频场景必需的原子操作和并发控制: - **`Incr(key string) (int64, error)`** / **`Decr(key string) (int64, error)`**: 通用的整数原子计数器。 - **`IncrWithExpire(key string, step int64, expiration time.Duration) (int64, error)`**: 强绑定 Lua 脚本的原子“自增并设置超时时间”,用于拦截每天受限的领奖或API限频。 - **`SetNX(key string, value interface{}, expiration time.Duration) (bool, error)`**: 若键不存在则极简、并发安全地抢占设值,通常用来作为简易拦截锁。 - **`GetSet(key string, newValue interface{}, dest interface{}) error`**: 原子替换一个状态值并成功拿到其旧状态标识进入下一步。 - **`Scan(cursor int64, match string, count int) (int64, []string, error)`**: 推荐使用的游标类渐进遍历接口,自动完成前缀剥离,杜绝 `KEYS *` 面临的单线程拥塞危险。 ### 哈希操作 哈希操作适合存储对象属性,每个哈希可以包含多个字段-值对。 #### HSet - 设置哈希字段 **函数签名:** ```go func (c *Client) HSet(key, field string, value interface{}) error ``` **参数说明:** - `key` (string): 哈希键名 - `field` (string): 字段名 - `value` (interface{}): 字段值 **使用场景:** - 存储用户属性 - 对象字段更新 - 配置项管理 - 计数器字段 **示例:** ```go // 设置用户信息 err := client.HSet("user:1", "name", "张三") err = client.HSet("user:1", "age", 25) err = client.HSet("user:1", "email", "zhangsan@example.com") err = client.HSet("user:1", "is_vip", true) // 更新单个字段 err = client.HSet("user:1", "last_login", time.Now()) // 存储配置信息 err = client.HSet("config:app", "max_connections", 1000) err = client.HSet("config:app", "timeout", 30) err = client.HSet("config:app", "debug_mode", false) ``` #### HGet - 获取哈希字段 **函数签名:** ```go func (c *Client) HGet(key, field string) (string, error) ``` **参数说明:** - `key` (string): 哈希键名 - `field` (string): 字段名 - 返回值: `(string, error)` - 字段值和错误 **使用场景:** - 获取对象属性 - 读取配置项 - 字段存在性检查 - 部分数据加载 **示例:** ```go // 获取用户姓名 name, err := client.HGet("user:1", "name") if err != nil { log.Printf("获取用户名失败: %v", err) } else { fmt.Printf("用户名: %s\n", name) } // 获取配置项 maxConn, err := client.HGet("config:app", "max_connections") if err == nil { fmt.Printf("最大连接数: %s\n", maxConn) } // 检查用户是否为VIP isVipStr, err := client.HGet("user:1", "is_vip") if err == nil && isVipStr == "true" { fmt.Println("用户是VIP") } ``` #### HGetAll - 获取所有哈希字段 **函数签名:** ```go func (c *Client) HGetAll(key string) (map[string]string, error) ``` **参数说明:** - `key` (string): 哈希键名 - 返回值: `(map[string]string, error)` - 所有字段-值对和错误 **使用场景:** - 获取完整对象 - 数据导出 - 对象序列化 - 批量字段读取 **示例:** ```go // 获取用户所有信息 userFields, err := client.HGetAll("user:1") if err != nil { log.Printf("获取用户信息失败: %v", err) } else { fmt.Printf("用户信息: %+v\n", userFields) // 输出: map[age:25 email:zhangsan@example.com is_vip:true name:张三] } // 获取应用配置 config, err := client.HGetAll("config:app") if err == nil { for key, value := range config { fmt.Printf("%s: %s\n", key, value) } } ``` #### HDel - 删除哈希字段 **函数签名:** ```go func (c *Client) HDel(key string, fields ...string) (int64, error) ``` **参数说明:** - `key` (string): 哈希键名 - `fields` (...string): 要删除的字段名(可变参数) - 返回值: `(int64, error)` - 删除的字段数量和错误 **使用场景:** - 删除对象属性 - 清理过期字段 - 字段重置 - 批量字段删除 **示例:** ```go // 删除单个字段 deleted, err := client.HDel("user:1", "temp_field") if err != nil { log.Printf("删除字段失败: %v", err) } else { fmt.Printf("删除了 %d 个字段\n", deleted) } // 批量删除字段 deleted, err = client.HDel("user:1", "old_field1", "old_field2", "old_field3") if err == nil { fmt.Printf("批量删除了 %d 个字段\n", deleted) } // 删除用户敏感信息 sensitiveFields := []string{"password", "ssn", "credit_card"} deleted, err = client.HDel("user:1", sensitiveFields...) ``` #### HExists - 检查字段是否存在 **函数签名:** ```go func (c *Client) HExists(key, field string) (bool, error) ``` **参数说明:** - `key` (string): 哈希键名 - `field` (string): 字段名 - 返回值: `(bool, error)` - 字段是否存在和错误 **使用场景:** - 字段存在性验证 - 条件判断 - 数据完整性检查 - 可选字段处理 **示例:** ```go // 检查用户是否有邮箱 hasEmail, err := client.HExists("user:1", "email") if err != nil { log.Printf("检查字段失败: %v", err) } else if hasEmail { email, _ := client.HGet("user:1", "email") fmt.Printf("用户邮箱: %s\n", email) } else { fmt.Println("用户未设置邮箱") } // 检查配置项是否存在 hasTimeout, err := client.HExists("config:app", "timeout") if hasTimeout { timeout, _ := client.HGet("config:app", "timeout") fmt.Printf("超时设置: %s\n", timeout) } else { fmt.Println("使用默认超时设置") } ``` ### 列表操作 列表操作适合实现队列、栈、时间线等数据结构。 #### LPush - 从左侧推入 **函数签名:** ```go func (c *Client) LPush(key string, values ...interface{}) (int64, error) ``` **参数说明:** - `key` (string): 列表键名 - `values` (...interface{}): 要推入的值(可变参数) - 返回值: `(int64, error)` - 推入后列表长度和错误 **使用场景:** - 实现栈(后进先出) - 消息队列 - 最新数据优先 - 任务队列 **示例:** ```go // 推入单个元素 length, err := client.LPush("task_queue", "task1") if err != nil { log.Printf("推入任务失败: %v", err) } else { fmt.Printf("队列长度: %d\n", length) } // 批量推入元素 length, err = client.LPush("recent_actions", "login", "view_profile", "update_settings") if err == nil { fmt.Printf("推入后列表长度: %d\n", length) } // 实现消息队列 messages := []string{"msg1", "msg2", "msg3"} for _, msg := range messages { client.LPush("message_queue", msg) } ``` #### RPush - 从右侧推入 **函数签名:** ```go func (c *Client) RPush(key string, values ...interface{}) (int64, error) ``` **参数说明:** - `key` (string): 列表键名 - `values` (...interface{}): 要推入的值(可变参数) - 返回值: `(int64, error)` - 推入后列表长度和错误 **使用场景:** - 实现队列(先进先出) - 时间线 - 日志记录 - 数据收集 **示例:** ```go // 推入单个元素 length, err := client.RPush("user_actions", "click_button") if err != nil { log.Printf("记录用户行为失败: %v", err) } // 批量推入元素 actions := []string{"login", "browse", "purchase", "logout"} for _, action := range actions { client.RPush("user_timeline", action) } // 实现日志队列 logEntry := map[string]interface{}{ "timestamp": time.Now(), "level": "INFO", "message": "User logged in", "user_id": 12345, } client.RPush("app_logs", logEntry) ``` #### LPop - 从左侧弹出 **函数签名:** ```go func (c *Client) LPop(key string) (string, error) ``` **参数说明:** - `key` (string): 列表键名 - 返回值: `(string, error)` - 弹出的值和错误 **使用场景:** - 栈操作(后进先出) - 任务处理 - 消息消费 - 优先级队列 **示例:** ```go // 弹出任务 task, err := client.LPop("task_queue") if err != nil { if err == redis.ErrNil { fmt.Println("任务队列为空") } else { log.Printf("弹出任务失败: %v", err) } } else { fmt.Printf("处理任务: %s\n", task) // 处理任务... } // 实现工作队列 for { task, err := client.LPop("work_queue") if err == redis.ErrNil { // 队列为空,等待一段时间 time.Sleep(1 * time.Second) continue } else if err != nil { log.Printf("获取任务失败: %v", err) break } // 处理任务 processTask(task) } ``` #### RPop - 从右侧弹出 **函数签名:** ```go func (c *Client) RPop(key string) (string, error) ``` **参数说明:** - `key` (string): 列表键名 - 返回值: `(string, error)` - 弹出的值和错误 **使用场景:** - 队列操作(先进先出) - 消息消费 - 数据流处理 - 日志处理 **示例:** ```go // 弹出消息 message, err := client.RPop("message_queue") if err != nil { if err == redis.ErrNil { fmt.Println("消息队列为空") } else { log.Printf("弹出消息失败: %v", err) } } else { fmt.Printf("处理消息: %s\n", message) } // 实现FIFO队列 for { item, err := client.RPop("fifo_queue") if err == redis.ErrNil { break // 队列为空,退出 } else if err != nil { log.Printf("处理队列失败: %v", err) break } // 处理队列项 processItem(item) } ``` #### LLen - 获取列表长度 **函数签名:** ```go func (c *Client) LLen(key string) (int64, error) ``` **参数说明:** - `key` (string): 列表键名 - 返回值: `(int64, error)` - 列表长度和错误 **使用场景:** - 队列监控 - 容量检查 - 性能统计 - 负载均衡 **示例:** ```go // 检查队列长度 queueLength, err := client.LLen("task_queue") if err != nil { log.Printf("获取队列长度失败: %v", err) } else { fmt.Printf("任务队列长度: %d\n", queueLength) // 根据队列长度调整处理策略 if queueLength > 1000 { fmt.Println("队列积压严重,需要增加处理能力") } else if queueLength == 0 { fmt.Println("队列为空,可以暂停处理") } } // 监控多个队列 queues := []string{"high_priority", "normal_priority", "low_priority"} for _, queue := range queues { length, _ := client.LLen(queue) fmt.Printf("%s 队列长度: %d\n", queue, length) } ``` #### LRange - 获取列表范围 **函数签名:** ```go func (c *Client) LRange(key string, start, stop int64) ([]string, error) ``` **参数说明:** - `key` (string): 列表键名 - `start` (int64): 开始索引(包含) - `stop` (int64): 结束索引(包含,-1表示到末尾) - 返回值: `([]string, error)` - 范围内的元素和错误 **使用场景:** - 分页查询 - 历史记录 - 数据浏览 - 列表展示 **示例:** ```go // 获取所有元素 allItems, err := client.LRange("user_actions", 0, -1) if err != nil { log.Printf("获取用户行为失败: %v", err) } else { fmt.Printf("用户行为记录: %v\n", allItems) } // 分页获取(每页10条) pageSize := int64(10) page := int64(1) start := (page - 1) * pageSize stop := start + pageSize - 1 items, err := client.LRange("news_feed", start, stop) if err == nil { fmt.Printf("第 %d 页新闻: %v\n", page, items) } // 获取最新的5条记录 recentItems, err := client.LRange("recent_logs", 0, 4) if err == nil { fmt.Printf("最新日志: %v\n", recentItems) } ``` ### 集合操作 ```go // 添加集合成员 added, err := client.SAdd("set", "member1", "member2") // 删除集合成员 removed, err := client.SRem("set", "member1") // 获取所有成员 members, err := client.SMembers("set") // 检查成员是否存在 exists, err := client.SIsMember("set", "member1") // 获取集合大小 size, err := client.SCard("set") ``` ### 有序集合操作 ```go // 添加有序集合成员 err := client.ZAdd("scores", 95.5, "张三") // 获取有序集合范围 members, err := client.ZRange("scores", 0, -1) // 获取带分数的范围 membersWithScores, err := client.ZRangeWithScores("scores", 0, -1) // 删除成员 removed, err := client.ZRem("scores", "张三") // 获取集合大小 size, err := client.ZCard("scores") ``` ### 管道操作 ```go // 创建管道 pipeline := client.Pipeline() // 添加命令 pipeline.Add("SET", "key1", "value1") pipeline.Add("SET", "key2", "value2") pipeline.Add("GET", "key1") // 执行管道 results, err := pipeline.Exec() ``` ### 发布订阅 ```go // 发布消息 subscribers, err := client.Publish("channel", "message") // 阻塞订阅(挂起接收) // 注意:通过外部 ctx.Cancel 控制订阅退出,防止连接与 Goroutine 长期泄漏 ctx, cancel := context.WithCancel(context.Background()) go func() { time.Sleep(10 * time.Second) cancel() // 模拟10秒后停止监听 }() err = client.Subscribe(ctx, "channel", func(msg string) { fmt.Println("收到消息:", msg) }) ``` ### 事务操作 `ixRedis` 针对安全事务作了独占物理连接隔离封装: ```go // 推荐的并发安全闭包执行事务(包含被动 Discard 机制) err := client.RunTx(func(txClient *ixRedis.Client) error { // 这个 txClient 只绑定一条连接,所有以下操作都会依附这条连接缓冲 txClient.Set("tx_key1", 1) txClient.Set("tx_key2", 2) if rand.Float32() > 0.5 { return errors.New("模拟发生业务错误,底层将主动触发 DISCARD 而不提交") } return nil // 无错误将自动触发 EXEC 事务确认提交 }) ``` ## ⚙️ 配置选项 ```go config := &ixRedis.Config{ Host: "localhost", // Redis 服务器地址 Port: 6379, // Redis 端口 Password: "", // 密码 DB: 0, // 数据库编号 KeyPrefix: "", // 键前缀(新增) MaxIdle: 10, // 最大空闲连接数 MaxActive: 100, // 最大活跃连接数 IdleTimeout: 300 * time.Second, // 连接空闲超时时间 ConnectTimeout: 5 * time.Second, // 连接超时时间 ReadTimeout: 3 * time.Second, // 读取超时时间 WriteTimeout: 3 * time.Second, // 写入超时时间 Wait: true, // 是否等待连接池耗尽 } ``` ### 便捷配置函数 ```go // 使用默认配置 client, err := ixRedis.NewClient(nil) // 使用选项配置 client, err := ixRedis.NewClientWithOptions("localhost", 6379, ixRedis.WithPassword("password"), ixRedis.WithDB(1), ixRedis.WithKeyPrefix("myapp"), // 设置键前缀 ixRedis.WithMaxIdle(20), ixRedis.WithMaxActive(200), ixRedis.WithTimeout(1*time.Second, 1*time.Second, 1*time.Second), ) ``` ## 🔧 高级特性 ### 模块化设计 库采用模块化设计,按功能拆分为多个文件: - **配置管理** (`config.go`): 统一的配置结构和选项函数 - **客户端管理** (`client.go`): 客户端生命周期管理 - **多实例管理** (`manager.go`): 支持管理多个 Redis 实例 - **功能模块**: 按 Redis 数据类型拆分为独立文件 - 基础操作 (`basic.go`) - 哈希操作 (`hash.go`) - 列表操作 (`list.go`) - 集合操作 (`set.go`) - 有序集合操作 (`sorted_set.go`) - 发布订阅 (`pubsub.go`) - 事务操作 (`transaction.go`) - 管道操作 (`pipeline.go`) - **工具方法** (`utils.go`): 通用工具函数 - **便捷方法** (`helpers.go`): 快速创建客户端的辅助函数 ### 连接池管理 库自动管理连接池,支持: - 连接复用 - 自动重连 - 连接健康检查 - 超时控制 ### 错误处理 所有操作都返回错误,便于调试和错误处理: ```go value, err := client.Get("key") if err != nil { if err == redis.ErrNil { // 键不存在 } else { // 其他错误 log.Printf("Redis 操作失败: %v", err) } } ``` ### 类型化支持 库支持存储和获取任何类型的数据: - **基础类型**: 字符串、整数、浮点数、布尔值 - **复杂类型**: 结构体、map、slice、数组 - **自动序列化**: 复杂类型自动使用 JSON 序列化 - **类型安全**: 提供类型化的获取方法,避免类型转换错误 ```go // 存储不同类型的数据 client.Set("name", "张三") // 字符串 client.Set("age", 25) // 整数 client.Set("score", 95.5) // 浮点数 client.Set("is_student", true) // 布尔值 // 存储复杂类型 user := User{ID: 1, Name: "张三", Age: 25} client.Set("user", user) // 结构体 data := map[string]interface{}{ "city": "北京", "country": "中国", } client.Set("location", data) // map items := []string{"apple", "banana"} client.Set("fruits", items) // slice // 类型安全的获取(统一API) var name string var age int64 var score float64 var isStudent bool var user User var location map[string]interface{} var fruits []string client.Get("name", &name) // 字符串 client.Get("age", &age) // 整数 client.Get("score", &score) // 浮点数 client.Get("is_student", &isStudent) // 布尔值 client.Get("user", &user) // 结构体 client.Get("location", &location) // map client.Get("fruits", &fruits) // slice ``` ### 批量操作 批量操作可以显著提高性能,减少网络往返次数。 #### BatchSet - 批量设置 **函数签名:** ```go func (c *Client) BatchSet(kvs map[string]interface{}) error ``` **参数说明:** - `kvs` (map[string]interface{}): 键值对映射 **使用场景:** - 批量数据导入 - 缓存预热 - 配置批量更新 - 数据迁移 **示例:** ```go // 批量设置用户信息 users := map[string]interface{}{ "user:1": map[string]interface{}{ "id": 1, "name": "张三", "age": 25, }, "user:2": map[string]interface{}{ "id": 2, "name": "李四", "age": 30, }, "user:3": map[string]interface{}{ "id": 3, "name": "王五", "age": 28, }, } err := client.BatchSet(users) if err != nil { log.Printf("批量设置用户失败: %v", err) } // 批量设置配置 configs := map[string]interface{}{ "app:name": "MyApp", "app:version": "1.0.0", "app:debug": true, "db:host": "localhost", "db:port": 3306, "cache:ttl": 3600, } err = client.BatchSet(configs) ``` #### BatchSetWithExpire - 批量设置带过期时间 **函数签名:** ```go func (c *Client) BatchSetWithExpire(kvs map[string]interface{}, expiration time.Duration) error ``` **参数说明:** - `kvs` (map[string]interface{}): 键值对映射 - `expiration` (time.Duration): 过期时间 **使用场景:** - 临时数据批量存储 - 会话数据批量设置 - 缓存批量预热 - 限时数据存储 **示例:** ```go // 批量设置临时会话数据 sessions := map[string]interface{}{ "session:abc123": map[string]interface{}{ "user_id": 12345, "login_time": time.Now(), "permissions": []string{"read", "write"}, }, "session:def456": map[string]interface{}{ "user_id": 67890, "login_time": time.Now(), "permissions": []string{"read"}, }, } err := client.BatchSetWithExpire(sessions, 30*time.Minute) // 批量设置限时优惠券 coupons := map[string]interface{}{ "coupon:SAVE10": map[string]interface{}{ "discount": 10, "min_amount": 100, "expires_at": time.Now().Add(24*time.Hour), }, "coupon:SAVE20": map[string]interface{}{ "discount": 20, "min_amount": 200, "expires_at": time.Now().Add(24*time.Hour), }, } err = client.BatchSetWithExpire(coupons, 24*time.Hour) ``` #### BatchGet - 批量获取 **函数签名:** ```go func (c *Client) BatchGet(keys []string) (map[string]string, error) ``` **参数说明:** - `keys` ([]string): 要获取的键列表 - 返回值: `(map[string]string, error)` - 键值对映射和错误 **使用场景:** - 批量数据读取 - 缓存批量命中检查 - 数据聚合 - 性能优化 **示例:** ```go // 批量获取用户信息 userKeys := []string{"user:1", "user:2", "user:3", "user:4", "user:5"} userData, err := client.BatchGet(userKeys) if err != nil { log.Printf("批量获取用户失败: %v", err) } else { for key, value := range userData { fmt.Printf("%s: %s\n", key, value) } } // 批量获取配置信息 configKeys := []string{ "app:name", "app:version", "app:debug", "db:host", "db:port", "cache:ttl", } configs, err := client.BatchGet(configKeys) if err == nil { for key, value := range configs { fmt.Printf("配置 %s: %s\n", key, value) } } // 检查多个缓存键 cacheKeys := []string{ "cache:expensive_calc:param1", "cache:expensive_calc:param2", "cache:expensive_calc:param3", } cacheData, err := client.BatchGet(cacheKeys) if err == nil { hitCount := 0 for key, value := range cacheData { if value != "" { hitCount++ fmt.Printf("缓存命中: %s\n", key) } } fmt.Printf("缓存命中率: %d/%d\n", hitCount, len(cacheKeys)) } ``` #### BatchDel - 批量删除 **函数签名:** ```go func (c *Client) BatchDel(keys []string) (int64, error) ``` **参数说明:** - `keys` ([]string): 要删除的键列表 - 返回值: `(int64, error)` - 删除的键数量和错误 **使用场景:** - 批量清理数据 - 用户数据删除 - 缓存清理 - 数据重置 **示例:** ```go // 批量删除用户相关数据 userKeys := []string{ "user:123:profile", "user:123:settings", "user:123:session", "user:123:preferences", "user:123:history", } deleted, err := client.BatchDel(userKeys) if err != nil { log.Printf("批量删除用户数据失败: %v", err) } else { fmt.Printf("删除了 %d 个用户数据键\n", deleted) } // 清理过期缓存 expiredKeys := []string{ "cache:old_data_1", "cache:old_data_2", "cache:old_data_3", "cache:old_data_4", } deleted, err = client.BatchDel(expiredKeys) if err == nil { fmt.Printf("清理了 %d 个过期缓存\n", deleted) } // 批量删除临时数据 tempKeys := make([]string, 0) for i := 1; i <= 100; i++ { tempKeys = append(tempKeys, fmt.Sprintf("temp:data_%d", i)) } deleted, err = client.BatchDel(tempKeys) ``` ### 缓存装饰器 缓存装饰器提供了高级缓存功能,支持缓存命中统计、模式删除等特性。 #### NewCacheDecorator - 创建缓存装饰器 **函数签名:** ```go func (c *Client) NewCacheDecorator(prefix string, ttl time.Duration) *CacheDecorator ``` **参数说明:** - `prefix` (string): 缓存键前缀 - `ttl` (time.Duration): 默认过期时间 **使用场景:** - 数据库查询缓存 - 计算结果缓存 - API响应缓存 - 配置数据缓存 **示例:** ```go // 创建用户缓存装饰器 userCache := client.NewCacheDecorator("user_cache", 10*time.Minute) // 模拟数据库查询 dbQuery := func() (interface{}, error) { // 模拟数据库查询延迟 time.Sleep(100 * time.Millisecond) return map[string]interface{}{ "id": 12345, "name": "张三", "email": "zhangsan@example.com", "age": 25, "created_at": time.Now(), }, nil } // 获取或设置缓存 var user map[string]interface{} err := userCache.GetOrSet(context.Background(), "user:12345", &user, dbQuery) if err != nil { log.Printf("获取用户缓存失败: %v", err) } else { fmt.Printf("用户信息: %+v\n", user) } ``` #### GetOrSet - 获取或设置缓存 **函数签名:** ```go func (cd *CacheDecorator) GetOrSet(ctx context.Context, key string, dest interface{}, setter func() (interface{}, error)) error ``` **参数说明:** - `ctx` (context.Context): 上下文 - `key` (string): 缓存键 - `dest` (interface{}): 目标变量指针 - `setter` (func() (interface{}, error)): 数据获取函数 **使用场景:** - 缓存穿透保护 - 数据库查询优化 - 计算结果缓存 - 外部API调用缓存 **示例:** ```go // 缓存API响应 apiCache := client.NewCacheDecorator("api_cache", 5*time.Minute) // 获取天气数据 var weather map[string]interface{} err := apiCache.GetOrSet(context.Background(), "weather:beijing", &weather, func() (interface{}, error) { // 调用外部天气API return fetchWeatherFromAPI("beijing") }) // 缓存计算结果 calcCache := client.NewCacheDecorator("calc_cache", 1*time.Hour) var result float64 err = calcCache.GetOrSet(context.Background(), "fibonacci:1000", &result, func() (interface{}, error) { // 计算斐波那契数列 return calculateFibonacci(1000), nil }) ``` #### DeletePattern - 按模式删除缓存 **函数签名:** ```go func (cd *CacheDecorator) DeletePattern(pattern string) error ``` **参数说明:** - `pattern` (string): 键模式(支持通配符) **使用场景:** - 批量缓存清理 - 分类缓存管理 - 缓存失效策略 - 数据更新清理 **示例:** ```go // 删除用户相关的所有缓存 err := userCache.DeletePattern("user:*") if err != nil { log.Printf("删除用户缓存失败: %v", err) } // 删除特定用户的所有数据 err = userCache.DeletePattern("user:12345:*") // 删除过期的配置缓存 err = configCache.DeletePattern("config:old_*") ``` #### NewStatsCacheDecorator - 创建带统计的缓存装饰器 **函数签名:** ```go func (c *Client) NewStatsCacheDecorator(prefix string, ttl time.Duration) *StatsCacheDecorator ``` **参数说明:** - `prefix` (string): 缓存键前缀 - `ttl` (time.Duration): 默认过期时间 **使用场景:** - 缓存性能监控 - 命中率统计 - 缓存效果分析 - 性能优化 **示例:** ```go // 创建带统计的缓存装饰器 statsCache := client.NewStatsCacheDecorator("stats_cache", 5*time.Minute) // 执行多次操作 for i := 0; i < 10; i++ { var data string statsCache.GetOrSet(context.Background(), "data:1", &data, func() (interface{}, error) { return "cached_data", nil }) } // 获取统计信息 stats := statsCache.GetStats() fmt.Printf("缓存统计:\n") fmt.Printf(" 命中次数: %d\n", stats.HitCount) fmt.Printf(" 未命中次数: %d\n", stats.MissCount) fmt.Printf(" 设置次数: %d\n", stats.SetCount) fmt.Printf(" 命中率: %.2f%%\n", float64(stats.HitCount)/float64(stats.HitCount+stats.MissCount)*100) ``` ### 分布式锁 分布式锁用于在分布式环境中实现互斥访问,确保同一时间只有一个进程能访问共享资源。 #### NewDistributedLock - 创建分布式锁 **函数签名:** ```go func (c *Client) NewDistributedLock(key string, expiration time.Duration) *DistributedLock ``` **参数说明:** - `key` (string): 锁的键名 - `expiration` (time.Duration): 锁的过期时间 **使用场景:** - 防止重复操作 - 资源互斥访问 - 分布式任务调度 - 数据一致性保证 **示例:** ```go // 创建分布式锁 lock := client.NewDistributedLock("order:12345", 30*time.Second) // 尝试获取锁 err := lock.TryLock(context.Background()) if err != nil { log.Printf("获取锁失败: %v", err) return } defer lock.Unlock() // 执行业务逻辑 fmt.Println("处理订单...") processOrder("12345") ``` #### Lock - 阻塞获取锁 **函数签名:** ```go func (dl *DistributedLock) Lock(ctx context.Context) error ``` **参数说明:** - `ctx` (context.Context): 上下文,用于取消操作 **使用场景:** - 必须获取锁的场景 - 长时间等待锁 - 任务队列处理 - 资源竞争 **示例:** ```go // 阻塞获取锁 ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) defer cancel() err := lock.Lock(ctx) if err != nil { if err == context.DeadlineExceeded { log.Println("获取锁超时") } else { log.Printf("获取锁失败: %v", err) } return } defer lock.Unlock() // 执行业务逻辑 fmt.Println("执行业务逻辑...") ``` #### TryLock - 非阻塞获取锁 **函数签名:** ```go func (dl *DistributedLock) TryLock(ctx context.Context) (bool, error) ``` **参数说明:** - `ctx` (context.Context): 上下文 - 返回值: `(bool, error)` - 是否获取成功和错误 **使用场景:** - 快速失败场景 - 避免长时间阻塞 - 资源可用性检查 - 优雅降级 **示例:** ```go // 非阻塞尝试获取锁 acquired, err := lock.TryLock(context.Background()) if err != nil { log.Printf("尝试获取锁失败: %v", err) return } if acquired { defer lock.Unlock() fmt.Println("成功获取锁,执行业务逻辑") processCriticalSection() } else { fmt.Println("锁被其他进程持有,跳过处理") // 执行降级逻辑 fallbackProcess() } ``` #### Refresh - 刷新锁 **函数签名:** ```go func (dl *DistributedLock) Refresh() error ``` **参数说明:** - 无参数 **使用场景:** - 长时间任务处理 - 防止锁过期 - 任务续期 - 保持锁状态 **示例:** ```go // 长时间任务处理 lock := client.NewDistributedLock("long_task", 10*time.Second) err := lock.TryLock(context.Background()) if err != nil { return } defer lock.Unlock() // 定期刷新锁 ticker := time.NewTicker(5 * time.Second) defer ticker.Stop() go func() { for range ticker.C { if err := lock.Refresh(); err != nil { log.Printf("刷新锁失败: %v", err) break } fmt.Println("锁已刷新") } }() // 执行长时间任务 processLongTask() ``` #### NewLockManager - 创建锁管理器 **函数签名:** ```go func (c *Client) NewLockManager() *LockManager ``` **参数说明:** - 无参数 **使用场景:** - 管理多个锁 - 锁的生命周期管理 - 批量锁操作 - 锁状态监控 **示例:** ```go // 创建锁管理器 manager := client.NewLockManager() // 获取锁 lock, err := manager.AcquireLock("resource:1", 30*time.Second) if err != nil { log.Printf("获取锁失败: %v", err) return } // 执行业务逻辑 fmt.Println("执行业务逻辑...") // 释放锁 err = manager.ReleaseLock("resource:1") if err != nil { log.Printf("释放锁失败: %v", err) } ``` ### 限流功能 限流功能用于控制系统的访问频率,防止系统过载。 #### NewRateLimiter - 创建滑动窗口限流器 **函数签名:** ```go func (c *Client) NewRateLimiter(key string, limit int64, window time.Duration) *RateLimiter ``` **参数说明:** - `key` (string): 限流器键名 - `limit` (int64): 时间窗口内允许的最大请求数 - `window` (time.Duration): 时间窗口大小 **使用场景:** - API接口限流 - 用户行为限制 - 系统保护 - 资源访问控制 **示例:** ```go // 创建API限流器(每分钟最多100个请求) apiLimiter := client.NewRateLimiter("api:user", 100, time.Minute) // 检查是否允许请求 allowed, err := apiLimiter.Allow(context.Background()) if err != nil { log.Printf("限流检查失败: %v", err) return } if allowed { fmt.Println("请求被允许") // 处理请求 handleAPIRequest() } else { fmt.Println("请求被限流") // 返回限流错误 return errors.New("rate limit exceeded") } ``` #### AllowN - 批量请求限流 **函数签名:** ```go func (rl *RateLimiter) AllowN(ctx context.Context, n int64) (bool, int64, error) ``` **参数说明:** - `ctx` (context.Context): 上下文 - `n` (int64): 请求数量 - 返回值: `(bool, int64, error)` - 是否允许、剩余请求数、错误 **使用场景:** - 批量操作限流 - 资源配额管理 - 批量API调用 - 批量数据处理 **示例:** ```go // 批量处理请求 batchSize := int64(10) allowed, remaining, err := apiLimiter.AllowN(context.Background(), batchSize) if err != nil { log.Printf("批量限流检查失败: %v", err) return } if allowed { fmt.Printf("允许处理 %d 个请求,剩余配额: %d\n", batchSize, remaining) processBatchRequests(batchSize) } else { fmt.Printf("限流,剩余配额: %d\n", remaining) // 分批处理或等待 processPartialRequests(remaining) } ``` #### NewTokenBucketRateLimiter - 创建令牌桶限流器 **函数签名:** ```go func (c *Client) NewTokenBucketRateLimiter(key string, capacity, refillRate int64, refillTime time.Duration) *TokenBucketRateLimiter ``` **参数说明:** - `key` (string): 限流器键名 - `capacity` (int64): 桶的容量 - `refillRate` (int64): 每次补充的令牌数 - `refillTime` (time.Duration): 补充令牌的时间间隔 **使用场景:** - 突发流量处理 - 平滑限流 - 带宽控制 - 资源分配 **示例:** ```go // 创建令牌桶限流器(容量100,每秒补充10个令牌) tokenLimiter := client.NewTokenBucketRateLimiter("api:burst", 100, 10, time.Second) // 检查是否允许请求 allowed, err := tokenLimiter.Allow(context.Background()) if err != nil { log.Printf("令牌桶限流检查失败: %v", err) return } if allowed { fmt.Println("请求被允许") // 处理请求 handleRequest() } else { fmt.Println("令牌不足,请求被限流") // 等待或拒绝请求 } // 获取当前令牌数 tokens, err := tokenLimiter.GetTokens(context.Background()) if err == nil { fmt.Printf("当前令牌数: %d\n", tokens) } ``` #### GetRemaining - 获取剩余请求数 **函数签名:** ```go func (rl *RateLimiter) GetRemaining(ctx context.Context) (int64, error) ``` **参数说明:** - `ctx` (context.Context): 上下文 - 返回值: `(int64, error)` - 剩余请求数和错误 **使用场景:** - 显示剩余配额 - 用户提示 - 监控统计 - 负载均衡 **示例:** ```go // 获取剩余请求数 remaining, err := apiLimiter.GetRemaining(context.Background()) if err != nil { log.Printf("获取剩余请求数失败: %v", err) return } fmt.Printf("剩余请求数: %d\n", remaining) // 根据剩余配额调整处理策略 if remaining < 10 { fmt.Println("配额不足,建议用户稍后重试") } else if remaining < 50 { fmt.Println("配额较少,建议用户合理使用") } else { fmt.Println("配额充足,正常处理") } ``` ### 监控指标 监控指标功能提供了详细的性能统计和健康检查功能。 #### NewMetricsClient - 创建带指标的客户端 **函数签名:** ```go func (c *Client) NewMetricsClient() *MetricsClient ``` **参数说明:** - 无参数 **使用场景:** - 性能监控 - 延迟统计 - 成功率监控 - 系统诊断 **示例:** ```go // 创建带指标的客户端 metricsClient := client.NewMetricsClient() // 执行操作(自动记录指标) err := metricsClient.Set("key1", "value1") if err != nil { log.Printf("设置失败: %v", err) } var value string exists, err := metricsClient.Get("key1", &value) if err != nil { log.Printf("获取失败: %v", err) } // 获取统计信息 metrics := metricsClient.GetMetrics() stats := metrics.GetStats() fmt.Printf("总操作数: %d\n", stats["total_operations"]) fmt.Printf("成功操作数: %d\n", stats["successful_operations"]) fmt.Printf("失败操作数: %d\n", stats["failed_operations"]) fmt.Printf("成功率: %.2f%%\n", stats["success_rate"]) fmt.Printf("平均延迟: %v\n", stats["average_latency"]) fmt.Printf("最大延迟: %v\n", stats["max_latency"]) fmt.Printf("最小延迟: %v\n", stats["min_latency"]) ``` #### GetStats - 获取统计信息 **函数签名:** ```go func (m *Metrics) GetStats() map[string]interface{} ``` **参数说明:** - 无参数 - 返回值: `map[string]interface{}` - 统计信息映射 **使用场景:** - 性能报告 - 监控面板 - 告警系统 - 数据分析 **示例:** ```go // 获取详细统计信息 stats := metrics.GetStats() // 连接统计 fmt.Printf("总连接数: %d\n", stats["total_connections"]) fmt.Printf("活跃连接数: %d\n", stats["active_connections"]) fmt.Printf("失败连接数: %d\n", stats["failed_connections"]) // 操作统计 fmt.Printf("总操作数: %d\n", stats["total_operations"]) fmt.Printf("成功操作数: %d\n", stats["successful_operations"]) fmt.Printf("失败操作数: %d\n", stats["failed_operations"]) // 性能统计 fmt.Printf("总延迟: %v\n", stats["total_latency"]) fmt.Printf("平均延迟: %v\n", stats["average_latency"]) fmt.Printf("最大延迟: %v\n", stats["max_latency"]) fmt.Printf("最小延迟: %v\n", stats["min_latency"]) // 命令统计 commandCounts := stats["command_counts"].(map[string]int64) for command, count := range commandCounts { fmt.Printf("%s 命令执行次数: %d\n", command, count) } // 时间统计 fmt.Printf("运行时间: %v\n", stats["uptime"]) fmt.Printf("最后操作时间: %v\n", stats["last_operation_time"]) ``` #### Reset - 重置统计信息 **函数签名:** ```go func (m *Metrics) Reset() ``` **参数说明:** - 无参数 **使用场景:** - 定期重置统计 - 测试环境清理 - 重新开始统计 - 性能基准测试 **示例:** ```go // 重置统计信息 metrics.Reset() // 执行新的测试 for i := 0; i < 1000; i++ { key := fmt.Sprintf("test_key_%d", i) value := fmt.Sprintf("test_value_%d", i) metricsClient.Set(key, value) } // 获取新的统计信息 newStats := metrics.GetStats() fmt.Printf("新测试总操作数: %d\n", newStats["total_operations"]) ``` #### NewHealthCheck - 创建健康检查 **函数签名:** ```go func (c *Client) NewHealthCheck(timeout time.Duration) *HealthCheck ``` **参数说明:** - `timeout` (time.Duration): 健康检查超时时间 **使用场景:** - 服务健康检查 - 负载均衡器检查 - 监控系统 - 自动故障转移 **示例:** ```go // 创建健康检查 healthCheck := client.NewHealthCheck(5 * time.Second) // 检查Redis是否健康 if healthCheck.IsHealthy() { fmt.Println("Redis 连接健康") } else { fmt.Println("Redis 连接异常") } // 定期健康检查 ticker := time.NewTicker(30 * time.Second) defer ticker.Stop() go func() { for range ticker.C { if !healthCheck.IsHealthy() { log.Println("Redis 健康检查失败,尝试重连...") // 执行重连逻辑 reconnectRedis() } } }() ``` #### Check - 执行健康检查 **函数签名:** ```go func (hc *HealthCheck) Check() error ``` **参数说明:** - 无参数 - 返回值: `error` - 检查结果 **使用场景:** - 详细健康检查 - 错误诊断 - 监控集成 - 故障排查 **示例:** ```go // 执行健康检查 err := healthCheck.Check() if err != nil { log.Printf("健康检查失败: %v", err) // 根据错误类型处理 if strings.Contains(err.Error(), "timeout") { log.Println("Redis 响应超时") } else if strings.Contains(err.Error(), "connection refused") { log.Println("Redis 连接被拒绝") } else { log.Printf("其他错误: %v", err) } } else { fmt.Println("Redis 健康检查通过") } ``` ### 性能优化 - 使用连接池减少连接开销 - 支持管道操作提高批量操作性能 - 支持并发操作 - 自动连接健康检查 - 批量操作减少网络往返次数 - 缓存装饰器提高数据访问性能 - 分布式锁确保数据一致性 - 限流功能保护系统稳定性 - 类型转换优化提高序列化性能 - 配置验证确保参数有效性 ## 📊 性能测试 库包含完整的测试套件,可以测试: - SET/GET 操作性能 - 管道操作性能 - 并发操作性能 - 批量操作性能 - 缓存装饰器性能 - 分布式锁性能 - 限流器性能 运行测试: ```bash # 运行所有测试 go test -v ./tests/... # 运行特定测试 go test -v ./tests/basic_test.go # 运行基准测试 go test -bench=. ./tests/... # 运行测试覆盖率 go test -cover ./tests/... ``` ## 🛡️ 安全特性 - 线程安全,支持并发操作 - 连接池自动管理,避免连接泄露 - 超时控制,避免长时间阻塞 - 错误处理完善,不会引起程序崩溃 - 分布式锁防止并发冲突 - 限流功能防止系统过载 - 配置验证确保参数安全 - 健康检查确保连接可用性 ## 🎯 使用场景总结 ### 基础场景 - **用户会话管理**: 使用 `SetWithExpire` 存储用户会话,自动过期 - **配置数据缓存**: 使用 `Set` 存储应用配置,`Get` 快速读取 - **临时数据存储**: 使用 `SetWithExpire` 存储验证码、临时令牌等 - **数据缓存**: 使用缓存装饰器缓存数据库查询结果 ### 高级场景 - **分布式任务队列**: 使用列表操作实现任务队列 - **实时排行榜**: 使用有序集合实现排行榜功能 - **用户标签系统**: 使用集合操作管理用户标签 - **消息发布订阅**: 使用发布订阅功能实现消息推送 - **分布式锁**: 使用分布式锁防止重复操作 - **API限流**: 使用限流器保护API接口 - **性能监控**: 使用监控指标分析系统性能 ### 最佳实践 #### 1. 键命名规范 ```go // 推荐的键命名格式 "user:123:profile" // 用户数据 "session:abc123" // 会话数据 "cache:api:user:123" // 缓存数据 "lock:order:12345" // 分布式锁 "rate_limit:api:user" // 限流器 ``` #### 2. 过期时间设置 ```go // 根据数据类型设置合理的过期时间 client.SetWithExpire("session:abc123", sessionData, 30*time.Minute) // 会话 client.SetWithExpire("sms_code:13800138000", "123456", 5*time.Minute) // 验证码 client.SetWithExpire("cache:expensive_calc", result, 1*time.Hour) // 缓存 ``` #### 3. 错误处理 ```go // 统一的错误处理模式 var value string exists, err := client.Get("key", &value) if err != nil { if err == redis.ErrNil { // 键不存在,使用默认值 value = "default_value" } else { // 其他错误,记录日志 log.Printf("Redis操作失败: %v", err) return err } } ``` #### 4. 批量操作优化 ```go // 使用批量操作提高性能 keys := []string{"key1", "key2", "key3", "key4", "key5"} values, err := client.BatchGet(keys) if err != nil { log.Printf("批量获取失败: %v", err) return } // 处理批量结果 for key, value := range values { if value != "" { fmt.Printf("%s: %s\n", key, value) } } ``` #### 5. 缓存策略 ```go // 使用缓存装饰器实现缓存策略 cache := client.NewCacheDecorator("user_cache", 10*time.Minute) var user User err := cache.GetOrSet(context.Background(), "user:123", &user, func() (interface{}, error) { // 数据库查询 return db.GetUser(123) }) ``` #### 6. 限流策略 ```go // 根据业务需求设置限流参数 // API限流:每分钟100次请求 apiLimiter := client.NewRateLimiter("api:user", 100, time.Minute) // 用户限流:每小时1000次操作 userLimiter := client.NewRateLimiter("user:123", 1000, time.Hour) // 令牌桶限流:支持突发流量 burstLimiter := client.NewTokenBucketRateLimiter("api:burst", 100, 10, time.Second) ``` #### 7. 全局前缀策略 ```go // 为不同应用设置不同的前缀 appClient, _ := ixRedis.NewClientWithOptions("localhost", 6379, ixRedis.WithKeyPrefix("myapp"), // 应用前缀 ixRedis.WithPassword("123456"), ) adminClient, _ := ixRedis.NewClientWithOptions("localhost", 6379, ixRedis.WithKeyPrefix("admin"), // 管理后台前缀 ixRedis.WithPassword("123456"), ) // 使用前缀时,键会自动加上前缀 appClient.Set("user:123", "用户数据") // 实际键: myapp:user:123 adminClient.Set("user:123", "管理员数据") // 实际键: admin:user:123 ``` #### 8. 数据库隔离策略 ```go // 为不同业务模块使用不同数据库 userClient, _ := ixRedis.NewClientWithOptions("localhost", 6379, ixRedis.WithDB(1), // 用户数据数据库 ixRedis.WithPassword("123456"), ) sessionClient, _ := ixRedis.NewClientWithOptions("localhost", 6379, ixRedis.WithDB(2), // 会话数据数据库 ixRedis.WithPassword("123456"), ) cacheClient, _ := ixRedis.NewClientWithOptions("localhost", 6379, ixRedis.WithDB(3), // 缓存数据数据库 ixRedis.WithPassword("123456"), ) // 每个客户端在各自的数据库中操作,完全隔离 userClient.Set("user:123", "用户信息") sessionClient.Set("session:abc", "会话数据") cacheClient.Set("cache:data", "缓存数据") ``` ## 📝 注意事项 1. **资源管理**: 使用完毕后记得调用 `Close()` 方法关闭客户端 2. **性能优化**: 对于大量数据操作,建议使用管道操作或批量操作 3. **连接池配置**: 合理设置连接池参数以平衡性能和资源使用 4. **安全设置**: 生产环境建议设置密码和适当的超时时间 5. **模块化设计**: 库采用模块化设计,每个文件专注于特定功能,便于维护和扩展 6. **分布式锁**: 使用分布式锁时注意设置合理的过期时间,避免死锁 7. **限流参数**: 限流器需要根据业务需求调整参数,避免误限流 8. **监控指标**: 监控指标可以帮助发现性能瓶颈,建议定期检查 9. **缓存策略**: 缓存装饰器适合读多写少的场景,注意缓存一致性 10. **配置验证**: 配置验证可以避免运行时错误,建议在启动时验证配置 11. **键过期**: 合理设置键的过期时间,避免内存泄漏 12. **错误处理**: 完善的错误处理机制,避免程序崩溃 13. **并发安全**: 库是线程安全的,可以在多个goroutine中并发使用 14. **网络超时**: 设置合适的网络超时时间,避免长时间阻塞 15. **健康检查**: 定期进行健康检查,确保Redis连接可用 16. **🏷️ 全局前缀**: 使用前缀功能时,所有键操作都会自动加上前缀,注意键的命名 17. **🗄️ 数据库隔离**: 不同数据库的客户端实例完全隔离,无法访问彼此的数据 18. **配置隔离**: 每个不同的配置都会生成独立的连接池,避免配置冲突 ## 🤝 贡献 欢迎提交 Issue 和 Pull Request! ## 📄 许可证 MIT License