Redis入门:go-redis基本操作与连接池
Redis入门:go-redis基本操作与连接池摘要: 本篇讲解Go操作Redis的核心库go-redis v9包括客户端连接配置、String/Hash/List/Set/ZSet五种数据类型的基本操作、连接池参数调优(PoolSize、MinIdleConns、PoolTimeout)分享连接池耗尽导致请求超时的踩坑经历对比go-redis与redigo的优劣。开篇故事上周五晚上我们一个营销活动的接口开始报超时。日志里全是redis: connection pool timeoutQPS一上来Redis就扛不住。我翻了半天代码连接池配置是默认值PoolSize才是10*runtime.GOMAXPROCS高并发场景下根本不够用。我直接把PoolSize调到200MinIdleConns设成50重新部署后超时消失。go-redis用起来简单但连接池参数不调好生产环境迟早出事。这篇我从安装配置讲起把go-redis v9的基本操作和连接池调优一次性讲透。一、go-redis安装与连接配置go-redis是Redis的Go客户端v9版本做了大量重构API和v8有区别。packagemainimport(contextfmttimegithub.com/redis/go-redis/v9)// 创建Redis客户端配置连接池参数funcnewRedisClient()*redis.Client{rdb:redis.NewClient(redis.Options{Addr:localhost:6379,// Redis地址Password:,// 密码没设就留空DB:0,// 使用的数据库编号PoolSize:200,// 连接池大小默认10*GOMAXPROCSMinIdleConns:20,// 最小空闲连接保持预热PoolTimeout:5*time.Second,// 从池中获取连接的超时IdleTimeout:5*time.Minute,// 空闲连接超时DialTimeout:5*time.Second,// 建立连接超时ReadTimeout:3*time.Second,// 读操作超时MaxRetries:3,// 命令失败重试次数})returnrdb}funcmain(){rdb:newRedisClient()deferrdb.Close()// Ping测试连接ctx:context.Background()pong,err:rdb.Ping(ctx).Result()iferr!nil{fmt.Println(连接失败:,err)return}fmt.Println(连接成功:,pong)// 输出PONG}二、五种数据类型基本操作String与HashString存缓存值和计数器Hash适合存对象。// String类型操作funcstringOps(ctx context.Context,rdb*redis.Client){// 设置键值带过期时间rdb.Set(ctx,name,张三,10*time.Minute)// 获取值区分键不存在和查询出错val,err:rdb.Get(ctx,name).Result()iferrredis.Nil{fmt.Println(键不存在)}elseiferr!nil{fmt.Println(查询出错:,err)}else{fmt.Println(name ,val)}// 自增操作适合做计数器rdb.Set(ctx,counter,0,0)rdb.Incr(ctx,counter)// 1rdb.IncrBy(ctx,counter,5)// 5rdb.Decr(ctx,counter)// -1// SetNX:不存在才设置常用于分布式锁ok,_:rdb.SetNX(ctx,lock:order:1,holder,10*time.Second).Result()fmt.Println(获取锁:,ok)}// Hash类型操作funchashOps(ctx context.Context,rdb*redis.Client){// 一个key下存多个字段rdb.HSet(ctx,user:1,name,李四,age,28,email,lisiexample.com)// 获取单个字段name,_:rdb.HGet(ctx,user:1,name).Result()fmt.Println(name ,name)// 获取所有字段fields,_:rdb.HGetAll(ctx,user:1).Result()fork,v:rangefields{fmt.Printf(%s %s\n,k,v)}rdb.HIncrBy(ctx,user:1,age,1)// 字段自增rdb.HDel(ctx,user:1,email)// 删除字段}List、Set与ZSetList做队列Set做标签去重ZSet做排行榜。// List类型:双向链表适合消息队列funclistOps(ctx context.Context,rdb*redis.Client){rdb.LPush(ctx,messages,msg1,msg2,msg3)// 左推入msg,_:rdb.RPop(ctx,messages).Result()// 右弹出先进先出fmt.Println(弹出:,msg)// 获取范围元素0到-1表示全部vals,_:rdb.LRange(ctx,messages,0,-1).Result()fmt.Println(剩余消息:,vals)// 阻塞式弹出适合消费队列result,_:rdb.BRPop(ctx,5*time.Second,messages).Result()iflen(result)0{fmt.Println(阻塞弹出:,result[1])}}// Set类型:无序集合自动去重funcsetOps(ctx context.Context,rdb*redis.Client){rdb.SAdd(ctx,tags:1,go,redis,backend)rdb.SAdd(ctx,tags:2,go,database,backend)// 交集:共同标签inter,_:rdb.SInter(ctx,tags:1,tags:2).Result()fmt.Println(共同标签:,inter)// [go backend]// 差集:tags:1有但tags:2没有的diff,_:rdb.SDiff(ctx,tags:1,tags:2).Result()fmt.Println(差集:,diff)// [redis]}// ZSet类型:有序集合带分数适合排行榜funczsetOps(ctx context.Context,rdb*redis.Client){rdb.ZAdd(ctx,rank:score,redis.Z{Score:100,Member:p1},redis.Z{Score:85,Member:p2},redis.Z{Score:92,Member:p3})// 按分数从高到低取前10名rank,_:rdb.ZRevRangeWithScores(ctx,rank:score,0,9).Result()fori,z:rangerank{fmt.Printf(第%d名: %s 分数:%.0f\n,i1,z.Member,z.Score)}// 增加分数rdb.ZIncrBy(ctx,rank:score,10,p2)}三、连接池参数调优连接池是go-redis性能的关键参数配错要么连接不够用要么资源浪费。packagemainimport(contextfmtsynctimegithub.com/redis/go-redis/v9)funcmain(){rdb:redis.NewClient(redis.Options{Addr:localhost:6379,PoolSize:200,// 连接池上限默认10*GOMAXPROCSMinIdleConns:20,// 预热连接数建议PoolSize的10%-25%PoolTimeout:4*time.Second,// 池满时等待时间默认ReadTimeout1sIdleTimeout:5*time.Minute,// 空闲连接存活时间MaxRetries:3,// 网络错误自动重试次数})deferrdb.Close()ctx:context.Background()// 并发测试连接池varwg sync.WaitGroupfori:0;i100;i{wg.Add(1)gofunc(nint){deferwg.Done()rdb.Set(ctx,fmt.Sprintf(key:%d,n),value,10*time.Second)}(i)}wg.Wait()// 查看连接池状态stats:rdb.PoolStats()fmt.Printf(总连接: %d, 空闲: %d, 等待次数: %d\n,stats.TotalConns,stats.IdleConns,stats.Waits)}调优看三个指标。stats.Waits多说明PoolSize太小。stats.IdleConns常年接近PoolSize说明配多了。stats.WaitDuration长说明要么加PoolSize要么查Redis本身是否慢。四、独家踩坑:连接池耗尽导致超时上线后发现高峰期接口偶尔超时报错redis: connection pool exhausted。第一反应是Redis扛不住了去看监控CPU才20%。然后看应用日志发现超时集中在一个批量查询接口循环里每次调一次Redis中间还套了time.Sleep(2 * time.Second)。// 问题代码:循环单条查询连接池被打满funcbadExample(ctx context.Context,rdb*redis.Client,ids[]int64){for_,id:rangeids{// 每次Get从池中借一个连接val,_:rdb.Get(ctx,fmt.Sprintf(user:%d,id)).Result()time.Sleep(2*time.Second)// 耗时操作期间连接被占用_val}}真正的问题在PoolSize默认值太小。线上GOMAXPROCS是8默认PoolSize才80高并发下很快借光。修复分两步PoolSize调到200MinIdleConns设50。把循环查询改成Pipeline批量查。// 修复后:用Pipeline批量查询只占一个连接funcfixedExample(ctx context.Context,rdb*redis.Client,ids[]int64)map[int64]string{pipe:rdb.Pipeline()cmds:make(map[int64]*redis.StringCmd,len(ids))for_,id:rangeids{cmds[id]pipe.Get(ctx,fmt.Sprintf(user:%d,id))// 注册命令}pipe.Exec(ctx)// 一次性执行result:make(map[int64]string,len(ids))forid,cmd:rangecmds{ifval,err:cmd.Result();errnil{result[id]val}}returnresult}调完后连接池等待次数从每天几万次降到几十次。经验就是连接池参数一定要根据实际QPS调别用默认值。五、对比分析特性go-redis v9redigoAPI风格链式调用类型安全手动写命令字符串连接池内置参数丰富需手动配置Pool结构集群支持原生Cluster和Sentinel需第三方或自己实现Pipeline内置Pipeline和TxPipeline需手动管理conn.Send自动重试内置MaxRetries需自己实现Context原生支持后期版本才加社区维护活跃官方推荐维护趋缓新项目建议直接选go-redis v9API更现代类型安全避免手写命令出错集群和哨兵开箱即用。redigo轻量但连接管理和错误处理要写更多代码。总结与预告go-redis v9上手简单五种数据类型的API设计清晰。连接池是生产环境关键PoolSize和MinIdleConns一定要根据QPS调优。Pipeline能批量操作就别循环单条查省连接省网络。下一篇讲Redis进阶深入Pipeline原理、事务的WATCH机制和发布订阅模式的实现。

相关新闻

改进哈里斯鹰优化算法:混沌映射与非线性逃逸能量策略

改进哈里斯鹰优化算法:混沌映射与非线性逃逸能量策略

1. 项目背景与核心价值在优化算法领域,哈里斯鹰优化(Harris Hawks Optimization, HHO)作为一种新兴的元启发式算法,近年来在工程优化、机器学习参数调优等领域展现出独特优势。但标准HHO算法存在两个典型痛点:初始种群多样性不足导致早熟收敛…

2026/10/18 15:01:28 阅读更多 →
仓储术语中英对照全解析:从SKU到WMS,提升物流效率必备指南

仓储术语中英对照全解析:从SKU到WMS,提升物流效率必备指南

1. 项目概述:为什么我们需要一份仓储词汇表?在物流与供应链行业摸爬滚打了十几年,我见过太多因为术语理解偏差导致的沟通事故。一次,我们团队与海外客户开电话会议,对方反复提到“Cross-docking”,我方同事…

2026/10/17 21:12:09 阅读更多 →
Java基础语法实战指南:从核心概念到高频坑点解析

Java基础语法实战指南:从核心概念到高频坑点解析

1. 项目概述:为什么“基础语法”是Java世界的基石聊到Java,很多人第一反应是Spring全家桶、微服务、高并发这些听起来很“高大上”的词。但作为一个写了十几年Java的老码农,我见过太多人,包括一些工作了几年的朋友,在面…

2026/10/18 11:37:35 阅读更多 →

最新新闻

梯度消失全解析:从数学原理到ReLU、BN与残差连接的实战解决路径

梯度消失全解析:从数学原理到ReLU、BN与残差连接的实战解决路径

1. 从一个训练到一半就“躺平”的模型说起如果你亲手训练过一个稍微有点深度的神经网络,大概率见过这种让人抓狂的场景:前几个epoch损失还降得好好的,突然就卡在一个不上不下的数值,准确率死活上不去,再往后训练&#…

2026/10/18 15:01:54 阅读更多 →
LAMMPS (23 Jun 2022) + oneAPI 安装避坑:从环境变量到编译验证的完整清单

LAMMPS (23 Jun 2022) + oneAPI 安装避坑:从环境变量到编译验证的完整清单

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 15:01:54 阅读更多 →
MATLAB三维热力图绘制全指南:从数据组织到交互验证

MATLAB三维热力图绘制全指南:从数据组织到交互验证

简介:这份资源聚焦MATLAB三维数据可视化,面向需要绘制三维热力图的学生、科研人员与工程技术人员,帮助解决三维曲面数据难以直观呈现的问题。资源包共3个文件,包含1个m脚本、1个mat数据文件和1个png效果图,压缩包约219…

2026/10/18 15:01:54 阅读更多 →
2026 用 AI 工具分析空口包 WiFi 包:TaoToken 统一 Key 接入 tshark/Wireshark 抓包总结

2026 用 AI 工具分析空口包 WiFi 包:TaoToken 统一 Key 接入 tshark/Wireshark 抓包总结

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 15:01:54 阅读更多 →
Java SHA算法实战:选型、编码、文件校验与安全边界

Java SHA算法实战:选型、编码、文件校验与安全边界

说实话,看到“SHA加密算法”这个标题,我第一反应是:这又是一个被写烂的入门Demo。但实际在项目里接手过几个跟数据校验、安全存储相关的模块之后,我觉得“SHA”这一块值得聊的东西其实非常多——很多人止步于会用MessageDigest.ge…

2026/10/18 15:01:54 阅读更多 →
JsLeakWatcher 报出一批对象,真的是内存泄漏吗:页面缓存、监听器和可达路径怎么分

JsLeakWatcher 报出一批对象,真的是内存泄漏吗:页面缓存、监听器和可达路径怎么分

JsLeakWatcher 报出一批对象,真的是内存泄漏吗:页面缓存、监听器和可达路径怎么分 页面退出后 JsLeakWatcher 报出几十个对象,团队立刻把所有缓存清掉,结果二次进入变慢,告警却仍然存在。工具发现“对象仍可达”&…

2026/10/18 15:00:54 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →