Redis数据结构与性能优化详解
Redis数据结构与性能优化详解1. Redis数据类型1.1 字符串(String)最基本的数据类型// 设置值 rdb.Set(ctx, name, John, 0) rdb.SetNX(ctx, name, John, 0) // 不存在时设置 rdb.SetEx(ctx, name, John, 3600) // 设置过期时间 // 获取值 val, err : rdb.Get(ctx, name).Result() // 批量操作 rdb.MSet(ctx, key1, value1, key2, value2) rdb.MGet(ctx, key1, key2)1.2 哈希(Hash)适合存储对象// 设置哈希 rdb.HSet(ctx, user:1, map[string]interface{}{ name: John, age: 30, email: johnexample.com, }) // 获取字段 name, _ : rdb.HGet(ctx, user:1, name).Result() // 获取所有字段 user, _ : rdb.HGetAll(ctx, user:1).Result() // 字段自增 rdb.HIncrBy(ctx, user:1, age, 1)1.3 列表(List)有序集合支持栈和队列操作// 左插入 rdb.LPush(ctx, tasks, task1) rdb.LPush(ctx, tasks, task2) // 右插入 rdb.RPush(ctx, tasks, task3) // 获取范围 tasks, _ : rdb.LRange(ctx, tasks, 0, -1).Result() // 弹出 task, _ : rdb.LPop(ctx, tasks).Result()1.4 集合(Set)无序不重复// 添加 rdb.SAdd(ctx, tags, go, redis, database) // 获取所有 tags, _ : rdb.SMembers(ctx, tags).Result() // 判断是否存在 isMember, _ : rdb.SIsMember(ctx, tags, go).Result() // 交集 common, _ : rdb.SInter(ctx, tags1, tags2).Result()1.5 有序集合(ZSet)按分数排序// 添加 rdb.ZAdd(ctx, leaderboard, redis.Z{ Score: 100, Member: player1, }) rdb.ZAdd(ctx, leaderboard, redis.Z{ Score: 90, Member: player2, }) // 获取排名 rank, _ : rdb.ZRevRank(ctx, leaderboard, player1).Result() // 获取分数 score, _ : rdb.ZScore(ctx, leaderboard, player1).Result() // 获取topN topPlayers, _ : rdb.ZRevRangeWithScores(ctx, leaderboard, 0, 9).Result()2. Go语言Redis客户端2.1 go-redis客户端import github.com/redis/go-redis/v9 rdb : redis.NewClient(redis.Options{ Addr: localhost:6379, Password: , DB: 0, PoolSize: 10, }) defer rdb.Close()2.2 连接池配置rdb : redis.NewClient(redis.Options{ Addr: localhost:6379, Password: , DB: 0, PoolSize: 100, // 连接池大小 MinIdleConns: 10, // 最小空闲连接 MaxRetries: 3, // 最大重试次数 DialTimeout: 5 * time.Second, ReadTimeout: 3 * time.Second, WriteTimeout: 3 * time.Second, })3. 性能优化3.1 管道操作批量执行命令减少网络开销pipe : rdb.Pipeline() pipe.Set(ctx, key1, value1, 0) pipe.Set(ctx, key2, value2, 0) pipe.Get(ctx, key1) pipe.Incr(ctx, counter) cmds, err : pipe.Exec(ctx) for _, cmd : range cmds { // 处理结果 }3.2 事务pipe : rdb.TxPipeline() pipe.Set(ctx, key1, value1, 0) pipe.Set(ctx, key2, value2, 0) _, err : pipe.Exec(ctx)3.3 Lua脚本原子执行script : redis.NewScript( local current redis.call(GET, KEYS[1]) if current ARGV[1] then redis.call(SET, KEYS[1], ARGV[2]) return 1 else return 0 end ) result, err : script.Run(ctx, rdb, []string{key}, expected, new_value).Result()4. 缓存策略4.1 Cache-Aside模式func GetUser(ctx context.Context, rdb *redis.Client, db *sql.DB, userID int) (*User, error) { // 1. 先查Redis cacheKey : fmt.Sprintf(user:%d, userID) cached, err : rdb.Get(ctx, cacheKey).Result() if err nil { var user User json.Unmarshal([]byte(cached), user) return user, nil } // 2. 缓存不存在查数据库 var user User err db.QueryRowContext(ctx, SELECT * FROM users WHERE id ?, userID).Scan(user) if err ! nil { return nil, err } // 3. 写入缓存 data, _ : json.Marshal(user) rdb.Set(ctx, cacheKey, data, 30*time.Minute) return user, nil }4.2 缓存过期策略// 设置过期时间 rdb.Set(ctx, key, value, 30*time.Minute) // 延长过期时间 rdb.Expire(ctx, key, 1*time.Hour) // 查看剩余时间 ttl, _ : rdb.TTL(ctx, key).Result()5. 分布式锁5.1 实现func AcquireLock(ctx context.Context, rdb *redis.Client, key string, expiration time.Duration) (bool, error) { result, err : rdb.SetNX(ctx, lock:key, 1, expiration).Result() return result, err } func ReleaseLock(ctx context.Context, rdb *redis.Client, key string) error { return rdb.Del(ctx, lock:key).Err() }5.1 可重入锁type RedLock struct { rdb *redis.Client keys []string values []string } func (l *RedLock) Lock(ctx context.Context, expiration time.Duration) (bool, error) { for i, key : range l.keys { ok, err : l.rdb.SetNX(ctx, key, l.values[i], expiration).Result() if err ! nil || !ok { return false, nil } } return true, nil }6. 消息队列6.1 发布订阅// 发布 rdb.Publish(ctx, channel1, message1) // 订阅 sub : rdb.Subscribe(ctx, channel1) defer sub.Close() for msg : range sub.Channel() { fmt.Println(msg.Channel, msg.Payload) }6.2 Stream// 添加消息 id, err : rdb.XAdd(ctx, redis.XAddArgs{ Stream: mystream, Values: map[string]interface{}{field: value}, }).Result() // 读取消息 messages, err : rdb.XRead(ctx, redis.XReadArgs{ Streams: []string{mystream}, Count: 10, }).Result()7. 最佳实践7.1 键命名规范业务:对象:属性 user:1:profile order:2023:status session:abc1237.2 内存优化选择合适的数据结构使用压缩存储大值定期清理过期键合理设置maxmemory7.3 持久化配置# RDB配置 save 900 1 save 300 10 save 60 10000 # AOF配置 appendonly yes appendfsync everysec8. 总结Redis作为高性能缓存和消息队列在现代应用中发挥重要作用。通过合理使用数据结构、管道操作、Lua脚本等特性可以构建高效的缓存系统和分布式应用。