虽然 Memorystore for Redis 提供实时服务器端指标来监控吞吐量、CPU 利用率和内存用量,但仅凭这些数据可能无法解释为什么您的客户端应用在复杂的分布式系统中会遇到高延迟。
客户端指标通过提供对完整请求-响应周期的透明度来解决此问题。它们会衡量从应用启动命令到应用处理响应的时间。通过捕获这些数据点,您可以准确确定延迟是源自应用逻辑、网络路径还是 Redis 服务器。
准备工作
确保您的客户端应用使用服务帐号,并且已为其分配以下 Identity and Access Management (IAM) 角色:
roles/cloudtrace.agent(Cloud Trace Agent)roles/monitoring.metricWriter(Monitoring Metric Writer)
如需详细了解如何授予角色,请参阅使用 Google Cloud 控制台授予 IAM 角色快速入门。
启用 Cloud Monitoring API
如需将客户端指标导出到 Monitoring, 您的应用需要启用 Monitoring API。 通过在 Monitoring 中导出和可视化这些指标,您可以找出瓶颈的根本原因,以确定延迟的来源。
如需启用 Monitoring API,请执行以下操作:
在 Google Cloud 控制台中,前往 API 和服务 页面。
选择您在其中创建 Memorystore for Redis 实例的项目。
点击启用 API 和服务 。
搜索
monitoring。在搜索结果中,点击 Cloud Monitoring API 。
如果显示 API 已启用 ,则表示此 API 已经启用。否则,请点击启用 。
启用 Cloud Trace API
如需在 Trace 中查看分布式跟踪记录,您必须 启用 Trace API。然后,您可以使用 Trace Explorer 查看这些跟踪记录、诊断瓶颈并隔离应用中的延迟来源。
如需启用 Trace API,请执行以下操作:
在 Google Cloud 控制台中,前往 API 和服务 页面。
选择您在其中创建 Memorystore for Redis 实例的项目。
点击启用 API 和服务 。
搜索
trace。在搜索结果中,点击 Cloud Trace API 。
如果显示 API 已启用 ,则表示此 API 已经启用。否则,请点击启用 。
启用客户端指标
如需启用客户端指标,请将 OpenTelemetry SDK、Cloud Monitoring 导出器和 Cloud Trace 导出器添加到应用的代码中。OpenTelemetry 插桩直接在应用的 Redis 客户端库内运行,用于捕获指标。这样,您的应用就可以记录延迟数据点,并将其导出到 Monitoring 和 Trace 以进行可视化。
如需启用客户端指标,您可以使用 Go、 Java、Node.js、 或 Python。如需了解如何为每种语言启用指标,请参阅以下标签页。
Go
如需安装所需的 OpenTelemetry 和 Google Cloud 导出器 依赖项,请在终端中运行以下命令:
go get github.com/gomodule/redigo/redis@latest go get go.opentelemetry.io/otel go get go.opentelemetry.io/otel/sdk/trace go get go.opentelemetry.io/otel/sdk/metric go get github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace go get github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric
如需启用客户端指标,请创建
main.go文件,并向其中添加以下代码:运行应用至少 1 分钟,以便导出器有足够的时间将已发布的指标批量发送到 Monitoring。
Java
如需安装所需的 OpenTelemetry 和 Google Cloud 导出器 依赖项,请将以下代码添加到应用的
pom.xml文件中:如需启用客户端指标,请创建
RedisTelemetryApp.java文件,并向其中添加以下代码:运行应用至少 1 分钟,以便导出器有足够的时间将已发布的指标批量发送到 Monitoring。
Node.js
如需安装所需的 OpenTelemetry 和 Google Cloud 导出器 依赖项,请在终端中运行以下命令:
npm install redis@^4.6.0 @opentelemetry/api@^1.9.0 @opentelemetry/sdk-trace-node@^2.1.0 @opentelemetry/sdk-trace-base@^2.1.0 @opentelemetry/sdk-metrics@^2.1.0 @opentelemetry/instrumentation@^0.205.0 @opentelemetry/instrumentation-redis@^0.67.0 @google-cloud/opentelemetry-cloud-trace-exporter@^3.0.0 @google-cloud/opentelemetry-cloud-monitoring-exporter@^0.21.0 @opentelemetry/resources@^2.1.0
如需启用客户端指标,请创建
server.js文件,并向其中添加以下代码:运行应用至少 1 分钟,以便导出器有足够的时间将已发布的指标批量发送到 Monitoring。
Python
如需安装所需的 OpenTelemetry 和 Google Cloud 导出器 依赖项,请在终端中运行以下命令:
pip install redis==7.0.1 opentelemetry-api==1.39.1 opentelemetry-sdk==1.39.1 opentelemetry-instrumentation-redis==0.60b1 opentelemetry-exporter-gcp-trace==1.11.0 opentelemetry-exporter-gcp-monitoring==1.11.0a0
如需启用客户端指标,请创建
main.py文件,并向其中添加以下代码:运行应用至少 1 分钟,以便导出器有足够的时间将已发布的指标批量发送到 Monitoring。
在 Monitoring 中查看指标
启用客户端指标并运行应用至少 1 分钟,以便导出器有足够的时间将指标批量发送到 Monitoring 后,您可以使用 Monitoring 可视化指标,按操作或实例对指标进行分组,并应用聚合器来监控应用的性能。
如需在 Monitoring 中查看指标,请执行以下操作:
在 Google Cloud 控制台中,前往 Metrics Explorer 页面。
选择您的 Google Cloud 项目。
点击选择指标 。
搜索
workload.googleapis.com/redis。选择客户端指标。根据需要按
operation和instance对数据进行分组,然后选择一个聚合器。如需了解更多选项,请参阅使用 Metrics Explorer 时选择指标。
在 Trace 中查看分布式跟踪记录
应用开始导出数据后,您可以使用 Trace 可视化 Redis 命令的完整请求-响应周期。通过在 Trace 中查看分布式跟踪记录,您可以诊断瓶颈,以便快速隔离应用中延迟的确切来源。
如需在 Trace 中查看分布式跟踪记录,请执行以下操作:
在 Google Cloud 控制台中,前往 Trace Explorer 页面。
在散点图上选择以点表示的最近跟踪记录。
检查瀑布图,通过识别以下瓶颈来隔离延迟来源:
总请求时长:顶层(父级)条形图显示了您必须等待操作完成的总 时间。
网络和服务器延迟 (RTT):子条形图(例如标有
GET或SET的条形图)显示了命令在网络上传输和在 Memorystore for Redis 服务器上运行所花费的时间。客户端连接阻塞:如果 Redis 子 span 开始之前存在较大的空白水平间隙,则表示应用线程卡在等待连接池中的可用 TCP 连接。
应用解析阻塞:如果 Redis 子 span 结束后存在较大的空白水平间隙,则表示应用难以解析 或难以处理返回的载荷。这种情况通常发生在多兆字节 JSON 字符串中。
重试:如果您看到同一父级跟踪记录中按顺序出现同一命令的多个短子 span,则表示您的客户端可能会遇到网络丟包,并且必须触发其指数退避重试循环。
问题排查
本部分列出了您可以使用客户端指标识别的常见性能问题,解释了这些问题的根本原因,并提供了有关问题排查的指南。
| 问题 | 原因 | 问题排查 |
|---|---|---|
您的应用遇到突发延迟峰值,但 Memorystore for Redis 看起来完全正常。
|
瓶颈严格位于您的应用内。您的
线程尝试运行 Redis 命令,但连接池已完全
耗尽。较高的 redis_client_blocking_latency 表示您的代码在将命令发送到网络之前等待可用 TCP 套接字所花费的时间。 |
如需处理更高的并发流量,请在 Redis 客户端配置中增加连接池大小限制(例如,MaxActive for Go, MaxTotal for Java, or max_connections for Node.js and Python)。 |
请求完成,但端点所花费的时间远超预期 。您的网络或服务器的运行状况没有相关问题。
|
Memorystore for Redis 运行命令,网络快速传输载荷(低 RTT)。但是,返回的载荷很大(例如,15 MB 的 JSON 字符串)。您的应用遇到较高的
redis_application_blocking_latency,因为应用
在分配内存并将该
大型字符串反序列化为对象时消耗了过多的资源。 |
优化您的数据模型。请勿在单个键中存储大量 JSON blob。
使用 Redis 哈希 (HSET) 分解数据,并使用
HGET 或 HMGET 仅检索所需的特定字段
。
|
面向用户的应用延迟出现峰值,但 Redis 指标 报告的服务器延迟较低,并且连接池签出正常。
|
由于 redis_client_rtt 仅捕获
成功请求的 RTT,因此它不会反映失败
数据包的超时时长。当您的应用遇到瞬时数据包丢弃或 TCP
重置时,插桩客户端的重试逻辑会增加
redis_retry_count 并触发其指数退避算法循环。这会在尝试之间引入休眠时间(例如,
100ms、200ms 或 400ms)。用户
会遇到较高的总延迟,但根本原因是网络
丟包,这会触发客户端休眠延迟。 |
检查 VPC 流日志中是否存在丢弃的数据包、带宽限制、
或跨区域路由异常。如果您遇到激进的超时,
请确保您的客户端连接超时(socket_timeout或
connect_timeout)大于预期 RTT,以应对瞬时网络抖动。 |
一切停止,遥测流水线的所有层级都报告 高延迟。
|
Redis 是单线程的。当您运行 O(N)
时间复杂度的命令(例如,KEYS *、对大型集执行 SMEMBERS
或对包含数百万个
字段的哈希执行 HGETALL)时,Redis 引擎会暂停以满足该请求。在该命令
运行时,所有其他应用请求都会排队,从而导致系统范围内的延迟
峰值。由于您的自定义 redis_client_rtt 与服务器的延迟 (commands/usec_per_call) 匹配,因此运行该命令的服务器是瓶颈。 |
打开 Trace,查看慢速 span 上的 Redis 命令,以确定哪个查询导致阻塞。将代码中的阻塞命令 替换为非阻塞命令。 如需以增量方式遍历大型数据集而不锁定
服务器线程,请使用 |
您的应用报告所有 Redis 命令的基准延迟始终较高,即使流量较低也是如此。
|
Redis 服务器会立即运行命令,但您的应用和您的
实例部署在不同的区域(例如,
us-central1 和 us-east1)。每个网络数据包
都必须在这些地理数据中心之间通过物理 Google Cloud 基础架构传输。这会导致每次往返都必须承担光速
跨区域延迟惩罚。 |
如需缩短延迟,请将应用部署到与实例相同的区域 和可用区。如需查看应用和 实例的区域,请使用 Google Cloud 控制台。 |