调试 Go Redis
连接池大小
为了提高性能,go-redis 会自动管理一个网络连接(套接字)池。默认情况下,连接池大小为 runtime.GOMAXPROCS
报告的每个可用 CPU 10 个连接。在大多数情况下,这已经足够了,调整它很少有帮助。
rdb := redis.NewClient(&redis.Options{
PoolSize: 1000,
})
redis: 连接池超时
当连接池中没有空闲连接可用,并且持续时间超过 Options.PoolTimeout
时,您可能会遇到此错误。如果您正在使用 redis.PubSub
或 redis.Conn
,请确保在不再需要时通过调用 Close
方法正确释放 PuSub
/Conn
资源。
当 Redis 处理命令的速度太慢,并且连接池中的所有连接都被阻塞超过 PoolTimeout
时间时,您也可能会遇到此错误。
超时
即使您正在使用 context.Context
时限,也请不要禁用 DialTimeout
、ReadTimeout
和 WriteTimeout
,因为 go-redis 在不使用上下文的情况下执行一些后台检查,而是依赖于连接超时。
如果您正在使用 AWS 或 Google Cloud 等云提供商,请不要使用小于 1 秒的超时。这种小的超时在大多数情况下都能正常工作,但在云比平时更慢的情况下会惨败。有关详细信息,请参阅 Go 上下文超时可能是有害的。
如果您遇到了此错误,还可以参阅 上下文时限已超过。
大量打开的连接
在高负载下,某些命令会超时,go-redis 会关闭这些连接,因为它们仍然可以稍后接收一些数据,并且不能重复使用。关闭的连接首先进入 TIME_WAIT
状态,并保持该状态,直到最大段生命周期结束的两倍时间,通常为 1 分钟。
cat /proc/sys/net/ipv4/tcp_fin_timeout
60
为了解决这个问题,您可以增加读写超时或升级服务器以处理更多流量。您还可以增加最大打开的连接数,但这不会使您的服务器或网络更快。
有关一些建议,还可以参阅 应对 TCP TIME-WAIT。
管道
由于 go-redis 大部分时间都花在从连接中写入/读取/等待数据上,因此您可以通过使用 管道 同时发送多个命令来提高性能。
缓存
如果您的应用程序逻辑不允许使用 管道,请考虑为最常用的操作添加一个本地进程内 缓存,例如使用 TinyLFU。
硬件
确保您的服务器具有良好的网络延迟和具有大型缓存的快速 CPU。如果您有多个 CPU 内核,请考虑在一台服务器上运行多个 Redis 实例。
有关更多详细信息,请参阅 影响 Redis 性能的因素。
分片
您还可以将数据拆分到多个 Redis 实例中,以便每个实例包含键的子集。这样,负载就会分布在多个服务器上,并且您可以通过添加更多服务器来提高性能。
如果您正在使用 Redis 进行缓存,并且可以承受丢失一些数据,则 Redis 环 是一个不错的选择。否则,您可以尝试 Redis 集群。
监控
监控 Redis 数据库的性能对于维护系统整体的健康状况、效率和可靠性至关重要。适当的性能监控有助于识别和解决潜在的问题,防止它们导致服务中断或性能下降。
Uptrace 是一个 OpenTelemetry 后端,支持分布式跟踪、指标和日志。您可以使用它来监控应用程序并排查问题。
Uptrace 提供直观的查询构建器、丰富的仪表板、带有通知的警报规则以及大多数语言和框架的集成。
Uptrace 可以在一台服务器上处理数十亿个跨度和指标,并允许您以 10 倍的低成本监控您的应用程序。
您只需几分钟即可尝试 Uptrace,方法是访问 云演示(不需要登录)或使用 Docker 在本地运行它。源代码在 GitHub 上可用。