通过 Amazon CloudWatch 配合 Amazon ElastiCache for Redis 遵循监控最佳实践
![通过 Amazon CloudWatch 配合 Amazon ElastiCache for Redis 遵循监控最佳实践](https://static001.geekbang.org/infoq/ee/eefb4367da3b1a9d87b2b2ef4fb3592d.jpeg)
![](https://static001.geekbang.org/infoq/90/901c94d306e577e558d31fbde8256f90.gif)
在维持 Amazon ElastiCache 资源的可靠性、可用性与性能方面,监控一直是最为重要的手段之一。在本文中,我们将共同了解如何使用 Amazon CloudWatch 及其他外部工具维持健康运作的 Redis 集群,并防止其意外中断。我们还将具体讨论对扩展需求进行预测及筹备的几种可行方法。
将 Amazon CloudWatch 与 Amazon ElastiCache
配合使用的优势
Amazon ElastiCache 与 Amazon CloudWatch 相结合,能够极大提升资源相关核心性能指标的可见性。此外,Amazon CloudWatch 警报还能够帮助您设置指标阈值并触发通知,确保在需要采取预防措施时及时做出提醒。
随时间对趋势加以监控,还可以帮助您检测工作负载的持续增长。您可以为数据点设置最长达 455 天(15 个月)的时间周期,在此窗口内观察 Amazon CloudWatch 指标的扩展情况,据此预测资源的后续利用率与使用情况。
监控资源
Amazon ElastiCache Redis 集群的运行状况由关键组件(例如 CPU、内存以及网络)的利用率决定。这些组件的过度使用可能导致系统等待时间延长以及整体性能下降。另一方面,过度配置则可能导致资源得不到充分利用,严重影响成本的优化效果。
Amazon ElastiCache 提供的指标使您能够监控集群;截至本文撰稿时,亚马逊云科技已经发布 18 项新的 Amazon CloudWatch 指标。
面向 Amazon ElastiCache 的 Amazon CloudWatch 指标主要分为两类:引擎级指标(由 Redis INFO 命令生成)以及主机级指标(来自 ElastiCache 节点的操作系统)。这些指标以 60 秒为间隔对每个缓存节点进行测量并进行发布。尽管 Amazon CloudWatch 允许您为每项指标任意指定统计信息与检测周期,但只有经过精心设计、相关组合才能真正服务于系统运行。例如,CPU 使用率中的“平均”、“最小”以及“最大”等统计信息非常重要,但“总和”信息则基本没有任何实际价值。
CPU
Redis 可以使用不同的 CPU 执行快照保存或者 UNLINK 等辅助操作,但只能通过单一线程运行命令。换句话说,Redis 每次只能处理一条命令。
考虑到 Redis 的单线程属性,Amazon ElastiCache 提供 EngineCPUUtilization 指标,用以提供对 Redis 进程本身负载情况的精确可见性,从而更好地帮助您了解 Redis 工作负载运行状态。
不同的用例对于高 EngineCPUUtilization 的容忍度都有所区别,其中不存在通用性质的阈值。但作为最佳实践,本文建议大家确保您的 EngineCPUUtilization 始终低于 90%。
使用应用程序及预期工作负载对集群进行基准测试,可以帮助您将 EngineCPUUtilization 与系统实际性能关联起来。我们建议您针对 EngineCPUUtilization 在不同层级上设置多项 Amazon CloudWatch 警报,以便在达到每项阈值(例如 WARN 为 65%,HIGH 为 90%)时,抢在集群性能遭遇实际影响前向您发出通知。
如果您集群的 EngineCPUUtilization 较高,则可以考虑以下补救措施:
较高的 EngineCPUUtilization 指标很可能源自特定的 Redis 操作。Redis 命令会使用 Big O 表示法对时间复杂度进行定义。您可以使用 Redis SLOWLOG 帮助您确定完成命令所需要的时间。一大常见问题在于过度使用 Redis KEY 命令,请在生产环境中对这条命令保持高度关注。
在 Redis 命令的时间复杂性方面,非最优数据模型也有可能给 EngineCPUUtilization 指标带来不必要的压力。例如,集合的基数可能为一项性能因素,而 SMEMBERS、SDIFF、SUNION 以及其他集命令的时间复杂度则由集内元素的数量所定义。哈希的大小(字段数)与运行的操作类型,也会给 EngineCPUUtilization 造成影响。
如果您在包含多个节点的节点组中运行 Redis,则建议您使用副本来创建快照。在从副本创建快照时,主节点不会受到快照保存任务的影响,因此可以继续处理请求而不会降低速度。请验证该节点是否在使用 SaveInProgress 创建快照。在完全同步的情况下,快照应始终位于主节点之上。
大量操作同样可能带来较高的 EngineCPUUtilization 。请明确操作所对应的具体负载类型。如果高 EngineCPUUtilization 主要源自大量读取操作,您可以在 Redis 客户端库中使用 Amazon ElastiCache 读取器端点将其配置为禁用集群模式,或者使用 Redis READONLY 命令将其配置为集群模式。如果您只从读取副本处进行读取,则可以在副本组或者各个分片中添加其他节点(最多五个读取副本)。如果写入操作带来较高的 EngineCPUUtilization ,则需要为主节点提供更强大的计算容量。您可以升级至最新一代 m5 与 r5 节点类型,使用更强的处理器快速执行任务。如果您已经在使用最新一代节点,则应考虑将禁用集群模式切换至启用集群模式。要完成切换,您可以为现有集群创建一套备份,并将另一套已经启用集群模式的新集群内还原这些数据。在启用集群模式之后,解决方案能够添加更多分片并进行横向扩展。分片数量越多,您能够添加的主节点数量就越多,计算容量自然就越强。
除了使用 EngineCPUUtilization 指标监控 Redis 进程负载之外,您还应当注意其余 CPU 内核的资源使用情况。通过 EngineCPUUtilization,您可以监控整个主机的 CPU 利用率百分比。例如,由于建立连接会带来部分处理负载,因此大量新连接的涌入同样有可能拉高 EngineCPUUtilization 指标。
对于 CPU 内核数量小于等于 2 个的小型节点,您还需要关注 CPUUtilization 指标。由于除了快照及托管维护事件等操作之外,您还需要保留一部分计算容量并与 Redis 共享节点 CPU 核心,因此在 EngineCPUUtilization 发生变化之前,您的 CPUUtilization 很可能先一步达到 100%。
最后,Amazon ElastiCache 还支持 T2 与 T3 缓存节点。这些缓存节点提供基准水平的 CPU 性能,并可随时突发峰值 CPU 容量,直到您的免费配额耗尽为止。如果您使用的正是 T2 或 T3 缓存节点,则应监控 CPUCreditUsage 与 CPUCreditBalance,这是因为在配额耗尽之后,其性能会逐渐降低至基准水平。
内存
内存是 Redis 中的一大核心要素。了解集群的内存利用率,有助于避免数据丢失并持续适应数据集规模的不断增长。
Redis INFO 命令中的 memory 部分,提供关于当前节点内存利用率的统计信息。
其中最重要的指标之一为 used_memory,即 Redis 使用分配器所分配的内存容量。Amazon CloudWatch 提供名为 BytesUsedForCache 的指标,其衍生自 used_memory ,您可以使用这项指标确定当前集群的内存利用率。
随着 18 项全新 Amazon CloudWatch 指标的发布,现在您可以使用 DatabaseMemoryUsagePercentage 并根据当前内存利用率(BytesUsedForCache)以及 maxmemory 查看内存利用率百分比。Maxmemory 将设置目标数据集的最大可用内存量。您可以使用 Redis INFO 命令以及 Redis 节点类型特定参数中的 memory 部分调车集群的内存上限。其默认取值由需要保留的内存容量决定。因此在设定之后,您的集群 maxmemory 将有所下降。例如,cache.r5.large 节点类型默认最大内存为 14037181030 字节,但如果您希望默认保留 25%的内存,则可用最大内存容量将为 10527885772.5 字节(14037181030 x 0.75)。
当您的 DatabaseMemoryUsagePercentage 达到 100%时,Redis maxmemory 策略将被触发,且根据所选策略(例如 volatile lru )决定是否进行数据逐出。如果高速缓存内没有任何对外贸易可以进行逐出(根据逐出策略),则写入操作将失败,Redis 主节点随后返回以下消息:(error) OOM command not allowed when used memory > 'maxmemory'
逐出并不代表必然发生了问题或性能下降。某些工作负载在设计上就考虑到了利用逐出机制。要监控集群内的逐出量,您可以使用 Evictions 指标。此指标同样可通过 Redis INFO 命令使用。但请注意,大量逐出同样会拉高 EngineCPUUtilization 指标。
如果您的工作负载在设计中并未考虑使用逐出,则建议您设置 Amazon CloudWatch 警报以在需要执行扩展操作时,主动根据 DatabaseMemoryUsagePercentage 指标的变化情况发出警报并扩展内存容量。对于禁用集群模式的场景,您可以扩展至更大的节点类型以获取更高内存容量。而对于启用集群模式的场景,横向扩展以逐步增加内存容量才是最合理的解决方案。
控制数据集增长的另一种方法,是在密钥当中使用 TTL (生存时间)。当生存时间到期之后,如果客户端(以被动方式)尝试访问或 Redis (以主动方式)定期测试随机密钥,则该密钥将不再提供起效并将被删除。您可以使用 Redis SCAN 命令来分析数据集内的某些部分,并放大被动方法以删除过期密钥。在 Amazon ElastiCache 当中,密钥到期可通过 Reclaimed AmazonCloudWatch 指标进行监控。
在执行备份或故障转移的过程中,当将集群数据写入至 .rdb 文件时,Redis 会使用额外的内存来记录对集群的写入操作。如果此额外的内存使用量超过了节点中的可用内存容量,则过度分页及 SwapUsage 会导致处理速度变慢。因此,我们建议您预留一部分内存容量。预留内存属于专为容纳某些操作(例如备份或故障转移)所预留的内存资源。
最后,本文建议您为 SwapUsage 建立 Amazon CloudWatch 警报。此指标不应超过 50 MB。如果集群正在消耗 swap 空间,请在集群的参数组中验证是否配置了充足的预留内存。
网络
决定集群网络带宽容量的一大决定性因素,在于您所使用的实际节点类型。
我们强烈建议您在实际生产使用之前对集群进行基准测试,借此评估其性能表现并在监控当中设置正确的阈值。您应以数小时为周期运行基准测试,借此反映临时性网络突发容量的出现频率与潜在需求。
Amazon ElastiCache 与 Amazon CloudWatch 提供多项主机层级的指标以监控网络利用率,类似于 Amazon Elastic Compute Cloud (Amazon EC2)实例。NetworkBytesIn 与 NetworkBytesOut 分别代表主机已经从网络处读取、以及发送至网络处的字节数。NetworkPacketsIn 与 NetworkPacketsOut 则分别代表在网络上接收及发送的数据包数。
在定义集群的网络容量之后,您可以借此映射并建立最高网络利用率预期峰值。此峰值不应高于所选节点类型的网络容量。每种节点类型都提供一定的突发容量,但我们建议您预留这部分额外容量以应对流量的意外增加。
根据您所定义的最高利用率,您可以创建 Amazon CloudWatch 警报,确保在网络利用率高于预期或接近此限制时发送电子邮件通知。
如果您的网络利用率持续增加并触发了网络警报,则应采取必要措施以添加更多网络容量。要确保调整正确,您需要确定导致网络利用率提高的因素。您可以使用 Amazon CloudWatch 指标来检测操作强度的变化,并在读取或写入操作类别中对这种波动进行分类。
如果网络利用率的提高源自读取操作,请首先确保使用一切现有读取副本处理读取操作。您可以在配置禁用集群模式下对 Redis 客户端库中使用 ElastiCache 读取器端点,也可以在启用集群模式下使用 Redis READONLY 命令。如果您已经在读取副本中执行读取操作,则可以在副本组或分片当添加更多节点(最多支持五个读取副本)。
如果网络利用率提高源自写入操作,则需要为主节点添加更多容量。在禁用集群模式的场景下,您可以直接将主节点扩展为更大的节点类型。在启用集群模式时,同样可以执行这一纵向扩展操作。
另外,启用集群模式时,您还可以使用另外一种读取及写入用例扩容方法。此方法将添加更多分片并执行横向扩展,确保每个节点只负责数据集中的部分较小子集,由此保证每个节点的网络利用率保持在较低水平。
尽管横向扩展能够解决大部分网络相关问题,但这里还是要讨论几种关于高热度键的极端情况。所谓高热度键,是指访问特别频率、远超正常比例的特定键或键子集,因此导致单一分片可能需要承受高于其他分片的流量规模。如果这些键保留在同一分片上,则会带来很高的网络利用率。在这类罕见示例中,如果不变更现有数据集,则向上扩展方法往往比较适用。当然,您也可以重构数据模型以重新均衡网络利用率。例如,您可以复制字符串并拆分存储有多个元素的对象。
连接
Amazon CloudWatch 为构建集群连接提供两项指标:
CurrConnections – Redis 引擎所注册的并发连接及活动连接数。此指标派生自 Redis INFO 命令中的 connected_clients 属性。
NewConnections – 在特定时段内,Redis 已接受的连接总数,包括所有处于活动状态及关闭状态的连接。此指标同样源自 Redis INFO 命令。
要监控连接,我们主要需要关注 Redis 中的 maxclients 限制指标。Amazon ElastiCache 为该指标设定的默认值为 65000。换句话说,每个节点最多可以使用 65000 个并发连接。
CurrConnections 与 NewConnections 指标均可帮助检测并预防性能问题。例如, CurrConnections 的不断增加可能快速耗尽 65000 个可用连接。这类指标增加可能表示应用程序端出现了问题,且连接未能正确关闭,因此最终还是在服务器端占用了连接。除了调查应用程序的行为以解决问题之外,您也可以在集群中使用 tcp-keepalive 以检测并终止潜在的死对等连接。在 Redis 3.2.4 及更高版本中,默认的 tcp-keepalive 计时器时长为 300 秒。对于旧版本,默认情况下禁用 tcp-keepalive。您可以在集群的参数组中调整 tcp-keepalive 计时器。
对 NewConnections 的监控同样非常重要。请注意,最大客户端限制 65000 不适用于此指标,因为其衡量的是指定时间内创建的连接总数,而各项连接之间并不一定同时发生。在 1 分钟的数据采样期间,一个节点可能会收到 10 万个 NewConnections,但从未达到 2000 个 CurrConnections(同时连接)。在此特定示例中,工作负载并未达到 Redhis 需要介入的连接限制风险。但是期间发生的大量连接快速开启及关闭同样可能会影响到节点性能。创建 TCP 连接需要耗费几毫秒时间,这也属于应用程序在运行 Redis 操作时经常出现的额外有效载荷。
根据最佳实践的要求,应用程序应尽可能复用现有连接,以避免创建新连接并造成额外成本。您可以通过 Redis 客户端库(如果支持)使用适合当前应用程序环境的框架以建立连接池,也可以亲手动手从零开始创建连接池。
更重要的是,由于 TLS 握手会带来额外的时间与 CPU 使用率,因此在集群内使用 Amazon ElastiCache 传输加密功能时,请关注对新连接数量的控制。
复制
如果存在至少一个读取副本,则主节点需要向读取节点发送复制命令流。通过 ReplicationBytes 指标,您可以看到需要复制的数据量。尽管此指标代表副本组上的写入负载,但无法帮助我们了解副本运行状况的具体见解。为此,您可以使用 ReplicationLag 指标。此指标提供一项非常便捷的表示形式,用以表现副本与主节点之间的延迟。从 Redis 5.0.6 版本开始,此指标数据将以毫秒为单位进行捕捉。尽管比较罕见,但您可以通过监控 ReplicationLag 指标以检测潜在的问题,其中复制滞后的峰值将表明主节点或副本无法及时处理复制操作。一旦发生这类情况,您可能需要对副本执行完全同步。完全同步代表更为复杂的过程,需要在主节点上创建快照,并可能导致性能下降。您可以将 ReplicationLag 指标与 SaveInProgress 指标确定完全同步尝试。
严重的复制滞后趋势,往往源自写入操作过多、网络容量耗尽或者基础服务降级等问题。
对于禁用集群模式的单一主节点,如果您的写入活动强度过高,则需要考虑启用集群模式,借此将写入操作分散到多个分片及其关联的主节点之上。如果复制滞后源自网络容量耗尽,则请参考本文“网络”部分的步骤进行操作。
延迟
您可以使用一组 Amazon CloudWatch 指标来衡量命令的延迟,通过这些指标为每种数据结构计算总延迟。您可以使用 Redis INFO 命令中的 commandstats 统计信息计算出这项结果。
在以下图表中,我们可以看到 StringBasedCmdsLatency 指标,代表的是特定时间范围之内运行的、基于字符串的命令的平均延迟(以微秒为单位)。
![](https://static001.geekbang.org/infoq/d5/d5dd3c92ebfa905afafef95a3599d145.png)
此延迟不包含网络与 I/O 时间,这些属于 Redis 处理操作时耗费的时间。
如果 Amazon CloudWatc h 指标指示出特定数据结构的延迟有所增加,则可以使用 Redis SLOWLOG 来确定哪些具体命令的运行时间较长。
如果您的应用程序遇到高延迟,但 Amazon CloudWatch 指标指示 Redis 引擎级延迟很低,则应主要关注网络延迟。Redis CLI 提供一款延迟监控工具,适用于以隔离方式调查网络或应用程序问题(min , max 以及 avg 皆以毫秒为单位):
$ redis-cli –latency-history -h mycluster.6advcy.ng.0001.euw1.cache.amazonaws.commin: 0, max: 8, avg: 0.46 (1429 samples) — 15.01 seconds rangemin: 0, max: 1, avg: 0.43 (1429 samples) — 15.01 seconds rangemin: 0, max: 10, avg: 0.43 (1427 samples) — 15.00 seconds rangemin: 0, max: 1, avg: 0.46 (1428 samples) — 15.00 seconds range
min: 0, max: 9, avg: 0.44 (1428 samples) — 15.01 seconds range
最后,您还可以监控客户端当中是否存在可能影响应用程序性能、或者导致处理时间增加的活动。
Amazon ElastiCache 事件与 Amazon SNS
与您资源相关的各类 Amazon ElastiCache 日志事件(包括故障转移、扩展操作、计划内维护等),皆包含日期与时间、源名称、源类型以及描述。您可以在 Amazon ElastiCache 控制台上、使用 Amazon 命令行界面(Amazon CLI)的 describe-events 命令以及 Amazon ElastiCache API 轻松访问这类事件。
![](https://static001.geekbang.org/infoq/a1/a1113610d1baa9d862e27423dcf1c50f.png)
监控事件可以帮助您随时了解集群的当前状态,并根据事件采取必要的措施。尽管 Amazon ElastiCache 事件可以通过多种方式获取,但我们强烈建议您在 Amazon ElastiCache 配置中使用 Amazon Simple Notification Service (Amazon SNS)发送重要的事件通知。
在将 Amazon SNS 主题添加至 Amazon ElastiCache 集群中时,与此集群相关的所有重要事件都将被发布至 Amazon SNS 主题当中,并可通过电子邮件进行发送。
在配合集群使用 Amazon SNS 时,您还可以通过编程方式对 ElastiCache 事件采取措施。例如,Amazon Lambda 函数可以订阅 Amazon SNS 主题并在检测到特定事件时自动运行。
总结
在本文中,我们讨论了 Amazon ElastiCache Redis 资源监控方面的常见挑战与相关最佳实践。借助本文中提到的知识,您现在可以轻松检测、诊断并维护 Amazon ElastiCache Redis 资源。
本篇作者
![](https://static001.geekbang.org/infoq/c6/c6fa270ae10a70529c12d722800fa65d.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
Yann Richard
Amazon ElastiCache 解决方案架构师
他的个人目标是在次毫秒级内完成数据传输,并在 4 小时之内完成马拉松。
![](https://static001.geekbang.org/infoq/5f/5f625c281cde5ea3a6b21f6fd11a6ff6.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
![](https://static001.geekbang.org/infoq/8e/8e57d5bdb2f39bbb02b0a378ab4c8e77.gif)
评论