作者:啃唯

Memcached 简介

Memcached 是什么?

Memcached 是一个免费开源、高性能、分布式内存对象缓存系统,支持将任意数据类型的 chunk 数据以键值对的方式存储。本质上 Memcached 是通用于所有的应用的,但最初用于存储被经常访问的静态数据,减轻数据库负载来加速动态 Web 应用程序。

统一观测丨使用 Prometheus 监控 Memcached 最佳实践_数据库

Memcached 特点

  • 内存存储
    Memcached 的所有数据都存储在内存中,与 PostgreSQL、MySQL 等持久化数据库相比存储过程无需重复往返磁盘,从而提供内存级别的响应时间(< 1ms),每秒可以执行十亿次操作。
  • 分布式
    分布式多线程架构使其易于扩展。支持将数据分散到多个节点中,从而通过向集群添加新节点来扩展容量。此外,Memcached 指定节点的多个核心,使用多线程的方式提高处理速度。
  • 键值存储
    Memcached 存储任意类型的数据,支持存储所有被经常访问的数据,适用于各种应用场景。不支持联合查询等复杂操作,以提高查询效率。
  • 简单性和可用性
    Memcached 提供各种语言框架的客户端程序,如 Java、C/C++、Go 等。

典型适用场景

适用场景
缓存

Memcached 的最初使用场景,存储网页静态数据(HTML、CSS、图片、会话等),这些数据读取次数多,修改次数少。用户在访问网页时可以优先返回内存中的静态数据,从而提高网站的响应速度。同其他的缓存一样,Memcached 不保证每次访问的数据都存在,而是提供了短期内访问加速的可能性。

数据库前端

Memcached 可作为高性能内存缓存,在系统中处于客户端与持久化数据库之间,以减少对较慢的数据库的访问次数,减少后端系统的负载,此时 Memcached 基本等于数据库的副本。在读取数据库时,首先检查 Memcached 中是否存在,若不存在则进一步访问数据库,若存在则直接返回。在写数据库时,写入 Memcached 后直接返回,后续在空闲时间时再写入数据库。

例如:在社交类 APP 中,常常有“最新评论”“最热评论”等功能,其需要大量的数据计算,并且调用频繁。若是仅用关系型数据库,则需要频繁地大量读写磁盘。在做出此类运算时,有大部分数据都会重复被使用,因此短暂地放在内存中可以大大加速整个过程。上次根据 1000 条评论计算了最热评论后,有 800 条被再次访问,它们能留在 Memcached 中。下一次计算最热评论时,只需再从数据库获取 200 条评论,节省了 80% 的数据库读写次数。

大数据量、高频读写场景

Memcached 是纯内存存储的数据库,其访问速度要远远高于其他持久化设备。此外,作为分布式数据库,Memcached 支持水平方向的扩展,将高负载请求分散到多个节点中,提供高并发的访问模式。

不适用场景
缓存对象过大

因为存储设计,官方推荐缓存的对象不要大于 1MB,Memcached 本身就不是为了存储处理庞大的多媒体(large media)和巨大的二进制块(streaming huge blobs)而设计的。

需要遍历数据

Memcached 在设计时仅支持少部分命令:set、put、inc、dec、del、cas,不支持对数据的遍历访问。Memcached 需要在常量时间内完成读写操作,但遍历数据的耗时会随着数据量的增大而增大,在这个过程中会影响其他命令的执行速度,不符合设计理念。

高可用性和容错性

Memcached 不保证缓存的数据是不被丢失的,相反,Memcached 存在命中率这一概念,即预期的数据丢失这一行为是可以接受的。当需要保证数据容灾备份、自动分区、故障转移等功能,最好将数据存储在持久性的数据库中,如:MySQL。

Memcached 核心概念

内存管理

如图为 Memcached 的内存管理方式:

  • Slab
    为了防止内存碎片的出现,memcached 使用了 slab 来管理。memcached 将内存分割为多个区域,称为 slab。在存储数据时,根据数据的大小选择 slab,每个 slab 只负责一定范围内的数据存储。例如:图中的 slab 只存储 1001~2000bytes 大小的值。Memcached 默认情况下下一个 slab 的最大值为前一个的 1.25 倍,这个可以通过修改 -f 参数来修改增长比例。
  • Page
    slab 由 page 组成,page 的固定大小有 1M,可以通过 -I 参数在启动时指定。如果需要申请内存时,Memcached 会划分出一个新的 page 并分配给需要的 slab 区域。page 一旦被分配在重启前不会被回收或者重新分配。
  • Chunk
    存储数据时,memcached 在 page 中分配一个固定大小的 chunk,并将值插入该 chunk。需要注意的是,不管插入数据的大小是多少,chunk 的大小总是固定的,摒弃每一个数据都会独占一个 chunk,不存在两个较少的数据存储在同一个 chunk 中。如果 chunk 不够用了,只能转到下一个 slab class 中的 chunk 中存储,造成空间浪费。

统一观测丨使用 Prometheus 监控 Memcached 最佳实践_数据_02

LRU

如图所示,Memcached 使用改良后的 LRU 机制来管理内存中的 item。

  • HOT
    因为 item 可能表现出很强的时间局部性或非常短的 TTL(生存时间)。因此,item 永远不会在 HOT 内发生移动:一旦某个 item 到达队列尾部,如果该项目处于活动状态 (3 ) ,它将被移动到 WARM ,如果它处于非活动状态 (5),它将被移动到 COLD。
  • WARM
    充当扫描工作负载的缓冲区,例如网络爬虫读取旧帖子。从未被击中两次的 item 无法进入 WARM。WARM item 有更大的机会活过其 TTL,同时也减少了锁争用。如果尾部 item 处于活动状态,我们将其移动回头部 (4)。否则,我们将不活动的 item 移至 COLD (7)。
  • COLD
    包含活动最少的 item。非活动 item 将从 HOT (5) 和 WARM (7) 流向 COLD。一旦内存已满,item 就会从 COLD 的尾部移出。如果某个 item 处于活动状态,它将排队异步移动到 WARM (6)。在 COLD 出现突发或大量点击的情况下,缓冲队列可能会溢出,item 将保持非活动状态。在过载情况下,来自 COLD 的移动将成为概率事件,而不会阻塞工作线程。
  • TEMP
    作为新 item 的队列,其 TTL 很短(2)(通常为几秒)。TEMP 中的 item 不会被替换,也不会流向其他 LRU,从而节省了 CPU 和锁的争用。目前默认情况下未启用该功能。

crawl 同时从下到上通过 LRU 向后遍历每个爬虫 item。爬虫会检查它传递的每个项目,看看它是否过期,如果过期则回收。

统一观测丨使用 Prometheus 监控 Memcached 最佳实践_memcached_03

主要版本介绍

  • 1.6.0:支持外部 flash 存储、更多 protocol、网络优化
  • 1.5.0:优化 LRU 实现、存储优化
  • 1.4.0:支持 C、Java 等 client 实现,binary protocol
  • 推荐使用最新的稳定版本

监控关键指标

接下来介绍 Prometheus 监控开源 Memcached 的一些关键指标。

统一观测丨使用 Prometheus 监控 Memcached 最佳实践_数据_04

系统指标

运行状态

启动状态是监控 Memcached 最基础的指标,表示 Memcached 实例是否在正常运行,或是否重启。当 Memcached 停机时,对整个系统的功能影响可能不大,因为对数据的访问会提交到底层的持久化数据库中,但缺少了 Memcached 的缓存会使系统运行效率降低至少一个数量级。

检查 Memcached 启动时长能帮助验证 Memcached 是否重启。因为 Memcached 将所有数据放置在内存,所有当 Memcached 重启后缓存的所有数据将会丢失。此时 Memcached 的命中率会骤降,导致缓存雪崩的情况,同样会给底层数据库带来很大压力,且降低系统效率。

内存使用

Memcached 作为高性能缓存,需要充分利用节点的硬件资源来提供快速的数据存储和查询服务,如果节点的资源使用超过了预期或者达到了极限,可能会导致性能下降或者系统崩溃,影响业务的正常运行。Memcached 把数据放置在内存中,所以我们需要重点关注内存的使用率。

当 Memcached 的内存占用率过高,可能影响节点的其他运行任务。需要考虑 key 的设计是否科学、增加硬件资源等优化方案。

读写指标

读写速率

读写速率是 Memcached 集群性能的重要指标,如果读写延迟较高,则可能会导致系统响应时间长,节点出现高负载、系统出现瓶颈等问题。读写指标表示了 Memcached 的运行效率总览,如果发现读写延迟较高,运维人员可以需要关注其他监控数据来排查问题。读写速率慢可能有多种原因,如命中率低、节点资源紧张等。针对不同的问题,需要采取不同的排查和优化措施来提高性能。

命令速率

Memcached 支持多种命令,如:set、get、delete、CAS、incr 等。监控各个命令的速率能得出 Memcached 瓶颈所在,当某种命令速率较低,导致了整体速率不高,可以考虑调整 item 存储策略、修改访问方式等方案提高 Memcached 性能。

命中率

缓存可以提高查询的性能和效率,减少对磁盘的读取次数,从而提高系统的响应速度和吞吐量。命中率是 Memcached 最重要的指标,命中指上层应用在获取某个数据时,发现能从 Memcached 中获取,而不需要访问底层的数据库。当命中率越高,表明大部分数据的访问都在内存中。

在使用缓存的系统中,有可能发生缓存雪崩、缓存穿透、缓存击穿等状况,导致在某一个时间段内命中率很低,此时系统的运行是很低的,因为大部分数据访问都落在了磁盘上,底层数据库压力很大。我们需要时刻关注命中率的变化情况,保证 Memcached 在系统中发挥着应有的作用。例如:网站某段时间的响应突然变得很慢,发现在该时间段命中率很低,再检查日志后发现:因为业务变化导致某个页面突然从低频访问变成高频访问,这是发生了缓存穿透的情况。解决命中率低的问题需要结合其他的指标来分析,如下文的 slab 指标。

Slab 指标

作为键值数据库,Memcached 将内存中的一对键值称为 item。了解 item 在 Memcached 中的存储情况,能够优化其内存的使用效率,并提高命中率。

Item 存储

item 的存储状态一般监控:Memcached 存储的 item 总量、回收的 item 总量、驱逐的 item 总量。通过观察 item 总量的趋势可以看到 Memcached 存储的压力,以及使用 Memcached 应用的存储模式。

驱逐和回收的区别是:当需要驱逐 item 时,Memcached 会查看 LRU 尾部周围的一些 item,寻找可以回收的过期 item,复用其内存空间,而不是驱逐真正的尾部。

Slab 使用情况

根据 Memcached 的设计思路,每个 slab 存储的 item 大小都相同,并且每个 item 独占一个 chunk,这是为了提高内存利用率。然而在使用过程中,这样的设计仍有优化空间。

Memcached 钙化是容易出现的一种问题。当内存达到 Memcached 限制的时候,服务进程会执行一系列的内存回收方案,但是,不管是什么内存回收方案,回收的大前提就只有一种:只回收与即将写入数据写入数据块一致的 Slabs。

例如:我们之前存储了大量大小为 64Kb 的 item,现在又需要存储大量大小为 128Kb 的 item。若内存的额度不够,且这些 128Kb 的 item 在不断地更新,为了存储新的数据 Memcached 只能选择其他 128Kb 的 item 驱逐。我们发现,原有的 64Kb 的 item 一直不被驱逐,在过期之前不停地占用内存空间,导致空间浪费,最终导致命中率降低。

要解决钙化的问题,就需要了解各个 slab 中 item 的分布指标。我们提供此类监控,观测 slab 之间存储 item 数量的对比。若发现某几个 slab 存储 item 数量远高于其他 slab,可以考虑调整各个 slab 的大小。默认的 slab 大小增长因子为 1.25,也就是每个 slab 的容量都是前一个的 1.25 倍。通过调低增长因子,并设置 slab 的起始大小,使 item 均匀分布在各个slab中,能有效缓解钙化的问题,并提高内存使用效率。

LRU 指标

区域 Item 数

在 Memcached 的 LRU 中,每个区域都有着不同的功能。HOT 中的是最新被存储的 item,WARM 中的是比较热点的 item,COLD 的是即将过期的 item。了解各个区域的 Item 数量能对 Memcached 的状态有较深的理解,并提供调优方案。下面是一些例子:

HOT 区域 item 较少,其他区域 item 较多。表明新创建的 item 较少,Memcached 中的数据比较少被更新,系统中的数据以读为主。反之,HOT 区域 item 较多,表明新创建的 item 较多,此时系统以写为主。

WARM 区域 item 比 COLD 区域 item 多。此时 item 被命中情况较多,属于比较理想的情况。反之命中率较低,需要考虑优化。

移动 Item 数

Item 命中与否,会影响其在哪个 LRU 区域。基于 LRU 的设计思路,通过监控 item 在 LRU 区域移动的情况,可以得出数据访问的状态。以下是一些例子:

COLD 区域移动至 WARM 区域的 item 数增大。表明即将过期的 item 被命中,当该数值过大,表明某些冷门数据突然成为热点数据。需要关注此类情况防止命中率降低。

HOT 区域移动至 COLD 区域的 item 数较大。表明有大量的 item 被插入后就不再被访问,这些数据可能不需要被缓存,考虑直接存入底层数据库以缓解内存压力。

WARM 区域的 item 数较大。表明大量的 item 被插入后被访问,这类情况比较理想,Memcached 存储的数据是被经常访问的,此时命中率较高。

连接指标

连接状态

由于 Memcached 使用基于事件的架构,因此大量客户端通常不会减慢速度。当用户拥有数十万个连接的客户端时,Memcached 也能正常工作。但监控当前的用户连接数可提供 Memcached 工作状态的总览。

连接错误

Memcached 限制单个客户端连接可以为每个事件发出的请求数,在启用时用-R参数决定。在客户端超出此值后,服务器会优先处理其他客户端,然后再继续处理原始客户端请求。应当时刻监控是否发生这样的情况,保证客户端正常使用 Memcached。Memcached 默认最大连接数 1024,运维人员需要监控连接数不突破限制,影响正常功能使用。

指标详细定义

系统指标

指标名

指标说明

memcached\_process\_system\_cpu\_seconds\_total

进程的system CPU使用时间

memcached\_process\_user\_cpu\_seconds\_total

进程的user CPU使用时间

memcached\_limit\_bytes

存储大小

memcached\_time\_seconds

当前时间

memcached\_up

是否启动

memcached\_uptime\_seconds

启动时间

memcached\_version

版本

读写指标

指标名

指标说明

memcached\_read\_bytes\_total

server中read数据的总大小

memcached\_written\_bytes\_total

server中send数据的总大小

memcached\_commands\_total

server中按命令分类的所有请求总数

memcached\_slab\_commands\_total

slab class中按命令分类的所有请求总数

存储指标
slab存储指标

指标名

指标说明

memcached\_items\_total

存储item的总数

memcached\_items\_evicted\_total

被驱逐的item数量

memcached\_slab\_items\_reclaimed\_total

过期item的数量,以slab分类

memcached\_items\_reclaimed\_total

过期item的总数量

memcached\_current\_items

当前实例的item数量

memcached\_malloced\_bytes

slab page大小

memcached\_slab\_chunk\_size\_bytes

chunk大小

memcached\_slab\_chunks\_free

空闲chunk数量

memcached\_slab\_chunks\_used

非空闲chunk数量

memcached\_slab\_chunks\_free\_end

最新的page中空闲chunk数量

memcached\_slab\_chunks\_per\_page

page中chunk数量

memcached\_slab\_current\_chunks

slab class中chunk数量

memcached\_slab\_current\_items

slab class中item数

memcached\_slab\_current\_pages

slab class中page数

memcached\_slab\_items\_age\_seconds

自上次访问slab class中最近一个item以来的秒数

memcached\_current\_bytes

item实际占用大小

memcached\_slab\_items\_outofmemory\_total

触发out of memory error的item数

memcached\_slab\_mem\_requested\_bytes

slab中item存储大小

LRU存储指标

指标名

指标说明

memcached\_lru\_crawler\_enabled

LRU crawler是否启用

memcached\_lru\_crawler\_hot\_max\_factor

设置HOT LRU转为WARM LRU的闲置时期

memcached\_lru\_crawler\_warm\_max\_factor

设置WARM LRU转为COLD LRU的闲置时期

memcached\_lru\_crawler\_hot\_percent

slab留给HOT LRU的百分比

memcached\_lru\_crawler\_warm\_percent

slab留给WARM LRU的百分比

memcached\_lru\_crawler\_items\_checked\_total

LRU Crawler检查的item数

memcached\_lru\_crawler\_maintainer\_thread

拆分LRU模式和后台线程

memcached\_lru\_crawler\_moves\_to\_cold\_total

移入COLD LRU的item数

memcached\_lru\_crawler\_moves\_to\_warm\_total

移入WARM LRU的item数

memcached\_slab\_items\_moves\_to\_cold

移入COLD LRU的item数,以slab分类

memcached\_slab\_items\_moves\_to\_warm

移入WARM LRU的item数,以slab分类

memcached\_lru\_crawler\_moves\_within\_lru\_total

被crawler处理,在HOT、WARM LRU中打乱的item数

memcached\_slab\_items\_moves\_within\_lru

在HOT、WARM间被命中而交换的item数

memcached\_lru\_crawler\_reclaimed\_total

LRU中被LRU Crawler清理的item数

memcached\_slab\_items\_crawler\_reclaimed\_total

slab中被LRU Crawler清理的item数

memcached\_lru\_crawler\_sleep

LRU Crawler的间隔时间

memcached\_lru\_crawler\_starts\_total

LRU启动时间

memcached\_lru\_crawler\_to\_crawl

每个slab被crawl的最大item数量

memcached\_slab\_cold\_items

COLD LRU中的item数

memcached\_slab\_hot\_items

HOT LRU中的item数

memcached\_slab\_hot\_age\_seconds

HOT LRU中最老的item年龄

memcached\_slab\_cold\_age\_seconds

COLD LRU中最老的item年龄

memcached\_slab\_warm\_age\_seconds

WARM LRU中最老的item年龄

memcached\_slab\_items\_evicted\_nonzero\_total

明确设置了过期时间的item在过期前必须从 LRU 中删除的总次数

memcached\_slab\_items\_evicted\_total

被驱逐且从未取回的item总数

memcached\_slab\_items\_evicted\_unfetched\_total

过期且从未取回的item总数

memcached\_slab\_items\_tailrepairs\_total

特定 ID 的item需要取回的总次数

memcached\_slab\_lru\_hits\_total

LRU总命中数

memcached\_slab\_items\_evicted\_time\_seconds

自上次访问该slab中最近被驱逐的item起的秒数。

memcached\_slab\_warm\_items

WARM中的item数,以slab分类

连接指标

指标名

指标说明

memcached\_connections\_total

接受连接总数

memcached\_connections\_yielded\_total

因触及 memcached -R 限制而运行的连接总数。

memcached\_current\_connections

打开连接数

memcached\_connections\_listener\_disabled\_total

触及限制的连接总数

memcached\_connections\_rejected\_total

拒绝连接数,触发memcached -c 限制

memcached\_max\_connections

client限制大小

监控大盘

我们默认提供了 Memcached Overview 大盘。

总览

在该 panel 能看到Memcached运行时需要重点关注的指标,在检查 Memcached 状态时,首先查看总览中是否有异常状态,再检查具体的指标。

  • 启动状态:绿色代表正常运行,即能查询到 Memcached 运行指标;红色表示 Memcached 异常
  • 内存使用率:使用红黄绿颜色提示,内存使用率在 80% 以下时为绿色,80%~90% 为黄色,90% 以上为红色
  • 命中率:使用红黄绿颜色提示,在 10% 以下为红色,10%~30% 为黄色,30% 以上为绿色

统一观测丨使用 Prometheus 监控 Memcached 最佳实践_数据库_05

性能

在以下 panel 能看到 Memcached 的运行速度,分为以下三类。

  • QPS:每秒能处理所有命令的总数
  • 命令速率:每秒能处理命令的数量,分为 set、get 等 Memcached 命令
  • 读/写速率:每秒能速写的数据量

统一观测丨使用 Prometheus 监控 Memcached 最佳实践_数据_06

命中率

命中率是需要重点关注的指标,通过以下三个 panel 能详细了解 Memcached 的命中状态。

  • 总命中率:整体的命中率趋势
  • 命令命中率:各命令的命中率趋势,一般重点关注 get 的命中率
  • 命中 slab 区域:命中的 slab 在哪个区域

统一观测丨使用 Prometheus 监控 Memcached 最佳实践_数据_07

item

item 表示 Memcached 的存储状态,通过以下 panel 检查 Memcached 的内存使用状态。

  • item 总数:Memcached 存储 item 的趋势
  • 各 slab 的 item 数:不同 slab 的 item 存储数量变化
  • slab 使用率、slab 大小:各 slab 的使用状态以及对应大小,能通过这些指标检查钙化问题
  • LRU 间 item 移动速率:通过检查 item 的移动情况,检查 Memcached 的热点、命中率问题
  • 回收、过期、驱逐 item 数:当内存不足时,必须有 item 要移出 Memcached

统一观测丨使用 Prometheus 监控 Memcached 最佳实践_数据库_08

统一观测丨使用 Prometheus 监控 Memcached 最佳实践_数据库_09

内存

内存是 Memcached 的重点关注硬件资源,通过该 panel 能了解 Memcached 的内存使用情况:

  • 最大内存:提供内存整体状态
  • 内存使用率/使用量:分析内存使用的趋势
  • OOM 次数:检查是否因为内存不足造成 OOM

统一观测丨使用 Prometheus 监控 Memcached 最佳实践_memcached_10

网络

尽管 Memcached 提供高并发无损耗的支持,但网络资源不是无限的,需要随时关注:

  • 最大连接数以及连接使用率:查看趋势以及仪表盘检查连接数是否符合预期
  • 拒绝连接数:检查是否发生过拒绝连接的情况,保证客户端正常运行
  • 请求过多连接数:检查该趋势以保证没有异常客户端

统一观测丨使用 Prometheus 监控 Memcached 最佳实践_memcached_11

句柄

句柄是系统指标,涉及到网络连接等资源。

统一观测丨使用 Prometheus 监控 Memcached 最佳实践_数据_12

关键告警项规则

在对 Memcached 进行告警规则配置时,我们推荐基于以上采集得到的指标,从以下几个方面进行告警规则的配置,分别是运行情况、资源使用情况、连接使用情况。一般来说,我们默认生成影响 Memcached 正常使用的告警规则,优先级较高。读写速率等与业务相关的告警则由用户自定义。以下是一些推荐的告警规则。

运行情况

Memcached 停机

Memcached 停机是 0/1 阈值的告警规则。一般来说,部署在 ACK 等阿里云环境的 Memcached 服务具有高可用的能力,当一个 Memcached 实例停止,其他的实例会继续工作。有可能出现程序错误,导致 Memcached 实例无法重新部署,这是非常严重的情况。我们默认设定 5 分钟内 Memcached 无法恢复的告警。

Memcached 重启

对于其他的服务,实例重启不算问题。然而 Memcached 是典型的有状态服务,它的主要数据都存储在内存中。当实例被重启,缓存的数据将全部丢失,此时命中率下降,导致系统性能很差。因此我们推荐监控 Memcached 的重启告警,当重启发生后找到对应问题,防止该情况再次出现。

资源使用情况

内存使用率

当内存使用率过高,Memcached 无法正常运行。我们设定的内存使用阈值为:危险值 80%,告警值 90%。当内存使用率为 80% 时,节点高负荷运转,但一般不影响正常使用。当内存长时间使用率为 90% 时,将发出告警,提示运维资源紧缺,尽早处理。

item 触发 OOM

当内存使用量超过节点总内存时,内存不足 (OOM) 情况可能会导致数据完全缓存刷新,从而中断您的应用程序和业务。当节点内存利用率指标接近 100% 时,实例更有可能遇到 OOM 情况。我们设置了 0/1 阈值的告警,一旦出现 OOM 则立刻告警。

连接使用情况

拒绝连接

一般情况下连接数的增多不影响 Memcached 的运行,除非突破了最大连接数限制,此时客户端无法正常获取 Memcached 服务。我们设置了 0/1 阈值的告警,一旦出现拒绝连接的情况,立刻告警,保证客户端正常运行。

连接请求数过多

我们设置了 0/1 阈值的告警,一旦出现连接请求数过多的情况,立刻告警,保证客户端正常运行。在这样的情况下,Memcached 暂时不接受该连接的命令。

相关实践示例

命中率低

命中率低有各种各样的原因,我们需要联系多个指标进行排查。

检查内存使用率
  • 原因: 当内存资源不够,Memcached 无法存储足够多的 item,某些应当是热点的 item 因为内存不足的原因被驱逐。
  • 排查方法: 检查大盘中的内存使用率 panel,检查内存使用率是否一直都很高。检查告警历史,查看是否提示内存资源不足。
  • 解决方法: 增加对应节点的内存资源。
检查 item 情况
  • 原因: 内存不足导致的命中率低同样会体现在 item 的相关指标。此外,缓存 item 设计是否合理同样可以通过 item 指标得出。
  • 排查方法: 分别检查 item 总数、item 驱逐数、item 回收数,正常情况下,item 驱逐数和 item 回收数应当占 item 总数比较小的比例。
  • 解决方法: 增加对应节点的内存资源;设计缓存的策略,尽量存储热点数据。
检查 LRU 各区域 item 情况
  • 原因: 存储的 item 有可能不是以后需要用到的;某些冷门数据突然成为热点数据。
  • 排查方法: 检查 LRU 区域 item 的指标。当 HOT 区域移动至 COLD 区域的 item 数较大。表明有大量的 item 被插入后就不再被访问。COLD 区域移动至 WARM 区域的 item 数增大。表明即将过期的 item 被命中,当该数值过大,表明某些冷门数据突然成为热点数据。
  • 解决方法: 设计缓存的策略,尽量存储热点数据。优化策略防止数据在冷门和热点两种状态切换。

内存使用率高

检查内存使用趋势

  • 原因: 节点的内存使用率一直是足够的,但是某些时间段流量突增,导致内存使用率突然上涨。
  • 排查方法: 检查大盘中内存使用率的趋势,查看是否有内存使用率突然上涨的情况。在结合上涨时间段检查业务流量。
  • 解决方法: 设置 memcached 实例横向扩展的策略,使其节点资源具有弹性。

检查 slab 使用率

  • 原因: 发生了存储钙化的问题,某些 slab 区域 item 一直占用内存。
  • 排查方法: 检查各 slab 区域的使用情况,是否有某几个特定 slab 存储量很大,某些 slab 存储量很小。
  • 解决方法: 调整 slab 大小策略:初始 slab 大小、slab 大小增长因子,尽量让 item 平均分布在各 slab 中。

监控体系搭建

自建 Prometheus 监控 Memcached 的痛点:

通常我们当前的 Memcached 都是部署在 ECS 上,因此自建 Prometheus 监控 Memcached 时,我们将面临的典型问题有:

  1. 由于安全、组织管理等因素,用户业务通常部署在多个相互隔离的 VPC,需要在多个 VPC 内都重复、独立部署 Prometheus,导致部署和运维成本高。
  2. 每套完整的自建监控系统都需要安装并配置 Prometheus、Grafana、AlertManager 等,过程复杂、实施周期长。
  3. 缺少与阿里云 ECS 无缝集成的服务发现(ServiceDiscovery)机制,无法根据 ECS 标签来灵活定义抓取 targets。如果自行实现类似功能,则需要使用 Golang 语言开发代码(调用阿里云 ECS POP 接口)、集成进开源 Prometheus 代码、编译打包后部署,实现门槛高、过程复杂、版本升级困难。
  4. 常用开源 Grafana Memcached 大盘不够专业,缺少结合 MSSQL 原理/特征和最佳实践进行深入优化。
  5. 缺少 Memcached 告警指标模板,需要用户自行研究、配置告警项,工作量大。

用阿里云 Prometheus 进行自建 Memcached 的监控:

  • 登录 ARMS 控制台 \[ 1]
  • 在左侧导航栏选择 Prometheus监控 > Prometheus 实例列表,进入可观测监控 Prometheus 版的实例列表页面。
  • 单击目标 Prometheus 实例名称,进入集成中心页面。
  • 单击 Memcached 卡片的安装。

统一观测丨使用 Prometheus 监控 Memcached 最佳实践_memcached_13

  • 配置相关参数,并单击确定,完成组件接入。

统一观测丨使用 Prometheus 监控 Memcached 最佳实践_memcached_14

已接入的组件会显示在集成中心页面的已安装区域。单击该组件卡片,在弹出的面板中可以查看 Targets、指标、大盘、告警、服务发现配置、Exporter 等信息。

统一观测丨使用 Prometheus 监控 Memcached 最佳实践_memcached_15

如下图所示,您可以看到目前可观测监控 Prometheus 版提供的关键告警指标:

统一观测丨使用 Prometheus 监控 Memcached 最佳实践_数据库_16

您可以在大盘页签,单击大盘缩略图,查看对应 Grafana 大盘。

统一观测丨使用 Prometheus 监控 Memcached 最佳实践_memcached_17

您可以面板中单击告警页签,查看 Memcached 的 Prometheus 告警。您还可以根据业务需求新增告警规则。创建 Prometheus 告警规则的具体操作,请参见 Prometheus 告警规则 \[ 2]

统一观测丨使用 Prometheus 监控 Memcached 最佳实践_数据库_18

自建 Prometheus 与阿里云可观测监控 Prometheus 版监控 Memcached 优劣对比:

统一观测丨使用 Prometheus 监控 Memcached 最佳实践_数据_19

参考链接:

\[1] <https://memcached.org/about>

\[2] <https://memcached.org/blog/modern-lru/>

\[3] <https://www.scaler.com/topics/aws-memcached/>

相关链接:

\[1] ARMS 控制台

<https://account.aliyun.com/login/login.htm?oauth_callback=https%3A%2F%2Farms.console.aliyun.com%2F#/home>

\[2] Prometheus 告警规则

<https://help.aliyun.com/zh/arms/prometheus-monitoring/create-alert-rules-for-prometheus-instances#task-2121615>