redis避免耗尽连接池相关泄露的问题
¶Redis避免耗尽连接池以及相关泄露的问题
¶问题背景
在编写《蒙东电网》接口服务时,需要频繁调用redis中的内容,造成了大量的redis的连接,但是连接没有及时关闭,最后导致蒙东电网的接口服务在单一设备的情况下运行大约一周左右便会出现无法继续上报数据的问题,经过排查发现问题在于redis的连接池的配置问题,导致连接数量过多后没能及时关闭连接,最后造成新的获取缓存数据的服务无法建立连接,从而导致无法上报相关数据。
¶解决方式
主要分为配置文件的优化,程序代码的连接关闭,重试机制以及超时管理。
¶一、配置文件修改(config.yaml)
¶1. Redis 连接池配置优化
1 | # 连接池配置(优化:降低连接池大小,避免与sagooiot-professional竞争资源) |
修改说明:
- poolSize: 500 → 50(降低 90%)
- 限制最大连接数,避免耗尽 Redis 连接
- 两个服务共享 Redis,总和不超过服务器限制
- minIdle: 50 → 10(降低 80%)
- 减少常驻空闲连接,降低内存占用
- 仍保留最小空闲连接,保证响应速度
¶2. MySQL 连接池配置优化
1 | maxIdle: 20 #连接池最大闲置的连接数(优化:从50降低到20,避免资源竞争) |
修改说明:
- maxOpen: 1000 → 100(降低 90%)
- maxIdle: 50 → 20(降低 60%)
- maxLifetime: 120 → 3600(增加 30 倍)
- 减少频繁重建连接,降低连接池压力
¶二、代码层面的防泄漏机制
¶1. 超时控制机制
在 realtime_pipeline.go 中添加了超时控制:
1 | func cacheAppendToday(ctx context.Context, domain Domain, device string, v any) error { |
作用:
- 每个 Redis 操作最多 10 秒超时
- 超时后自动取消,连接归还连接池
- 防止因网络问题导致连接长时间占用
¶2. 重试机制
1 | // 添加重试机制,最多重试3次 |
作用:
- 失败时最多重试 3 次
- 每次重试前检查超时,避免无效重试
- 重试间隔递增,避免瞬时压力
- 失败后连接正常归还,不会泄漏
¶三、框架层面的连接管理(GoFrame)
¶1. 连接自动归还机制
代码中使用 g.Redis() 获取连接:
1 | redis := g.Redis() |
GoFrame 的连接管理机制:
- 自动连接池:
g.Redis()返回的是连接池客户端,不是单个连接 - 自动归还:操作完成后,连接自动归还到连接池
- 连接复用:多个操作共享连接池中的连接
¶2. 连接池生命周期管理
GoFrame 框架会自动:
- 启动时创建连接池(懒加载)
- 根据
poolSize和minIdle管理连接数量 - 空闲连接自动清理(超过
idleTimeout后关闭) - 连接异常时自动重建
¶四、防止连接泄漏的机制总结
¶1. 配置层面
| 配置项 | 修改前 | 修改后 | 防泄漏作用 |
|---|---|---|---|
poolSize |
500 | 50 | 限制最大连接数,防止无限制增长 |
minIdle |
50 | 10 | 减少常驻连接,降低泄漏影响 |
maxOpen |
1000 | 100 | 限制数据库连接数 |
maxLifetime |
120秒 | 3600秒 | 减少频繁重建,降低连接池压力 |
¶2. 代码层面
| 机制 | 实现位置 | 防泄漏作用 |
|---|---|---|
| 超时控制 | context.WithTimeout(ctx, 10*time.Second) |
防止连接长时间占用 |
| 上下文取消 | opCtx.Err() != nil 检查 |
超时后立即释放资源 |
| 错误处理 | 重试机制中的错误检查 | 确保异常时连接正常归还 |
| 框架管理 | g.Redis() 自动管理 |
GoFrame 自动处理连接生命周期 |
¶3. 连接泄漏防护流程
1 | 1. 获取连接 |
¶五、为什么这样配置能防止泄漏?
¶1. 限制连接数上限
poolSize: 50限制最大连接数- 即使有泄漏,最多泄漏 50 个连接
- 不会无限增长导致服务器崩溃
¶2. 超时机制强制释放
- 10 秒超时确保连接不会永久占用
- 即使代码有 bug,超时后也会释放
¶3. 框架自动管理
- GoFrame 自动处理连接生命周期
- 不需要手动
Close(),减少人为错误
¶4. 减少空闲连接
minIdle: 10减少常驻连接- 即使有泄漏,影响也较小
¶六、监控建议
可以添加以下监控来验证配置是否生效:
1 | # 监控 Redis 连接数 |
如果连接数稳定在配置范围内,说明配置生效,连接没有泄漏。
¶总结
主要修改:
- 配置文件:降低
poolSize和minIdle - 代码层面:添加超时控制和重试机制
- 框架层面:依赖 GoFrame 的自动连接管理
这些改动共同确保:
- 连接数不会超过限制
- 超时后自动释放
- 异常情况下连接正常归还
- 两个服务共享资源时不会互相影响
如需进一步优化,可添加连接池监控和告警机制。