当前位置: 首页 > news >正文

Go语言Redis缓存技术实战

Go语言Redis缓存技术实战引言Redis是目前最流行的内存数据库之一被广泛应用于缓存、会话管理、消息队列等场景。Go语言通过go-redis库可以高效地与Redis进行交互。本文将深入探讨Go语言中Redis缓存技术的实战应用。一、环境配置与连接1.1 安装依赖go get github.com/go-redis/redis/v81.2 基本连接配置package main import ( context fmt log github.com/go-redis/redis/v8 ) var ctx context.Background() func main() { // 创建Redis客户端 rdb : redis.NewClient(redis.Options{ Addr: localhost:6379, Password: , // 没有密码时为空 DB: 0, // 使用默认数据库 PoolSize: 10, // 连接池大小 }) // 测试连接 pong, err : rdb.Ping(ctx).Result() if err ! nil { log.Fatalf(Failed to connect to Redis: %v, err) } fmt.Println(Connected to Redis:, pong) }二、基础数据类型操作2.1 String类型func StringOperations(rdb *redis.Client) error { // 设置值 err : rdb.Set(ctx, user:1:name, John, 0).Err() if err ! nil { return err } // 获取值 name, err : rdb.Get(ctx, user:1:name).Result() if err ! nil { return err } fmt.Println(User name:, name) // 设置过期时间 err rdb.Set(ctx, temp:token, abc123, 60*time.Second).Err() if err ! nil { return err } // 原子递增 count, err : rdb.Incr(ctx, counter).Result() if err ! nil { return err } fmt.Println(Counter:, count) return nil }2.2 Hash类型func HashOperations(rdb *redis.Client) error { // 设置Hash字段 err : rdb.HSet(ctx, user:1, map[string]interface{}{ name: John, email: johnexample.com, age: 30, created: time.Now().Unix(), }).Err() if err ! nil { return err } // 获取Hash字段 user, err : rdb.HGetAll(ctx, user:1).Result() if err ! nil { return err } fmt.Println(User:, user) // 获取单个字段 email, err : rdb.HGet(ctx, user:1, email).Result() if err ! nil { return err } fmt.Println(Email:, email) // 递增字段值 newAge, err : rdb.HIncrBy(ctx, user:1, age, 1).Result() if err ! nil { return err } fmt.Println(New age:, newAge) return nil }2.3 List类型func ListOperations(rdb *redis.Client) error { // 从左侧插入 err : rdb.LPush(ctx, queue:tasks, task1, task2, task3).Err() if err ! nil { return err } // 从右侧弹出队列 task, err : rdb.RPop(ctx, queue:tasks).Result() if err ! nil { return err } fmt.Println(Processed task:, task) // 获取列表长度 length, err : rdb.LLen(ctx, queue:tasks).Result() if err ! nil { return err } fmt.Println(Queue length:, length) // 获取列表范围 tasks, err : rdb.LRange(ctx, queue:tasks, 0, -1).Result() if err ! nil { return err } fmt.Println(All tasks:, tasks) return nil }2.4 Set类型func SetOperations(rdb *redis.Client) error { // 添加元素到集合 err : rdb.SAdd(ctx, users:online, user1, user2, user3).Err() if err ! nil { return err } // 检查元素是否存在 exists, err : rdb.SIsMember(ctx, users:online, user1).Result() if err ! nil { return err } fmt.Println(User1 online:, exists) // 获取集合大小 count, err : rdb.SCard(ctx, users:online).Result() if err ! nil { return err } fmt.Println(Online count:, count) // 集合交集 err rdb.SAdd(ctx, users:vip, user1, user4).Err() if err ! nil { return err } vipOnline, err : rdb.SInter(ctx, users:online, users:vip).Result() if err ! nil { return err } fmt.Println(VIP users online:, vipOnline) return nil }2.5 Sorted Set类型func SortedSetOperations(rdb *redis.Client) error { // 添加元素到有序集合 err : rdb.ZAdd(ctx, leaderboard, redis.Z{ Score: 100, Member: player1, }, redis.Z{ Score: 85, Member: player2, }, redis.Z{ Score: 95, Member: player3, }).Err() if err ! nil { return err } // 获取排名从高到低 rank, err : rdb.ZRevRank(ctx, leaderboard, player1).Result() if err ! nil { return err } fmt.Println(Player1 rank:, rank1) // 获取前N名 topPlayers, err : rdb.ZRevRangeWithScores(ctx, leaderboard, 0, 2).Result() if err ! nil { return err } for _, player : range topPlayers { fmt.Printf(%s: %.0f\n, player.Member, player.Score) } // 增加分数 newScore, err : rdb.ZIncrBy(ctx, leaderboard, 10, player2).Result() if err ! nil { return err } fmt.Println(Player2 new score:, newScore) return nil }三、缓存策略实现3.1 缓存与数据库读写模式type User struct { ID int Name string Email string } func GetUser(rdb *redis.Client, db *sql.DB, userID int) (*User, error) { // 先从缓存获取 cacheKey : fmt.Sprintf(user:%d, userID) cachedUser, err : rdb.Get(ctx, cacheKey).Result() if err nil { // 缓存命中 var user User if err : json.Unmarshal([]byte(cachedUser), user); err nil { return user, nil } } // 缓存未命中从数据库获取 var user User err db.QueryRow(SELECT id, name, email FROM users WHERE id ?, userID). Scan(user.ID, user.Name, user.Email) if err ! nil { return nil, err } // 写入缓存 userJSON, _ : json.Marshal(user) rdb.Set(ctx, cacheKey, string(userJSON), 5*time.Minute) return user, nil } func UpdateUser(rdb *redis.Client, db *sql.DB, user *User) error { // 更新数据库 _, err : db.Exec(UPDATE users SET name ?, email ? WHERE id ?, user.Name, user.Email, user.ID) if err ! nil { return err } // 清除缓存 cacheKey : fmt.Sprintf(user:%d, user.ID) rdb.Del(ctx, cacheKey) return nil }3.2 缓存击穿处理var mu sync.Mutex func GetUserWithLock(rdb *redis.Client, db *sql.DB, userID int) (*User, error) { cacheKey : fmt.Sprintf(user:%d, userID) // 尝试获取缓存 cachedUser, err : rdb.Get(ctx, cacheKey).Result() if err nil { var user User json.Unmarshal([]byte(cachedUser), user) return user, nil } // 缓存未命中加锁防止击穿 mu.Lock() defer mu.Unlock() // 再次检查缓存防止重复查询 cachedUser, err rdb.Get(ctx, cacheKey).Result() if err nil { var user User json.Unmarshal([]byte(cachedUser), user) return user, nil } // 查询数据库 var user User err db.QueryRow(SELECT id, name, email FROM users WHERE id ?, userID). Scan(user.ID, user.Name, user.Email) if err ! nil { return nil, err } // 设置缓存 userJSON, _ : json.Marshal(user) rdb.Set(ctx, cacheKey, string(userJSON), 5*time.Minute) return user, nil }四、分布式锁实现4.1 基于Redis的分布式锁func AcquireLock(rdb *redis.Client, lockKey string, timeout time.Duration) (bool, error) { // 使用SET NX获取锁 result, err : rdb.SetNX(ctx, lockKey, locked, timeout).Result() if err ! nil { return false, err } return result, nil } func ReleaseLock(rdb *redis.Client, lockKey string) error { // 使用Lua脚本原子性删除锁 script : if redis.call(GET, KEYS[1]) ARGV[1] then return redis.call(DEL, KEYS[1]) else return 0 end _, err : rdb.Eval(ctx, script, []string{lockKey}, locked).Result() return err } func WithLock(rdb *redis.Client, lockKey string, timeout time.Duration, fn func() error) error { // 获取锁 acquired, err : AcquireLock(rdb, lockKey, timeout) if err ! nil { return err } if !acquired { return fmt.Errorf(failed to acquire lock) } defer ReleaseLock(rdb, lockKey) // 执行临界区代码 return fn() }五、消息队列实现5.1 使用List实现队列type MessageQueue struct { rdb *redis.Client queueKey string } func NewMessageQueue(rdb *redis.Client, queueKey string) *MessageQueue { return MessageQueue{ rdb: rdb, queueKey: queueKey, } } func (mq *MessageQueue) Publish(message string) error { return mq.rdb.RPush(ctx, mq.queueKey, message).Err() } func (mq *MessageQueue) Subscribe() (string, error) { // 阻塞式弹出BLPOP result, err : mq.rdb.BLPop(ctx, 0, mq.queueKey).Result() if err ! nil { return , err } // 返回值格式: [key, value] return result[1], nil } func (mq *MessageQueue) Len() (int64, error) { return mq.rdb.LLen(ctx, mq.queueKey).Result() }5.2 使用Pub/Sub实现发布订阅func PublishMessage(rdb *redis.Client, channel string, message string) error { return rdb.Publish(ctx, channel, message).Err() } func SubscribeChannel(rdb *redis.Client, channel string) { pubsub : rdb.Subscribe(ctx, channel) defer pubsub.Close() for { msg, err : pubsub.ReceiveMessage(ctx) if err ! nil { log.Println(Receive error:, err) continue } fmt.Printf(Received message from %s: %s\n, msg.Channel, msg.Payload) } }六、高级特性6.1 管道操作func PipelineExample(rdb *redis.Client) error { pipe : rdb.Pipeline() // 添加多个命令到管道 pipe.Set(ctx, key1, value1, 0) pipe.Set(ctx, key2, value2, 0) pipe.Incr(ctx, counter) pipe.Get(ctx, key1) // 批量执行 cmds, err : pipe.Exec(ctx) if err ! nil { return err } // 处理结果 for i, cmd : range cmds { fmt.Printf(Command %d result: %v\n, i, cmd.Val()) } return nil }6.2 事务操作func TransactionExample(rdb *redis.Client) error { tx : rdb.TxPipeline() // 添加事务命令 tx.Set(ctx, user:2:name, Alice, 0) tx.Incr(ctx, user:count) // 执行事务 _, err : tx.Exec(ctx) return err }6.3 Lua脚本func LuaScriptExample(rdb *redis.Client) error { script : local key KEYS[1] local value ARGV[1] redis.call(SET, key, value) return redis.call(GET, key) result, err : rdb.Eval(ctx, script, []string{lua:test}, hello).Result() if err ! nil { return err } fmt.Println(Lua result:, result) return nil }七、性能优化与最佳实践7.1 连接池配置func NewRedisClient() *redis.Client { return 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, PoolTimeout: 4 * time.Second, }) }7.2 缓存键设计规范const ( CacheKeyUser user:%d // 用户信息 CacheKeyUserList users:list:%d:%d // 用户列表分页 CacheKeyProduct product:%d // 商品信息 CacheKeyLockPrefix lock: // 锁前缀 ) func GetUserCacheKey(userID int) string { return fmt.Sprintf(CacheKeyUser, userID) }结语Redis作为高性能缓存数据库与Go语言的结合可以构建高效、可靠的后端系统。通过合理使用各种数据类型、缓存策略和高级特性可以充分发挥Redis的优势提升应用性能和可扩展性。希望本文的实战经验能帮助你更好地使用Go语言与Redis进行开发。
http://www.gsyq.cn/news/1374933.html

相关文章:

  • MySQL安装与基础操作指南
  • 告别微信传文件!麒麟KYLINOS自带‘传书’工具,局域网互传文件保姆级教程
  • 2026年质量好的农村污水处理设备/工厂污水处理设备/潍坊工业污水处理设备/一体化污水处理设备厂家哪家好 - 行业平台推荐
  • 伽马暴宇宙学分析中流量阈值选择的敏感性研究
  • 基于变分自编码器的类星体光谱无监督分析:QUEST工具原理与实践
  • 2026年比较好的生活污水处理设备/污水处理设备/养殖污水处理设备/工厂污水处理设备公司哪家好 - 品牌宣传支持者
  • ARM SME指令集:矩阵运算优化与AI加速实践
  • 不止于仿真:在Ubuntu 20.04上把Gazebo Garden装进ROS2,我的机器人开发环境才算完整
  • 图自编码器在金融风控中的拓扑模式检测实践
  • 家庭账目不再是一笔糊涂账
  • ARM SME指令集与浮点运算优化实践
  • 机器学习监控与可观测性:从黑盒到白盒的实践指南
  • Spine Unity Runtime免费集成指南:合规运行时加载与URP适配
  • Windows屏幕录制全栈实现:Graphics Capture+FFmpeg零拷贝编码
  • 互联网大厂Java面试实录:严肃面试官 vs 求职程序员的三轮技术问答
  • ChatGPT绘画提示词生成效率革命(92%设计师不知道的5层语义嵌套法)
  • 物理信息神经网络QNM-Net:用准正规模理论实现电磁散射的高效可解释建模
  • 【C++ 知识点回顾】C++ 工程中真正常见的内存泄漏:不是忘记 delete,而是生命周期失控
  • 如何让政策数据在三个端保持同步?政策快报的实践方案
  • List<T>泛型列表
  • 二、大模型节点配置以及结束节点配置
  • 诗心撷珍 | 李白诗行里,那些被忽略的星辰与旷野
  • 别急着买云服务器!手把手教你用闲置Win10电脑搭建个人SSH服务器(保姆级教程)
  • 手把手教你解锁影驰B360M主板隐藏的fTPM 2.0,绕过限制升级Win11(附BIOS修改避坑指南)
  • 量子计算硬件指纹识别:从噪声特性到设备认证
  • CVPR 2019 RKD论文复现踩坑记:从理论公式到可运行的PyTorch代码全解析
  • 信号与系统避坑指南:为什么两个三角波卷积不是尖顶脉冲?用Python和傅里叶变换给你讲透
  • 2026年知名的扫描电镜产品/台式扫描电镜/扫描电镜/SEM扫描电镜口碑好的厂家推荐 - 行业平台推荐
  • 【小白吃透AI】大语言模型LLM超详细原理全集|通俗图解+训练流程+推理机制+优缺点+面试大全
  • 助睿实验作业3-学生用户画像考勤画像可视化分析