排查 Azure Cache for Redis 延迟和超时问题

未及时接收响应的客户端操作可能会导致高延迟或超时异常。 操作可能会在不同阶段超时。 了解超时的来源,有助于判定原因以及确定缓解措施。

本部分讨论如何排查连接到 Azure Cache for Redis 时出现的延迟以及超时问题。

注意

本指南中的多个故障排除步骤包括了运行 Redis 命令和监视各种性能指标的说明。 如需更多信息和说明,请参阅 其他信息 部分的文章。

客户端故障排除

下面是客户端故障排除。

流量突增和线程池配置

流量激增时,如果 ThreadPool 设置不佳,则可能导致对 Redis 服务器已发送但尚未在客户端上使用的数据的处理出现延迟。 检查指标“错误”(类型:UnresponsiveClients)验证客户端主机能应对突然出现的流量高峰。

使用示例 ThreadPoolLogger 监视 ThreadPool 统计信息在不同时间的变化。 可以使用 StackExchange.Redis 发出的 TimeoutException 消息做进一步的调查:

    System.TimeoutException: Timeout performing EVAL, inst: 8, mgr: Inactive, queue: 0, qu: 0, qs: 0, qc: 0, wr: 0, wq: 0, in: 64221, ar: 0,
    IOCP: (Busy=6,Free=999,Min=2,Max=1000), WORKER: (Busy=7,Free=8184,Min=2,Max=8191)

在上面的异常中,有几个需要注意的问题:

  • 请注意,在 IOCP 部分和 WORKER 部分,Busy 值大于 Min 值。 这种差异意味着 ThreadPool 设置需要调整。
  • 也可参看 in: 64221。 此值表示客户端的内核套接字层收到了 64,221 字节,但应用程序尚未读取这些字节。 这种差异通常意味着,应用程序(例如 StackExchange.Redis)从网络读取数据的速度没有服务器向你发送数据的速度快。

可以配置 ThreadPool 设置,确保线程池在流量激增的情况下快速扩展。

大键值

有关使用多个键和较小值的信息,请参阅考虑使用更多键和较小的值

可以使用 redis-cli --bigkeys 命令检查缓存中的大键。 有关详细信息,请参阅 redis-cli,Redis 命令行接口 --Redis

  • 增大 VM 的大小以获得更高的带宽能力
    • 提高客户端或服务器 VM 上的带宽可以缩短较大响应的数据传输时间。
    • 将两台计算机上的网络用量与当前 VM 大小的限制进行比较。 只提高服务器上的带宽,或者只提高客户端上的带宽,都不足以解决问题。
  • 增加应用程序使用的连接对象数。
    • 使用轮询方法通过不同的连接对象发出请求

客户端主机上的 CPU 使用率高

客户端 CPU 使用率偏高表示系统无法跟上分配给它的工作的进度。 即使缓存发送响应的速度很快,客户端也可能无法及时处理该响应。 建议将客户端 CPU 保持在 80% 以下。 检查指标“错误”(类型:UnresponsiveClients),以确定客户端主机能否及时处理来自 Redis 服务器的响应。

使用 Azure 门户中提供的指标或者通过计算机上的性能计数器监视客户端的系统范围的 CPU 使用率。 请注意不要监视进程 CPU,因为即使单个进程的 CPU 使用率较低,但系统范围的 CPU 使用率也可能很高。 注意与超时相对应的 CPU 使用率峰值。 CPU 使用率较高可能还会导致 TimeoutException 错误消息中出现较大的 in: XXX 值,如[流量突增]部分所述。

注意

StackExchange.Redis 1.1.603 及更高版本在 TimeoutException 错误消息中包括了 local-cpu 指标。 确保使用最新版本的 StackExchange.Redis NuGet 包。 代码中会定期修复 Bug,使其更可靠地解决超时问题。 请务必采用最新版本。

缓解客户端 CPU 使用率较高的问题:

  • 调查出现 CPU 峰值的原因。
  • 将客户端升级到可提供更多 CPU 容量的更大 VM 大小。

客户端主机的网络带宽限制

不同的客户端计算机体系结构对于可提供的网络带宽存在不同的限制。 如果客户端超出可用带宽,则客户端的数据处理速度将赶不上服务器的数据发送速度。 这种情况下会导致超时。

使用 示例 BandwidthLogger监视带宽使用率在不同时间的变化。 在对权限有限制的某些环境(例如 Azure 网站)中,此代码可能无法成功运行。

若要缓解此问题,请减少网络带宽消耗,或者将客户端 VM 大小提高到可以提供更大网络容量的大小。 有关详细信息,请参阅请求或响应大小过大

基于 Linux 的客户端应用程序的 TCP 设置

由于 Linux 中采用乐观 TCP 设置,Linux 上托管的客户端应用程序可能会遇到连接问题。 有关详细信息,请参阅 Linux 托管客户端应用程序的 TCP 设置

RedisSessionStateProvider 重试超时

如果使用 RedisSessionStateProvider,请确保正确设置重试超时。 retryTimeoutInMilliseconds 值应大于 operationTimeoutInMilliseconds 值。 如果不是这样,则不会重试。 在下面的示例中,retryTimeoutInMilliseconds 设置为 3000。 有关详细信息,请参阅 Azure Redis 缓存的 ASP.NET 会话状态提供程序How to use the configuration parameters of Session State Provider and Output Cache Provider(如何使用会话状态提供程序和输出缓存提供程序的配置参数)。

<add 
    name="AFRedisCacheSessionStateProvider"
    type="Microsoft.Web.Redis.RedisSessionStateProvider"
    host="enbwcache.redis.cache.chinacloudapi.cn"
    port="6380"
    accessKey="..."
    ssl="true"
    databaseId="0"
    applicationName="AFRedisCacheSessionState"
    connectionTimeoutInMilliseconds = "5000"
    operationTimeoutInMilliseconds = "1000"
    retryTimeoutInMilliseconds="3000"
>

服务器端故障排除

下面是服务器端故障排除。

服务器维护

计划内或计划外维护可能会导致客户端连接中断。 异常的数目和类型取决于当缓存关闭其连接时,请求在代码路径中所处的位置。 例如,在发生故障转移时发送了请求但未收到响应的操作可能会收到超时异常。 对关闭的连接对象发出的新请求将收到连接异常,直到重新连接成功为止。

有关详细信息,请查看以下其他部分:

若要检查 Azure Cache for Redis 在超时期间是否发生了故障转移,请检查指标“错误”。 在 Azure 门户的“资源”菜单上选择“指标”。 然后创建一个新的图表来测量 Errors 指标,按 ErrorType 拆分。 创建此图表后,会看到故障转移计数。

有关故障转移的详细信息,请参阅 Azure Cache for Redis 的故障转移和修补

高服务器负载

高服务器负载意味着 Redis 服务器无法跟上请求,导致超时。 服务器可能会减慢响应速度,且无法跟上请求速率。

监视指标,例如服务器负载。 注意与超时相对应的 Server Load 使用率峰值。 基于关于服务器负载的指标创建警报,以提前收到有关潜在影响的通知。

可以通过做出几项更改来缓解较高的服务器负载:

  • 调查导致高服务器负载的原因,例如本文提到的由于内存压力大而导致的长时间运行的命令
  • 横向扩展到更多的分片,以跨多个 Redis 进程分配负载,或者纵向扩展到具有更多 CPU 内核的更大缓存大小。 有关详细信息,请参阅 Azure Cache for Redis 规划常见问题解答
  • 如果 C1 缓存上的生产工作负载受到某些内部 Defender 病毒扫描运行导致的额外延迟的不利影响,则可以通过缩放到具有多个 CPU 核心的更高层级产品/服务(例如 C2)来降低影响。

服务器负载中的峰值

在 C0C1 缓存上,当内部 Defender 扫描在 VM 上运行时,可能会看到服务器负载在一天中数次出现短暂峰值,但这不是由于请求数增加而导致的。 在这些层级上进行内部 Defender 扫描时,你会看到更高的请求延迟。 C0 和 C1 层上的缓存只有一个核心用来进行多任务处理,并将服务于内部 Defender 扫描和 Redis 请求的工作分开。

内存使用率较高

本部分已移到其他位置。 有关详细信息,请参阅高内存使用率

长时间运行的命令

某些 Redis 命令的执行开销比其他命令高。 Redis 命令文档介绍了每个命令的时间复杂性。 Redis 命令处理是单线程的。 需要很长时间运行的任何命令都会阻止其后的所有其他命令。

查看正在向 Redis 服务器发出的命令,以了解它们对性能的影响。 例如,我们经常使用 KEYS 命令,但事先并不知道它是一个 O(N) 操作。 可以使用 SCAN 来避免 KEYS,以降低 CPU 峰值。

使用 SLOWLOG GET 命令可以测量正在对服务器执行的命令的开销。

客户可以使用控制台运行这些 Redis 命令来调查长时间运行以及花费较高的命令。

  • SLOWLOG 用于读取和重置 Redis 慢速查询日志。 它可用于调查在客户端长时间运行的命令。 Redis 慢速日志是记录超过指定执行时间的查询的系统。 执行时间不包括 I/O 操作,例如与客户端交谈、发送答复等,而只是实际执行命令所需的时间。 客户可以使用 SLOWLOG 命令测量/记录针对其 Redis 服务器执行的昂贵命令。
  • MONITOR 是一个调试命令,该命令流式返回 Redis 服务器处理的每个命令。 该命令能帮助你了解数据库中的情况。 此命令要求很高,可能会对性能产生负面影响。 这可能会降低性能。
  • INFO - 命令返回有关服务器的信息和统计数据,其格式便于计算机解析和用户阅读。 在这种情况下,可使用 CPU 部分来调查 CPU 使用情况。 服务器负载为 100(最大值),表示 Redis 服务器一直忙,在处理请求时永远不会空闲。

输出示例:

# CPU
used_cpu_sys:530.70
used_cpu_user:445.09
used_cpu_avg_ms_per_sec:0
server_load:0.01
event_wait:1
event_no_wait:1
event_wait_count:10
event_no_wait_count:1
  • 客户端列表 - 以用户可读的格式返回有关客户端连接服务器的信息和统计数据。

网络带宽限制

不同的缓存大小具有不同的网络带宽容量。 如果服务器超出可用带宽,则数据将无法快速发送到客户端。 客户端请求可能会超时,因为服务器无法以足够快的速度将数据推送到客户端。

可以使用“缓存读取”和“缓存写入”指标来查看使用的服务器端带宽量。 可以在门户中查看这些指标。 基于指标(例如缓存读取或缓存写入)创建警报,以提前收到有关潜在影响的通知。

缓解网络带宽用量即将达到最大容量的情况:

StackExchange.Redis 超时异常

若要更详细地了解在使用 Stackexchange.redis 时如何解决超时问题,请参阅调查 StackExchange.Redis 中的超时异常