未能及时收到响应的 Azure Cache for Redis 客户端操作可能会导致高延迟或触发超时异常。 本文介绍如何排查可能导致高延迟和超时的常见问题。
某个操作可能会在各个阶段遇到问题或超时。 问题的源有助于确定原因和缓解措施。 本文分为客户端和服务器端问题。
客户端问题
- 客户端连接数量太多
- 客户端主机上的 CPU 使用率高
- 大键值
- Redis 客户端上的内存压力
- 客户端主机的网络带宽限制
- sSessionStateProvider 重试超时
- 基于 Linux 的客户端应用程序的 TCP 设置
- 流量突增和线程池配置
服务器端问题
以下客户端问题可能会影响延迟和性能,并导致超时。
超过缓存最大范围的客户端连接请求可能会失败。 处理重复的重新连接尝试时,客户端连接数过多还可能导致服务器负载过高。
客户端连接数过多可能表示客户端代码中存在连接泄漏。 连接可能没有被重用或正确关闭。 查看用于连接的客户端代码。
如果高连接都是合法且必需的客户端连接,则可能需要将缓存升级到具有更高连接限制的大小。 检查 连接客户端的最大聚合指标 是否接近或高于缓存大小允许的最大连接数。 有关每个客户端连接的大小调整的详细信息,请参阅 Azure Cache for Redis 性能。
高客户端 CPU 使用率表示系统无法跟上分配给它的工作。 即使缓存快速发送响应,客户端也可能无法快速处理响应。 最好将客户端 CPU 保持在小于 80%。
缓解客户端 CPU 使用率较高的问题:
- 调查 CPU 峰值的原因。
- 将客户端升级到具有更多 CPU 容量的大型虚拟机(VM)大小。
使用 Azure 门户中提供的指标或通过 VM 上的性能计数器监视客户端的系统范围的 CPU 使用率。 检查指标 错误(类型:无响应Clients),以确定您的客户端主机是否能够及时处理来自 Redis 服务器的响应。
请注意不要监视进程 CPU,因为单个进程的 CPU 使用率较低,但系统范围的 CPU 可能很高。 注意与超时相对应的 CPU 使用率峰值。 高 CPU 也可能导致错误消息中的in: XXX
值变高timeoutException
。 有关示例,请参阅 流量突发和线程池配置 部分。
StackExchange.Redis 1.1.603 及更高版本在 local-cpu
错误消息中包括了 timeoutException
指标。 请确保使用 最新版本的 StackExchange.Redis NuGet 包,因为定期修复 bug 以使代码对超时更具抵抗力。 有关详细信息,请参阅 调查 timeout
StackExchange.Redis 中的异常。
可以使用 redis-cli --bigkeys
命令检查缓存中的大键。 有关 redis-cli、Redis 命令行接口的详细信息,请参阅 Redis CLI。
若要缓解问题:
增加 VM 的大小以获取更高的带宽功能。 提高客户端或服务器 VM 上的带宽可以缩短较大响应的数据传输时间。 将两个 VM 上的当前网络使用情况与当前 VM 大小的限制进行比较。 仅服务器或客户端上的更多带宽可能不够。
增加应用程序使用的连接对象数。 使用轮询方法通过不同的连接对象发出请求。 有关使用多个键和较小值的信息,请参阅考虑使用更多键和较小的值。
客户端的内存压力可能导致延迟处理缓存响应的性能问题。 出现内存压力时,系统可能会将数据分页到磁盘。 此页面错误导致系统显著减慢。
检测客户端上的内存压力:
- 监视 VM 上的内存使用情况,确保不会超过可用内存。
- 监视客户端的
Page Faults/Sec
性能计数器。 在正常运行期间,大多数系统会出现某些页面错误。 如果页面错误中存在与请求超时相关的峰值,可能表示出现了内存压力。
若要缓解客户端上的高内存压力,
- 调查内存使用模式以减少客户端上的内存消耗。
- 将客户端 VM 升级到可提供更多内存的更大大小。
根据它们的体系结构,客户端计算机可能对网络带宽可用性有限制。 如果客户端因网络容量超载而超过可用带宽,数据在客户端的处理速度就没有服务器发送的快。 这种情况下会导致超时。
若要缓解此问题,请减少网络带宽消耗,或者将客户端 VM 大小提高到可以提供更大网络容量的大小。 有关详细信息,请参阅请求或响应大小过大。
如果使用 RedisSessionStateProvider
,请确保正确设置 retryTimeout
。
retryTimeoutInMilliseconds
值应大于 operationTimeoutInMilliseconds
值。 如果不是这样,则不会重试。
在以下示例中,retryTimeoutInMilliseconds
设置为 3000
。
<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"
>
有关详细信息,请参见:
由于 Linux 中的乐观 TCP 设置,在 Linux 上托管的客户端应用程序可能会遇到连接问题。 有关详细信息,请参阅 Linux 托管客户端应用程序的 TCP 设置。
流量激增时,如果 ThreadPool
设置不佳,则可能导致对 Redis 服务器已发送但尚未在客户端上使用的数据的处理出现延迟。 检查 错误(类型:无响应客户端) 指标,以确认您的客户端是否可以应对瞬间流量高峰。 可以 配置线程池设置,以确保线程池在突发场景中快速扩展。
可以使用 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)不会像服务器发送数据一样快速从网络读取数据。
StackExchange.Redis 1.1.603 及更高版本在 local-cpu
错误消息中包括了 timeoutException
指标。 请确保使用 最新版本的 StackExchange.Redis NuGet 包,因为定期修复 bug 以使代码对超时更具抵抗力。 了解更多信息,请参阅 StackExchange.Redis 中超时异常的研究。
以下服务器端问题可能会影响性能并导致超时。
服务器上的内存压力可能导致延迟请求处理的各种性能问题。 出现内存压力时,系统会将数据分页到磁盘,这会导致系统明显减慢速度。
内存压力的一些可能原因是,缓存填充的数据接近其最大容量,或者 Redis 服务器内存碎片较高。
当负载模式存储大小差异较高的数据时,例如,当数据分布在 1 KB 和 1 MB 大小之间时,可能会发生碎片。 从现有内存中删除 1 KB 密钥时,1 MB 键无法容纳到空间中,从而导致碎片化。 同样,如果删除 1-MB 密钥,则添加的 1.5 MB 密钥无法容纳到现有的回收内存中。 此未使用的可用内存会导致碎片化。
如果缓存出现碎片并在高内存压力下运行,则系统将执行故障转移以尝试恢复驻留集大小(RSS)内存。 Redis 公开了两个统计信息,used_memory
和 used_memory_rss
,通过 INFO 命令来帮助你识别此问题。 还可以 在 Azure 门户中查看这些指标。
如果 used_memory_rss
值是 used_memory
指标的 1.5 倍,内存中便会出现碎片。 若出现以下情况,碎片可能会导致问题:
- 内存使用率接近缓存的最大内存限制。
- 该
used_memory_rss
指标高于最大内存限制,可能会导致内存中页面出错。
可以采取多项措施来帮助保持内存使用的健康状态。
- 配置内存策略,对密钥设置过期时间。 如果出现碎片化,则此策略可能不够充分。
- 配置 maxmemory-reserved 和 maxfragmentationmemory-reserved 参数 的值足够大,以补偿内存碎片。
- 基于指标(例如已用内存)创建警报,以提前收到有关潜在影响的通知。
- 扩展到可提供更多内存容量的更大缓存大小。 有关详细信息,请参阅 Azure Cache for Redis 规划常见问题解答。
有关内存管理的详细信息,请参阅 内存管理的最佳做法。
高服务器负载意味着 Redis 服务器繁忙,无法跟上请求,导致超时或响应缓慢。 为缓解服务器负载高的情况,首先应调查原因,例如高内存压力导致的长时间运行的命令。
可以从 Azure 门户 监视服务器 负载等指标。 若要检查服务器负载指标,请从缓存页上的左侧导航菜单中选择“监视”下的“见解”,然后查看“服务器加载”图。 或在左侧导航菜单中的“监视”下选择“指标”,然后在“指标”下选择“服务器负载”。
监视与超时相关的服务器负载使用量峰值。 针对服务器负载指标创建警报,以便尽早收到潜在影响通知。
在 C0 和 C1 缓存中,服务器负载可能会出现短暂的峰值,这并不是由于请求增加,而是在 VM 上运行的内部 Defender 扫描导致的。 在这些层上,当内部的 Defender 扫描发生时,请求面临更高的延迟。
C0 层和 C1 层上的缓存仅使用单个核心来处理多任务,将负责内部 Defender 扫描和 Redis 请求的工作整合在一起。 如果内部 Defender 扫描的额外延迟会对 C1 缓存上的生产工作负荷产生负面影响,则可以扩展到具有多个 CPU 核心(如 C2)的更高层产品/服务。 有关详细信息,请参阅 选择正确的层。
有关客户端连接数快速更改的详细信息,请参阅 “避免客户端连接峰值”。
可以横向扩展到更多分片,以跨多个 Redis 进程分配负载,或者纵向扩展到具有更多 CPU 核心的更大的缓存。 缩放作占用大量 CPU 和内存,因为它们可能涉及围绕节点移动数据以及更改群集拓扑。 有关详细信息,请参阅 Azure Redis 缓存规划常见问题解答 和 缩放。
某些 Redis 命令的执行开销比其他命令高。 Redis 命令 文档显示每个命令的时间复杂性。 Redis 命令处理是单线程的。 运行时间较长的任何命令都可以阻止其后面的其他命令。
查看你向 Redis 服务器发出的命令,以了解其性能影响。 例如,在不知道这是一个大 O 复杂度操作(O(N))的情况下,KEYS 命令经常被使用。 若要减少 CPU 峰值,可以使用 SCAN 来避免KEYS
。
可以在控制台中运行以下 Redis 命令,以调查运行时间长且耗费资源的命令。
-
该
CLIENT LIST
命令以人类可读格式返回有关客户端连接服务器的信息和统计信息。 -
该
INFO
命令返回有关服务器的信息和统计信息,其格式对于计算机来说,分析简单且易于人类阅读。 此CPU
部分可用于调查 CPU 使用率。 一个server_load
100
(最大值)表示 Redis 服务器一直处于忙碌状态,在处理请求时永远不会空闲。以下示例演示命令的
INFO
输出:# 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
-
MONITOR
是一个调试命令,用于流式传输 Redis 服务器处理的每个命令。MONITOR
可以帮助你了解数据库的动态。 此命令要求很高,可能会对性能产生负面影响并降低性能。 -
Redis 慢速日志是记录超过指定执行时间的查询的系统。 执行时间不包括 I/O作,例如与客户端通信或发送回复,但仅包含实际执行命令所需的时间。
该
SLOWLOG
命令读取并重置 Redis 慢查询日志,还可用于调查客户端上长时间运行的命令。 可以使用 SLOWLOG GET 监视和记录针对 Redis 服务器执行的昂贵命令。
不同的缓存大小具有不同的网络带宽容量。 如果服务器超过可用带宽,则数据不会尽快发送到客户端。 客户端请求可能会超时,因为服务器无法以足够快的速度将数据推送到客户端。
可以在 Azure 门户中监视缓存读取和缓存写入等指标,以查看使用的服务器端带宽量。 针对这些指标创建警报,以便尽早收到潜在影响通知。
缓解网络带宽用量即将达到最大容量的情况:
- 更改客户端调用行为,以降低网络需求。
- 扩展到可提供更高网络带宽容量的更大缓存大小。 有关详细信息,请参阅 Azure Cache for Redis 规划常见问题解答。
计划内或计划外维护可能会导致客户端连接中断。 异常的数目和类型取决于当缓存关闭其连接时,请求在代码路径中所处的位置。
如果 Azure Redis 缓存出现故障切换,来自故障节点的所有客户端连接都会转移到仍在运行的节点。 由于连接增加,服务器负载可能会急剧上升。 可以尝试重启客户端应用程序,以便在两个节点之间重新创建并重新分布所有客户端连接。
在发生故障转移时发送请求但未收到响应的操作可能会遭遇异常timeout
。 对关闭的连接对象发出的新请求将收到连接异常,直到重新连接成功为止。
若要检查在发生 timeout
异常期间 Azure Redis 缓存是否发生故障转移,请检查 错误 指标。 在缓存的 Azure 门户页上,在左侧导航菜单中的“监视”下选择“指标”。 然后创建一个新图表来测量 Errors 指标,按 ErrorType 拆分。 创建此图表后,会看到故障转移计数。 有关故障转移的详细信息,请参阅 Azure Cache for Redis 的故障转移和修补。
有关因服务器维护而缓解问题的详细信息,请参阅以下文章: