本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
持续连接问题
在对持续连接问题进行故障排除时,必须验证以下各项 ElastiCache:
主题
安全组是保护您的 ElastiCache 客户端(EC2实例、 AWS Lambda 函数、Amazon ECS 容器等)和 ElastiCache 缓存的虚拟防火墙。安全组是有状态的,也就是说在允许传入或传出流量后,对该流量所做的响应将在该特定安全组的上下文中自动获得授权。
有状态功能要求安全组跟踪所有已授权的连接,而且对跟踪的连接有限制。如果达到该限制,新连接将会失败。有关如何识别客户端或 ElastiCache 端是否已达到限制的帮助,请参阅疑难解答部分。
您可以同时为客户机和 ElastiCache 群集分配单个安全组,也可以为每个安全组分配单独的安全组。
在这两种情况下,您都需要允许来自源 ElastiCache 端口的TCP出站流量和来自同一端口的入站流量到 ElastiCache。Memcached 的默认端口为 11211,Valkey 或 Redis 的默认端口为 6379。OSS默认情况下,安全组允许所有出站流量。在这种情况下,只需要目标安全组中的入站规则。
有关更多信息,请参阅 访问 Amazon 中集 ElastiCache 群的访问模式VPC 。
网络 ACLs
网络访问控制列表 (ACLs) 是无状态规则。必须在入站和出站两个方向上都允许流量,才能成功。网络分配给ACLs子网,而不是特定的资源。可以将相同的资源ACL分配给 ElastiCache 和客户机资源,特别是如果它们位于同一个子网中。
默认情况下,网络ACLs允许所有流量。但可对它们自定义,以拒绝或允许流量。此外,对ACL规则的评估是按顺序进行的,这意味着与流量匹配的数字最小的规则将允许或拒绝它。允许 Valkey 或 Redis OSS 流量的最低配置是:
客户端网络ACL:
-
出站规则:
-
规则编号:最好低于所有拒绝规则;
-
类型:自定义TCP规则;
-
协议:TCP
-
端口范围:1024 – 65535
-
来源:0.0.0.0/0(或集群子网。 ElastiCache 请记住,在故障转移或扩展集群的情况下,使用 specific IPs 可能会造成问题)
-
允许/拒绝:允许
有关更多信息,请参阅 网络ACLs 。
与网络类似ACLs,每个子网可以有不同的路由表。如果客户端和 ElastiCache 集群位于不同的子网中,请确保它们的路由表允许它们相互访问。
更复杂的环境,包括多个VPCs动态路由或网络防火墙,可能很难排除故障。请参阅 网络连接验证 以确认您的网络设置是否合适。
DNS分辨率
ElastiCache 根据DNS名称提供服务端点。可用的端点包括
Configuration
、
Primary
、
Reader
和
Node
端点。有关更多信息,请参阅
查找连接终端节点
。
在故障转移或集群修改的情况下,与端点名称关联的地址可能会发生变化,并将自动更新。
自定义DNS设置(即不使用VPCDNS服务)可能不知道 ElastiCache提供的DNS名称。确保您的系统能够使用诸如
dig
(如下所示)或之类的系统工具成功解析 ElastiCache 端点
nslookup
。
$ dig +short example.xxxxxx.ng.0001.use1.cache.amazonaws.com example-001.xxxxxx.0001.use1.cache.amazonaws.com. 1.2.3.4
您也可以通过VPCDNS服务强制解析名称:
$ 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用法:Valkey 和 Redis OSS 是多线程应用程序。但是,每个命令的执行都发生在一个(主)线程中。因此, ElastiCache 提供了指标
CPUUtilization
和EngineCPUUtilization
。EngineCPUUtilization
提供专用于Valkey或Redis进程的CPU利用率,以及所有OSS进程CPUUtilization
的使用情况。vCPUs具有多个 v 的节点CPU通常具有不同的CPUUtilization
和值EngineCPUUtilization
,第二个值通常更高。高EngineCPUUtilization
可能是由于请求数量增加或需要花费大量CPU时间才能完成的复杂操作所致。您可以通过以下方式标识两者:-
CacheHits
和CacheMisses
:成功的请求数量或在缓存中找不到有效项目的请求的数量。如果未命中与命中之比较高,则应用程序会因无效的请求浪费时间和资源。 -
SetTypeCmds
和GetTypeCmds
:这些与EngineCPUUtilization
相关的指标可以帮助理解写入请求(由SetTypeCmds
衡量)还是读取请求(由GetTypeCmds
衡量)的负载明显更高。如果负载主要是读取,则使用多个只读副本可以在多个节点之间平衡请求,并将主节点留出用于写入。在禁用集群模式的集群中,可通过使用读取器终端节点在应用程序中创建其他连接配置来使用只读副本。 ElastiCache 有关更多信息,请参阅 查找连接终端节点 。读取操作必须提交到此额外连接。写入操作将通过常规主端点完成。在已启用集群模式的情况下,建议使用支持本机只读副本的库。使用正确的标志,库将能够自动发现集群拓扑、副本节点,通过 READONLY
-
增加的连接数:
-
CurrConnections
和NewConnections
:CurrConnection
是数据点集合时已建立的连接数,而NewConnections
显示的是在期间内创建的连接数。创建和处理连接需要大量CPU开销。此外,创建新连接所需的TCP三方握手会对整体响应时间产生负面影响。
NewConnections
每分钟数千个的 ElastiCache 节点表示仅通过几个命令即可创建和使用连接,这不是最佳选择。最佳做法是保持已建立连接并将其重复用于新操作。当客户端应用程序支持并正确实现连接池或持久连接时,可采用此最佳做法。使用连接池时,currConnections
数量没有很大的变化,NewConnections
应该尽可能的低。Valkey 和 Redis 只需少量即可OSS提供最佳性能。currConnections保持 currConnection 数十或数百可以最大限度地减少支持单个连接(例如客户端缓冲区和为连接提供服务的CPU周期)的资源使用量。 -
网络吞吐量:
-
确定带宽: ElastiCache 节点的网络带宽与节点大小成正比。由于应用程序具有不同的特征,因此结果可能会因工作负载而异。例如,小请求率高的应用程序对CPU使用率的影响往往大于对网络吞吐量的影响,而较大的密钥会导致更高的网络利用率。因此,建议使用实际工作负载测试节点,以便更好地了解限制。
模拟应用程序的负载可以提供更准确的结果。但是,通过基准工具可以很好地了解限制。
-
对于主要是读取请求的情况,使用副本进行读取操作将减轻主节点上的负载。如果使用场景主要是写入,则使用许多副本将增加网络使用率。对于写入主节点的所有字节,有 N 个字节将被发送到副本,N 为副本数。写入密集型工作负载的最佳实践是使用启用集群模式的 ElastiCache (RedisOSS),这样写入就可以在多个分片之间进行平衡,或者扩展到具有更多网络功能的节点类型。
-
CloudWatchmetrics
NetworkBytesIn
和分别NetworkBytesOut
提供进入或离开节点的数据量。ReplicationBytes
是专用于数据复制的流量。有关更多信息,请参阅 网络相关限制 。
-
复杂命令:Redis OSS 命令在单个线程上提供,这意味着请求是按顺序提供的。单个慢速命令可能会影响其他请求和连接,最终导致超时。对多个值、密钥或数据类型进行操作的命令的使用必须仔细完成。根据参数数量或其输入或输出值的大小,可以阻止或终止连接。
一个显著例子就是
KEYS
命令。此命令扫描整个密钥空间来搜索给定模式,并在其执行过程中阻止其他命令的执行。Redis OSS 使用 “Big O” 表示法来描述其命令的复杂性。密钥命令具有 O (N) 时间复杂性,N 表示数据库中的密钥数。因此,密钥数越大,命令的速度就越慢。
KEYS
可能会以不同的方式制造麻烦:如果未使用搜索模式,则该命令会返回所有可用的密钥名称。在含有数千或百万个项目的数据库中,这将会创建大量输出并充满网络缓冲区。如果使用了搜索模式,则只有匹配该模式的密钥才会返回到客户端。但是,引擎仍然会扫描整个密钥空间来搜索它,并且完成命令的时间将是相同的。
KEYS
命令的一个替代选择是SCAN
命令。此命令会遍历密钥空间并限制特定数量项目中的迭代,避免引擎上的长时间阻塞。扫描具有
COUNT
参数,用于设置迭代块的大小。默认值为 10(每次迭代 10 个项目)。取决于数据库中的项目数,较小的
COUNT
值数据块将需要更多的迭代才能完成全面扫描,而且较大的值将使引擎在每次迭代中处于繁忙状态。虽然小计数值将使SCAN
在大数据库变慢,较大的值可能会导致出现KEYS
中提及的相同问题。例如,运行
SCAN
命令(计数值为 10)将需要在具有 100 万个密钥的数据库上进行 10 万次重复操作。如果平均网络往返时间为 0.5 毫秒,则传输请求将耗时大约 5 万毫秒(50 秒)。另一方面,如果计数值为 100,0000,则需要一次迭代,并且传输它只需要 0.5 毫秒。但是,在命令完成扫描所有密钥空间之前,该引擎将完全阻止其他操作。
除了
KEYS
之外,其他几个命令如果使用不当也可能会有害。要查看所有命令的列表及其各自的时间复杂度,请转到 Valkey 和 Redis OSS潜在问题的示例:
-
Lua 脚本:Valkey 和 Redis OSS 提供了嵌入式 Lua 解释器,允许在服务器端执行脚本。Valkey 和 Redis 上的 Lua 脚本OSS是在引擎级别执行的,顾名思义是原子的,这意味着在脚本执行期间不允许运行其他命令或脚本。Lua 脚本提供了直接在引擎上运行多个命令、决策算法、数据解析和其他命令的可能性。虽然脚本的原子性和分载应用程序的可能性很诱人,但必须小心使用脚本,并且仅用于小型操作。开 ElastiCache启后,Lua 脚本的执行时间限制为 5 秒。未写入密钥空间的脚本将在 5 秒后自动终止。为了避免数据损坏和不一致,如果脚本执行在 5 秒内未完成并且在执行过程中有任何写入,则节点将进行故障转移。 事务
-
批量删除项目:
DEL
命令接受多个参数,这些参数是要删除的密钥名称。删除操作是同步的,如果参数列表很大,或者包含大列表、集合、排序集或哈希(包含多个子项的数据结构),则删除操作将花费大量CPU时间。换句话说,如果具有许多元素,那么即使删除单个密钥也可能需要相当长的时间。替代方法DEL
是UNLINK
,这是自 Redis OSS 4 起可用的异步命令。UNLINK
DEL
只要有可能,就必须优先于首选。从 ElastiCache (RedisOSS) 6x 开始,该lazyfree-lazy-user-del
参数使DEL
命令的行为与启用UNLINK
时相同。有关更多信息,请参阅 Redis OSS 6.0 参数更改 。 -
对多个密钥进行操作的命令:
DEL
在先前是作为接受多个实际参数的命令提起,其执行时间直接与之成正比。但是,Redis OSS 提供了更多工作方式相似的命令。例如,MSET
和MGET
允许一次插入或检索多个字符串键。使用它们可能有助于降低多个单独的SET
或GET
命令固有的网络延迟。但是,大量的参数列表会影响CPU使用。虽然仅CPU使用率并不是连接问题的原因,但花费太多时间通过多个密钥处理单个或几个命令可能会导致其他请求失败并提高总体CPU利用率。
密钥的数量及其大小将影响命令的复杂性,从而影响完成时间。
其他可对多个密钥进行操作的命令示例:
HMGET
、HMSET
、MSETNX
、PFCOUNT
、PFMERGE
、SDIFF
、SDIFFSTORE
、SINTER
、SINTERSTORE
、SUNION
、SUNIONSTORE
、TOUCH
、ZDIFF
、ZDIFFSTORE
、ZINTER
或ZINTERSTORE
。 -
作用于多种数据类型的命令:Redis OSS 还提供对一个或多个密钥执行操作的命令,无论其数据类型如何。 ElastiCache (RedisOSS) 提供了监控此类命令
KeyBasedCmds
的指标。此指标汇总了以下命令在所选时间段内的执行情况:-
EXISTS
-
OBJECT
-
PTTL
-
RANDOMKEY
-
TTL
-
TYPE
-
EXPIRE
-
EXPIREAT
-
MOVE
-
PERSIST
-
PEXPIRE
-
PEXPIREAT
-
UNLINK (O(N)
来回收内存。但是,内存回收任务发生在一个单独的线程中,并且不会阻塞引擎
-
-
-
根据数据类型不同的复杂性时间:
-
DEL
-
DUMP
-
RENAME
被认为是一个具有 O(1) 复杂性的命令,但在内部执行DEL
。执行时间将根据重命名密钥的大小而变。 -
RENAMENX
-
RESTORE
-
SORT
大哈希:哈希是一种数据类型,允许单个密钥和多个键值子项目。每个哈希可以存储 4,294,967,295 个项目,并且对大哈希执行的操作可能会变得昂贵。类似于
KEYS
,哈希具有
HKEYS
命令,该命令具有 O(N) 时间复杂度,N 表示哈希中的项目数。
HSCAN
必须优先于
HKEYS
来避免长时间运行的命令。
HDEL
、
HGETALL
、
HMGET
、
HMSET
和
HVALS
是应谨慎用于大哈希的命令。