Troubleshooting - 用于 Redis 的 Amazon ElastiCache
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 AWS 服务入门

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

Troubleshooting

在排查 的持久性连接问题时,必须验证以下项目ElastiCache:

安全组

安全组是保护您的ElastiCache客户端EC2 实例、 AWS Lambda 函数Amazon ECS、容器等)和 ElastiCache 集群的虚拟防火墙。安全组是有状态的,这意味着在允许传入或传出流量后,该流量的响应将自动在该特定安全组的上下文中授权。

有状态功能需要安全组跟踪所有授权连接,并且跟踪的连接有限制。如果达到限制,新连接将失败。有关如何确定客户端或 Elasticache 端是否达到了限制的帮助,请参阅故障排除部分。

您可以同时将单个安全组分配给客户端和ElastiCache集群,也可以为每个安全组分配单个安全组。

对于这两种情况,您需要允许ElastiCache端口上来自源的 TCP 出站流量,以及同一端口上到 的入站流量ElastiCache。Memcached 的默认端口为 11211,Redis 的默认端口为 6379。默认情况下,安全组允许所有出站流量。在这种情况下,只需要目标安全组中的入站规则。

有关更多信息,请参阅用于访问 中的 ElastiCache Amazon VPC 集群的访问模式。

网络 ACL

网络访问控制列表 (ACLs) 是无状态的规则。必须允许双向(入站和出站)流量才能成功。网络 ACLs分配给子网,而不是特定的资源。可以将相同的 ACL 分配给 ElastiCache 和客户端资源,尤其是当它们位于同一子网中时。

默认情况下,网络 ACLs 允许所有 trafic。但是,可以自定义它们以拒绝或允许流量。此外,ACL 规则的评估是顺序的,这意味着与流量匹配且数量最小的规则将允许或拒绝它。允许 Redis 流量的最低配置为:

客户端网络 ACL:

  • 入站规则:

  • 规则编号:最好低于任何拒绝规则;

  • 类型:自定义 TCP 规则;

  • Protocol:TCP

  • Port 1024-65535

  • 源:0.0.0.0/0(或为ElastiCache集群子网创建单独规则)

  • Allow/Deny:Allow

  • 出站规则:

  • 规则编号:最好低于任何拒绝规则;

  • 类型:自定义 TCP 规则;

  • Protocol:TCP

  • Port Range:6379

  • 源:0.0.0.0/0(或ElastiCache集群子网)。 请记住,使用特定 IPs可能会在故障转移或扩展集群时产生问题)

  • Allow/Deny:Allow

ElastiCache 网络 ACL:

  • 入站规则:

  • 规则编号:最好低于任何拒绝规则;

  • 类型:自定义 TCP 规则;

  • Protocol:TCP

  • Port Range:6379

  • 源:0.0.0.0/0(或为ElastiCache集群子网创建内部规则)

  • Allow/Deny:Allow

  • 出站规则:

  • 规则编号:最好低于任何拒绝规则;

  • 类型:自定义 TCP 规则;

  • Protocol:TCP

  • Port 1024-65535

  • 源:0.0.0.0/0(或ElastiCache集群子网)。 请记住,使用特定 IPs可能会在故障转移或扩展集群时产生问题)

  • Allow/Deny:Allow

有关更多信息,请参阅网络 ACLs

路由表

与网络 ACLs类似,每个子网可以具有不同的路由表。如果客户端和ElastiCache集群位于不同的子网中,请确保它们的路由表允许它们相互访问。

涉及多个 VPCs动态路由或网络防火墙的更复杂的环境可能会变得难以排查问题。请参阅 网络连接验证 以确认您的网络设置合适。

DNS 解析

ElastiCache 根据 DNS 名称提供服务终端节点。可用的终端节点为 ConfigurationPrimary、 和 Reader Node 终端节点。有关更多信息,请参阅查找连接终端节点

在进行故障转移或集群修改时,与终端节点名称关联的地址可能会更改,并且会自动更新。

自定义 DNS 设置(即不使用 VPC DNS 服务)可能不知道 提供的 DNS ElastiCache名称。确保您的系统可以使用 系统工具ElastiCache(如下所示)或 成功解析dig终端节点nslookup

$ dig +short example.xxxxxx.ng.0001.use1.cache.amazonaws.com example-001.xxxxxx.0001.use1.cache.amazonaws.com. 1.2.3.4

您还可以通过 VPC DNS 服务强制解析名称:

$ dig +short example.xxxxxx.ng.0001.use1.cache.amazonaws.com @169.254.169.253 example-001.tihewd.0001.use1.cache.amazonaws.com. 1.2.3.4

识别服务器端诊断的问题

CloudWatch 来自 ElastiCache 引擎的 指标和运行时信息是确定连接问题的潜在来源的常见源或信息。良好的分析通常从以下项目开始:

  • CPU 使用率:Redis 是一个多线程应用程序。但是,每个命令的执行都发生在一个(主)线程中。因此, ElastiCache 提供 指标CPUUtilizationEngineCPUUtilizationEngineCPUUtilization 提供 Redis 进程专用的 CPU CPUUtilization 利用率以及跨所有 vCPUs使用情况。具有多个 vCPU 的节点通常具有不同的 CPUUtilization 和 值EngineCPUUtilization,第二个通常较高。高EngineCPUUtilization可能是由请求数增加或复杂的操作导致,这些操作需要大量的 CPU 时间才能完成。您可以使用以下内容标识二者:

    • 请求数增加:检查与EngineCPUUtilization模式匹配的其他指标是否增加。有用的指标包括:

      • CacheHitsCacheMisses:在缓存中未找到有效项目的 成功请求或 请求的数量。如果未命中数与命中数的比率较高,则应用程序浪费时间和资源来处理不必要的请求。

      • SetTypeCmdsGetTypeCmds:与 关联的这些指标EngineCPUUtilization有助于了解 所测量的写入请求SetTypeCmds或读取的负载是否显著较高GetTypeCmds。如果主要读取负载,则使用多个只读副本可以跨多个节点平衡请求,并保留主集群进行写入。在集群禁用模式的集群中,可以通过ElastiCache使用读取器终端节点在应用程序中创建额外的连接配置来完成只读副本的使用。有关更多信息,请参阅查找连接终端节点。读取操作必须提交到此附加连接。写入操作将通过常规主终端节点完成。在已启用集群模式的 中,建议使用在本机支持只读副本的库。利用正确的标记,库将自动发现集群拓扑、副本节点,通过 READONLY Redis 命令启用读取操作,并将读取请求提交给副本。

    • 连接数增加:

      • CurrConnectionsNewConnectionsCurrConnection 是数据点收集时已建立的连接数,而 NewConnections 显示在此期间创建的连接数。

        创建和处理连接意味着大量的 CPU 开销。此外,创建新连接所需的 TCP 三向握手对总体响应时间有负面影响。

        ElastiCache 每分钟具有数千个 的 NewConnections 节点表示只有几个命令创建和使用连接,这不是最佳的。建立连接并将其重复用于新操作是最佳实践。当客户端应用程序支持并正确实现连接池或持久性连接时,这是可能的。对于连接池, 的数量currConnections没有较大的变化, NewConnections 应尽可能少。Redis 通过少量currConnections 提供最佳性能。将 currConnection 保持数十或数百的顺序排列可最大程度地减少资源的使用量,以支持各个连接(如客户端缓冲区和 CPU 周期)来为连接提供服务。

    • 网络吞吐量:

      • 确定带宽: ElastiCache 节点具有与节点大小成比例的网络带宽。由于应用程序具有不同的特征,因此,结果可能会因工作负载而异。例如,具有较高速率的小型请求的应用程序往往会比网络吞吐量影响更多的 CPU 使用率,而较大的键会导致较高的网络利用率。因此,最好使用实际工作负载测试节点,以更好地了解限制。

        模拟来自应用程序的负载将提供更准确的结果。但是,基准测试工具可以很好地了解限制。

      • 对于主要读取请求的情况,使用副本执行读取操作将减少主节点上的负载。如果使用案例主要为写入,则使用多个副本将扩大网络使用情况。对于写入主节点的每个字节,将 N 个字节发送到副本,即 N 个副本。写入密集型工作负载的最佳实践是将 ElastiCache for Redis 与支持集群模式的 结合使用,因此可以跨多个分片平衡写入,或扩展到具有更多网络功能的节点类型。

      • CloudWatch指标 NetworkBytesIn 和 分别NetworkBytesOut提供进入或离开节点的数据量。ReplicationBytes 是用于数据复制的流量。

      有关更多信息,请参阅与网络相关的限制

    • 复杂的命令:Redis 命令在单个线程上提供,这意味着请求按顺序提供。单个慢速命令可能会影响其他请求和连接,从而造成超时。必须谨慎使用作用于多个值、键或数据类型的命令。可以根据参数数、其输入或输出值的大小来阻止或终止连接。

      一个常见的示例是 KEYS 命令。它扫描给定模式的整个键空间搜索,并在执行期间阻止其他命令的执行。Redis 使用“Big O”表示法描述其命令的复杂性。

      键命令具有 O(N) 时间复杂性,N 是数据库中的键数。因此,键数越大,命令的速度就越慢。KEYS 可能以不同方式导致问题:如果未使用搜索模式,则命令将返回所有可用的键名。在包含数千个或数百万个项目的数据库中,将创建大型输出并泛洪网络缓冲区。

      如果使用了搜索模式,则仅与该模式匹配的键将返回到客户端。但是,引擎仍会扫描整个键空间搜索,并且完成命令的时间相同。

      的替代方法是 KEYS SCAN 命令。它循环访问键空间并限制特定数量的项中的迭代,从而避免引擎上的长时间数据块。

      扫描具有 COUNT 参数,用于设置迭代块的大小。默认值为 10(每次迭代 10 个项目)。

      根据数据库中的项目数,较小的COUNT值块需要更多迭代以完成完全扫描,而较大的值将在每次迭代时保持引擎的繁忙时间。虽然较小的计数值会导致大型数据库SCAN的速度变慢,但较大的值可能会导致 提到的相同问题KEYS

      例如,运行计数值为 10 的SCAN命令需要在具有 100 万个键的数据库上进行 100,000 次重复。如果平均网络往返时间为 0.5 毫秒,则大约 50,000 毫秒 (50 秒) 将用于传输请求。

      另一方面,如果计数值为 100,0000,则需要进行单次迭代,并且仅花费 0.5 毫秒进行传输。但是,对于其他操作,引擎将被完全阻止,直到命令完成覆盖所有键空间。

      除了 之外KEYS,其他几个命令如果使用不正确,则可能有害。要查看所有命令的列表及其相应的时间复杂性,请转到 https://redis.io/commands

      潜在问题的示例:

      • Lua 脚本:Redis 提供了嵌入式 Lua 解释器,允许在服务器端执行脚本。Redis 上的 Lua 脚本在引擎级别执行,并且根据定义是原子的,这意味着在脚本执行期间不允许运行任何其他命令或脚本。Lua 脚本提供了直接在 Redis 引擎上运行多个命令、决策算法、数据解析等操作的可能性。虽然脚本的原子性和卸载应用程序的几率很诱人,但脚本必须谨慎使用且适用于小型操作。在 上ElastiCache,Lua 脚本的执行时间限制为 5 秒。尚未写入键空间的脚本将在 5 秒的时间段后自动终止。为避免数据损坏和不一致,如果脚本执行在 5 秒内未完成并且在执行期间有任何写入,则节点将进行故障转移。事务是保证 Redis 中多个相关密钥修改的一致性的替代方法。事务允许执行一组命令,同时监视现有键以查找修改。如果事务完成之前任何受监控密钥发生更改,则放弃所有修改。

      • 项目的大规模删除: DEL 命令接受多个参数,这些参数是要删除的键名。删除操作是同步的,如果参数列表很大,或者包含大型列表、集、排序集或哈希(包含多个子项的数据结构),则删除操作将花费大量的 CPU 时间。换句话说,即使删除单个密钥包含许多元素,也可能需要花费大量时间。的替代方法是 DEL UNLINK,这是一个自 Redis 4 以来可用的异步命令。UNLINK 必须DEL优先于 。从 ElastiCache for Redis 6x开始, lazyfree-lazy-user-del 参数使DEL命令在启用UNLINK时的行为与启用时的行为类似。有关更多信息,请参阅 Redis 6.x 参数更改

      • 对多个键执行的命令: 之前作为接受多个参数的命令DEL提及,其执行时间将与此成正比。但是,Redis 还提供了更多工作类似的命令。例如, MSETMGET 允许一次插入或检索多个字符串键。使用它们可能有助于减少多个单个 SETGET 命令固有的网络延迟。但是,大量参数列表将影响 CPU 使用率。

        虽然仅 CPU 使用率不是导致连接问题的原因,但花过多时间通过多个键处理单个或几个命令可能会导致其他请求失败并增加整体 CPU 利用率。

        键的数量及其大小将影响命令的复杂性并随之影响完成时间。

        可以对多个键执行操作的命令的其他示例HMGET:、HMSETMSETNXPFCOUNTPFMERGESDIFFSDIFFSTORESINTERSINTERSTORESUNIONSUNIONSTORE、、TOUCHZDIFF、、、 ZDIFFSTORE ZINTERZINTERSTORE

      • 作用于多种数据类型的命令:Redis 还提供了作用于一个或多个键的命令,无论其数据类型如何。 ElastiCache for Redis 提供了 指标KeyBasedCmds来监控此类命令。此指标计算所选时间段内以下命令的执行情况:

        • O(N) 复杂性:

          • KEYS

        • O(1)

          • EXISTS

          • OBJECT

          • PTTL

          • RANDOMKEY

          • TTL

          • TYPE

          • EXPIRE

          • EXPIREAT

          • MOVE

          • PERSIST

          • PEXPIRE

          • PEXPIREAT

          • UNLINK (O(N) 回收内存。但是,内存回收任务在单独的线程中进行,并且不会阻止引擎

        • 根据数据类型,不同的复杂性时间会有所不同:

          • DEL

          • DUMP

          • RENAME 被视为具有 O(1) 复杂性的命令,但 DEL 内部执行。执行时间因重命名的键的大小而异。

          • RENAMENX

          • RESTORE

          • SORT

        • 大哈希:哈希是一种数据类型,它允许具有多个键/值子项的单个键。每个哈希可以存储 294.967.295 个项目和对大哈希执行的操作可能会变得昂贵。与 类似KEYS,哈希具有 HKEYS 命令,且 O(N) 时间复杂,N 是哈希中的项目数。HSCAN 必须优先于 HKEYS ,以避免长时间运行的命令。HDEL HGETALL、、 HMGETHMSET HVALS 是 命令,应谨慎用于大哈希。

      • 其他大数据结构:除了哈希以外,其他数据结构可能采用 CPU 密集型结构。设置、列表、排序集和 Hyperloglogs 也可能需要大量时间来操作,具体取决于它们的大小和使用的命令。有关这些命令的更多信息,请参阅 https://redis.io/commands

网络连接验证

在查看与 DNS 解析、安全组、网络 ACLs和路由表相关的网络配置后,可以使用 VPC 可到达性分析器和系统工具验证连接。

可到达性分析器将测试网络连接并确认是否满足所有要求和权限。对于下面的测试,您需要 VPC 中可用ElastiCache节点之一的 ENI ID(弹性网络接口标识)。您可以通过执行以下操作找到它:

  1. 转至 https://console.aws.amazon.com/ec2/v2/home?# NIC:

  2. 按 Elasticache 集群名称或之前从 DNS 验证获得的 IP 地址筛选接口列表。

  3. 记下或以其他方式保存 ENI ID。如果显示多个接口,请查看描述以确认它们属于正确的ElastiCache集群,然后选择其中一个。

  4. 继续执行下一步。

  5. https://console.aws.amazon.com/vpc/home?# 创建分析路径 ReachabilityAnalyzer 并选择以下选项:

    • Source Type (源类型):如果您的客户端在 实例或ElastiCache网络接口Amazon EC2上运行,并且它使用其他服务(如 与 awsvpc 网络、 AWS Fargate等)以及相应的资源 EC2 实例或 ENI ID),则选择Amazon ECS实例AWS Lambda。

    • Destination Type (目标类型):选择 Network Interface (网络接口),然后从列表中选择 Elasticache ENI。

    • 目标端口:为 指定 6379 ElastiCache for Redis 或为 指定 ElastiCache for Memcached11211。这些是使用默认配置定义的端口,此示例假定它们未更改。

    • Protocol:TCP

创建分析路径,然后等待片刻,获得结果。如果状态无法访问,请打开分析详细信息并查看分析资源管理器以了解阻止请求的详细信息。

如果通过了可到达性测试,则继续在操作系统级别进行验证。

要验证ElastiCache服务端口上的 TCP 连接:在 Amazon Linux 上, Nping 位于程序包中nmap,可以测试ElastiCache端口上的 TCP 连接,并提供网络往返时间以建立连接。使用此参数验证ElastiCache集群的网络连接和当前延迟,如下所示:

$ sudo nping --tcp -p 6379 example.xxxxxx.ng.0001.use1.cache.amazonaws.com Starting Nping 0.6.40 ( http://nmap.org/nping ) at 2020-12-30 16:48 UTC SENT (0.0495s) TCP ... (Output suppressed ) Max rtt: 0.937ms | Min rtt: 0.318ms | Avg rtt: 0.449ms Raw packets sent: 5 (200B) | Rcvd: 5 (220B) | Lost: 0 (0.00%) Nping done: 1 IP address pinged in 4.08 seconds

默认情况下, nping 发送 5 个探测器,它们之间的延迟为 1 秒。您可以使用选项“-c”来增加探测器数量,使用“--delay”来更改发送新测试的时间。

如果使用 的测试nping失败,并且通过了 VPC 可到达性分析器测试,请要求系统管理员查看基于主机的防火墙规则、非对称路由规则或操作系统级别的任何其他可能限制。

在 ElastiCache 控制台上,检查是否在集群详细信息中启用了传输中ElastiCache加密。如果启用了传输中加密,请使用以下命令确认是否可以建立 TLS 会话:

openssl s_client -connect example.xxxxxx.use1.cache.amazonaws.com:6379

如果连接和 TLS 协商成功,预计会有大量输出。检查最后一行中提供的返回代码,值必须为 0 (ok)。如果 openssl 返回不同的内容,请在 https://www.openssl.org/docs/man1.0.2/man1/verify.html#DIAGNOSTICS 上检查错误的原因。

如果所有基础设施和操作系统测试都已通过,但应用程序仍无法连接到 ElastiCache,请检查应用程序配置是否符合 ElastiCache 设置。常见错误包括:

  • 您的应用程序不支持ElastiCache集群模式,并且已启用ElastiCache集群模式;

  • 您的应用程序不支持 TLS/SSL,并且已启用传输ElastiCache中加密;

  • 应用程序支持 TLS/SSL,但没有正确的配置标记或可信的证书颁发机构;

与网络相关的限制

  • 最大连接数:同时连接有硬限制。每个ElastiCache节点允许跨所有客户端的最多 65000 个同时连接。可通过 上的 CurrConnections 指标监控此限制CloudWatch。但是,客户端也具有出站连接的限制。在 Linux 上,请使用 命令检查允许的临时端口范围:

    # sysctl net.ipv4.ip_local_port_range net.ipv4.ip_local_port_range = 32768 60999

    在上一个示例中,将允许从同一源到同一目标 IP(ElastiCache 节点)和端口的 28231 个连接。以下命令显示特定 Elasticache 节点 (IP 1.2.3.4) 有多少个连接存在:

    ss --numeric --tcp state connected "dst 1.2.3.4 and dport == 6379" | grep -vE '^State' | wc -l

    如果数字过高,您的系统可能会过载,尝试处理连接请求。建议您考虑实施连接池或持久性连接等技术以更好地处理连接。如果可能,请配置连接池以将最大连接数限制为几百个。此外,最好使用退避逻辑来处理超时或其他连接异常,以避免在出现问题时引发连接流失。

  • 网络流量限制:检查 Redis 的以下CloudWatch指标以确定ElastiCache节点上可能存在的网络限制:

    • NetworkBandwidthInAllowanceExceeded / NetworkBandwidthOutAllowanceExceeded:网络数据包形状,因为吞吐量超出了聚合带宽限制。

      请务必注意,写入主节点的每个字节都将复制到 N 个副本,其中 N 个是副本的数量。具有小节点类型、多个副本和密集型写入请求的集群可能无法处理复制积压。对于此类情况,最好进行纵向扩展(更改节点类型)、横向扩展(在启用集群模式的集群中添加分片)、减少副本数或最大程度地减少写入数。

    • NetworkConntrackAllowanceExceeded:因超出分配到节点的所有安全组的最大跟踪连接数而形成数据包。在此期间,新连接可能会失败。

    • NetworkPackets PerSecondAllowanceExceeded:超出每秒最大数据包数。基于高速率的非常小请求的工作负载可能会超过此限制,超过最大带宽。

    以上指标是确认节点达到其网络限制的理想方式。但是,网络指标的稳定状态也可以确定限制。

    如果观察到平台很长一段时间,则它们可能后跟复制滞后、增加用于缓存的字节数、减少可释放内存、高交换和 CPU 使用率。 Amazon EC2 实例还具有可通过 ENA 驱动程序指标跟踪的网络限制。具有增强联网支持和 ENA 驱动程序 2.2.10 或更高版本的 Linux 实例可以使用 命令查看限制计数器:

    # ethtool -S eth0 | grep "allowance_exceeded"

CPU 使用率

CPU 使用率指标是调查的起点,以下项目可以帮助缩小ElastiCache这一侧可能存在的问题:

  • Redis SlowLogsElastiCache默认配置保留最后 128 个需要 10 毫秒以上的命令。慢速命令的历史记录将在引擎运行时保留,并在发生故障或重新启动时丢失。如果列表达到 128 个条目,则将删除旧事件以便为新事件开放空间。慢速事件列表的大小和所考虑的慢速执行时间可以通过 参数修改slowlog-max-len,也可以在slowlog-log-slower-than自定义参数https://docs.amazonaws.cn/AmazonElastiCache/latest/red-ug/ParameterGroups.html组中进行修改。可通过SLOWLOG GET 128在引擎上运行 来检索慢速日志列表,报告的最近 128 个慢速命令即为 128 个慢速命令。每个条目都具有以下字段:

    1) 1) (integer) 1 -----------> Sequential ID 2) (integer) 1609010767 --> Timestamp (Unix epoch time)of the Event 3) (integer) 4823378 -----> Time in microseconds to complete the command. 4) 1) "keys" -------------> Command 2) "*" ----------------> Arguments 5) "1.2.3.4:57004"-> Source

    上述事件于 12 月 26 日 19:26:07 UTC 发生,耗费 4.8 秒 (823ms) 才能完成,是由从客户端 1.2.3.4 请求的 KEYS 命令导致的。

    在 Linux 上,可以使用命令日期转换时间戳:

    $ date --date='@1609010767' Sat Dec 26 19:26:07 UTC 2020

    使用 Python:

    >>> from datetime import datetime >>> datetime.fromtimestamp(1609010767) datetime.datetime(2020, 12, 26, 19, 26, 7)

    或在具有 PowerShell 的 Windows 上:

    PS D:\Users\user> [datetimeoffset]::FromUnixTimeSeconds('1609010767') DateTime : 12/26/2020 7:26:07 PM UtcDateTime : 12/26/2020 7:26:07 PM LocalDateTime : 12/26/2020 2:26:07 PM Date : 12/26/2020 12:00:00 AM Day : 26 DayOfWeek : Saturday DayOfYear : 361 Hour : 19 Millisecond : 0 Minute : 26 Month : 12 Offset : 00:00:00Ticks : 637446075670000000 UtcTicks : 637446075670000000 TimeOfDay : 19:26:07 Year : 2020

    很短的一段时间内的慢速命令 (分钟或更短时间) 是引起关注的原因。查看命令的性质以及如何优化它们(请参阅前面的示例)。如果频繁报告具有 O(1) 时间复杂性的命令,请检查前面提到的高 CPU 使用率的其他因素。

  • 延迟指标: ElastiCache for Redis 提供了用于监控不同类别命令的平均延迟的CloudWatch指标。数据点的计算方法是:将 类别中命令的总执行次数除以该时间段内的总执行时间。请务必了解延迟指标结果是多个命令的聚合。单个命令可能会导致意外结果(如超时),而不会对指标产生重大影响。对于此类情况,慢速日志事件将是更准确的信息源。以下列表包含可用的延迟指标以及影响这些指标的相应命令。

    • EvalBasedCmdsLatency与 Lua Script 命令eval、、 相关evalsha

    • GeoSpatialBasedCmdsLatency:geodistgeohash、、geoposgeoradiusgeoradiusbymember、、 geoadd

    • GetTypeCmdsLatency:读取命令,无论数据类型如何;

    • HashBasedCmdsLatency:hexistshgethgetallhkeyshlenhmgethvalshstrlenhdelhincrbyhincrbyfloathmset、、、、、、hset、、、、、、、、、、、、 hsetnx

    • HyperLogLogBasedCmdsLatency:pfselftestpfcountpfdebugpfadd、、pfmerge

    • KeyBasedCmdsLatency:可作用于不同数据类型的命令:dumpexists、、keysobjectpttlrandomkeyttltypedelexpireexpireat、、movepersistpexpire、、pexpireat、、、rename、、、renamenx、、、、、、、restoreK、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、sort、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、 unlink

    • ListBasedCmdsLatency:lindex、llen、lrange、blpop、brpop、brpoplpush、linsert、lpop、lpush、lpushx、lrem、lset、ltrim、rpop、rpoplpush、rpush、rpushx;

    • PubSubBasedCmdsLatency:psubscribe、publish、puubsub、punsubscribe、subscribe、unsubscribe;

    • SetBasedCmdsLatency:scardsdiffsintersismembersmemberssrandmembersunionsaddsdiffstoresinterstoresmovespop、、、、、、srem、、 sunionstore

    • SetTypeCmdsLatency:无论数据类型如何,都写入命令;

    • SortedSetBasedCmdsLatency:zcardzcount、、zrangezrangebyscorezrankzrevrangezrevrangebyscore、、zrevrankzscorezrangebylex、、zrevrangebylexzlexcountzadd、。zincrbyzinterstorezremzremrangebyrankzremrangebyscore、、zunionstorezremrangebylexzpopmaxzpopminbzpopmin、、bzpopmax

    • StringBasedCmdsLatency:bitcountgetgetbitgetrangemgetstrlen、、substrbitposappendbitopbitfielddecrdecrbygetset、、incrincrbyincrbyfloatmsetmsetnxpsetex、、、set、、、、、、setbit、、、、、、、、、、、、、、、、、、setex、、、、、、、、、、、、、、、、、、、、、、、、、、、、setnx、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、 setrange

    • StreamBasedCmdsLatency:xrangexrevrangexlenxreadxpendingxinfoxaddxgroupreadgroupxackxclaimxdel、、、、、、、xtrim、、、 xsetid

  • Redis 运行时命令:

    • info commandstats:提供自 Redis 引擎启动以来执行的命令的列表、其累积执行数、总执行时间和每个命令的平均执行时间;

    • 客户端列表:提供当前连接的客户端以及缓冲区使用情况、上次执行的命令等相关信息的列表;

  • 备份和复制:2.8.22 之前的ElastiCache for Redis版本使用分支过程创建备份并处理与副本的完整同步。此方法可能会因写入密集型使用案例而产生大量内存开销。

    从 Elasticache Redis 2.8.22 开始,AWS 引入了无分支备份和复制方法。新方法可能会延迟写入以防止失败。这两种方法都可能会导致较高的 CPU 利用率,导致更高的响应时间,并因此导致在执行期间出现客户端超时。始终检查客户端故障是否在备份时段内发生或 SaveInProgress 指标在该时段内为 1。最好将备份时段安排在低利用率期间,以最大程度地降低客户端出现问题或备份故障的可能性。

从服务器端终止的连接

默认ElastiCache for Redis配置保持客户端连接无限期建立。但是,在某些情况下,可能需要终止连接。例如:

  • 客户端应用程序中的错误可能会导致连接被忘记并保持空闲状态。这称为“连接泄漏”,因此,将随着CurrConnections在 指标上观察到的已建立连接数的不断增加而逐渐增加。此行为可能导致客户端或ElastiCache端的饱和。当无法从客户端立即修复时,某些管理员会在其ElastiCache参数组中设置“timeout”值。超时是空闲连接持续所允许的秒数。如果客户端在这段时间内未提交任何请求,Redis 引擎将在连接达到超时值后立即终止连接。超时值较小可能会导致不必要的断开连接,客户端需要正确处理它们并重新连接,从而造成延迟。

  • 用于存储密钥的内存将与客户端缓冲区共享。具有大量请求或响应的慢速客户端可能需要大量内存来处理其缓冲区。默认ElastiCache for Redis配置不限制常规客户端输出缓冲区的大小。如果达到maxmemory限制,引擎将尝试移出项目以完成缓冲区使用。在极低的内存条件下, ElastiCache for Redis 可能会选择断开使用大型客户端输出缓冲区的客户端的连接,以释放内存并保持集群的运行状况。

    可以使用自定义配置限制客户端缓冲区的大小,达到限制的客户端将断开连接。但是,客户端应该能够处理意外断开连接。用于处理常规客户端的缓冲区大小的参数如下所示:

    • client-query-buffer-limit:单个输入请求的最大大小;

    • client-output-buffer-limit-normal-soft-limit:客户端连接的软限制。如果 超出软限制的时间(以秒为单位)超过 client-output-buffer-limit-normal-soft-seconds或者达到硬限制,则连接将终止;

    • client-output-buffer-limit-normal-soft-seconds允许连接超出 client-output-buffer-limit-normal-soft-limit 的时间;

    • client-output-buffer-limit-normal-hard-limit:达到此限制的连接将被立即终止。

    除了常规客户端缓冲区之外,以下选项还控制副本节点和 Pub/Sub (发布/订阅) 客户端的缓冲区:

    • client-output-buffer-limit-replica-hard-limit;

    • client-output-buffer-limit-replica-soft-seconds;

    • client-output-buffer-limit-replica-hard-limit;

    • client-output-buffer-limit-pubsub-soft-limit;

    • client-output-buffer-limit-pubsub-soft-seconds;

    • client-output-buffer-limit-pubsub-hard-limit;

Amazon EC2 实例的客户端故障排除

客户端上的负载和响应能力也会影响对 的请求ElastiCache。在解决间歇性连接或超时问题时,需要仔细检查 EC2 实例和操作系统限制。需要观察的一些要点:

  • CPU:

    • EC2 实例 CPU 使用率:确保 CPU 未饱和或接近 100%。历史分析可以通过 完成CloudWatch,但请记住,数据点粒度为 1 分钟(启用详细监控)或 5 分钟;

    • 如果使用可突增EC2 实例,请确保其 CPU 积分余额尚未用完。此信息在 CPUCreditBalance CloudWatch 指标中提供。

    • CPU 使用率高的短暂期间可能会导致超时,而不会反映 上的 100% 使用率CloudWatch。此类情况需要使用操作系统工具(如 topps 和 )进行实时监控mpstat

  • Network

    • 根据实例功能,检查网络吞吐量是否低于可接受的值。有关更多信息,请参阅 Amazon EC2 实例类型

    • 在具有ena增强网络驱动程序的实例上,检查 ena 统计数据中的超时或超出限制。以下统计数据可用于确认网络限制饱和度:

      • bw_in_allowance_exceeded /bw_out_allowance_exceeded:由于入站或出站吞吐量过高而形成形状的数据包数;

      • conntrack_allowance_exceeded:由于安全组连接跟踪限制而丢弃的数据包数。当此限制饱和时,新连接将失败;

      • linklocal_allowance_exceeded:由于通过 VPC DNS 对实例元数据 NTP 的请求过多而丢弃的数据包数。所有 服务的限制为每秒 1024 个数据包;

      • pps_allowance_exceeded:由于每秒数据包比率过高而丢弃的数据包数。当网络流量包含每秒数千个或数百万个非常小的请求时,可能会达到 PPS 限制。 ElastiCache 流量经过优化,可以更好地通过管道或一次执行多个操作的命令(例如 MGET ,而不是 )使用网络数据包GET

拆分完成单个请求所花费的时间

  • 在网络上: TcpdumpWireshark (命令行上为 tshark) 是一个方便的工具,用于了解请求在网络中传输、命中ElastiCache引擎和获取返回所花费的时间。以下示例重点介绍使用以下命令创建的单个请求:

    $ echo ping | nc example.xxxxxx.ng.0001.use1.cache.amazonaws.com 6379 +PONG

    与上述命令并行执行 tcpdump 并返回:

    $ sudo tcpdump -i any -nn port 6379 -tt tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes 1609428918.917869 IP 172.31.11.142.40966 > 172.31.11.247.6379: Flags [S], seq 177032944, win 26883, options [mss 8961,sackOK,TS val 27819440 ecr 0,nop,wscale 7], length 0 1609428918.918071 IP 172.31.11.247.6379 > 172.31.11.142.40966: Flags [S.], seq 53962565, ack 177032945, win 28960, options [mss 1460,sackOK,TS val 3788576332 ecr 27819440,nop,wscale 7], length 0 1609428918.918091 IP 172.31.11.142.40966 > 172.31.11.247.6379: Flags [.], ack 1, win 211, options [nop,nop,TS val 27819440 ecr 3788576332], length 0 1609428918.918122 IP 172.31.11.142.40966 > 172.31.11.247.6379: Flags [P.], seq 1:6, ack 1, win 211, options [nop,nop,TS val 27819440 ecr 3788576332], length 5: RESP "ping" 1609428918.918132 IP 172.31.11.142.40966 > 172.31.11.247.6379: Flags [F.], seq 6, ack 1, win 211, options [nop,nop,TS val 27819440 ecr 3788576332], length 0 1609428918.918240 IP 172.31.11.247.6379 > 172.31.11.142.40966: Flags [.], ack 6, win 227, options [nop,nop,TS val 3788576332 ecr 27819440], length 0 1609428918.918295 IP 172.31.11.247.6379 > 172.31.11.142.40966: Flags [P.], seq 1:8, ack 7, win 227, options [nop,nop,TS val 3788576332 ecr 27819440], length 7: RESP "PONG" 1609428918.918300 IP 172.31.11.142.40966 > 172.31.11.247.6379: Flags [.], ack 8, win 211, options [nop,nop,TS val 27819441 ecr 3788576332], length 0 1609428918.918302 IP 172.31.11.247.6379 > 172.31.11.142.40966: Flags [F.], seq 8, ack 7, win 227, options [nop,nop,TS val 3788576332 ecr 27819440], length 0 1609428918.918307 IP 172.31.11.142.40966 > 172.31.11.247.6379: Flags [.], ack 9, win 211, options [nop,nop,TS val 27819441 ecr 3788576332], length 0 ^C 10 packets captured 10 packets received by filter 0 packets dropped by kernel

    通过上面的输出,我们可以确认 TCP 三向握手已在 222 微秒 (918091 - 917869) 中完成,并且在 173 微秒 (918295 - 918122) 中提交并返回了 ping 命令。

    从请求到关闭连接耗费了 438 微秒 (918307 - 917869)。这些结果将确认网络和引擎响应时间是否良好,并且调查可以专注于其他组件。

  • 在操作系统上: Strace 可帮助识别操作系统级别的时间差距。最好使用更广泛、专用的应用程序分析器或调试器来分析实际应用程序。以下示例仅显示基本操作系统组件是否按预期工作,否则可能需要进一步调查。PING 我们对 使用相同的 Redis strace 命令:

    $ echo ping | strace -f -tttt -r -e trace=execve,socket,open,recvfrom,sendto nc example.xxxxxx.ng.0001.use1.cache.amazonaws.com (http://example.xxxxxx.ng.0001.use1.cache.amazonaws.com/) 6379 1609430221.697712 (+ 0.000000) execve("/usr/bin/nc", ["nc", "example.xxxxxx.ng.0001.use"..., "6379"], 0x7fffede7cc38 /* 22 vars */) = 0 1609430221.708955 (+ 0.011231) socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3 1609430221.709084 (+ 0.000124) socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3 1609430221.709258 (+ 0.000173) open("/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 3 1609430221.709637 (+ 0.000378) open("/etc/host.conf", O_RDONLY|O_CLOEXEC) = 3 1609430221.709923 (+ 0.000286) open("/etc/resolv.conf", O_RDONLY|O_CLOEXEC) = 3 1609430221.711365 (+ 0.001443) open("/etc/hosts", O_RDONLY|O_CLOEXEC) = 3 1609430221.713293 (+ 0.001928) socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 3 1609430221.717419 (+ 0.004126) recvfrom(3, "\362|\201\200\0\1\0\2\0\0\0\0\rnotls20201224\6tihew"..., 2048, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("172.31.0.2")}, [28->16]) = 155 1609430221.717890 (+ 0.000469) recvfrom(3, "\204\207\201\200\0\1\0\1\0\0\0\0\rnotls20201224\6tihew"..., 65536, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("172.31.0.2")}, [28->16]) = 139 1609430221.745659 (+ 0.027772) socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 3 1609430221.747548 (+ 0.001887) recvfrom(0, 0x7ffcf2f2ca50, 8192, 0, 0x7ffcf2f2c9d0, [128]) = -1 ENOTSOCK (Socket operation on non-socket) 1609430221.747858 (+ 0.000308) sendto(3, "ping\n", 5, 0, NULL, 0) = 5 1609430221.748048 (+ 0.000188) recvfrom(0, 0x7ffcf2f2ca50, 8192, 0, 0x7ffcf2f2c9d0, [128]) = -1 ENOTSOCK (Socket operation on non-socket) 1609430221.748330 (+ 0.000282) recvfrom(3, "+PONG\r\n", 8192, 0, 0x7ffcf2f2c9d0, [128->0]) = 7 +PONG 1609430221.748543 (+ 0.000213) recvfrom(3, "", 8192, 0, 0x7ffcf2f2c9d0, [128->0]) = 0 1609430221.752110 (+ 0.003569) +++ exited with 0 +++

    在上述示例中,命令需要 54 毫秒以上才能完成(752110 - 697712 = 54398 微秒)。

    实例化 nc 并执行名称解析(从 697712 到 717890)需要花费大量时间(约 20ms在此时间之后,需要 2ms来创建 TCP 套接字 (745659 到 74758) 和 0.4 毫秒 (747858 到 748300) 以提交和接收请求响应。