ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Memcached stats命令全解析:从基础字段到内存分配排查实战

Memcached stats命令全解析:从基础字段到内存分配排查实战 1. 先把话说在前面为什么你必须学 stats 命令聊到 Memcached 排查大部分人第一反应是看监控面板、看缓存命中率曲线真正落到命令行敲stats的人反而少。我在生产环境踩过几次坑之后越来越觉得stats命令才是 Memcached 运维里最被低估的利器。它不需要任何额外组件一条命令就能把整个实例的运行状态、内存分配、对象数量、淘汰情况全部拉出来比很多可视化监控都来得真实、来得及时。严格来说stats不是单条命令而是一族命令包括基础的stats、stats settings、stats slabs、stats items、stats cachedump、stats sizes等等。每条命令回答的问题都不一样实例整体状态怎么样、配置参数实际生效没生效、内存分得合不合理、哪些 key 是僵尸数据、当前热点数据规模有多大。学完这一族命令排查 Memcached 问题时你基本能做到不慌不忙——先stats看整体再stats settings核对配置接着stats slabs和stats items定位内存和淘汰问题最后用stats cachedump去抽查具体数据。这一套流程走下来绝大多数线上异常都能定位到根因。这篇博文面向三类人刚接触 Memcached、对着命令手册一头雾水的入门运维已经部署了 Memcached 但只靠监控面板看数据的开发以及正在排查线上缓存异常、需要快速定位问题的工程人员。我尽量把每个字段讲透不只是告诉你它“是什么”更重要的是告诉你“异常时它可能说明什么”。命令本身很简单难的是看懂数字背后的含义。2. 动手之前先搞定进入 Memcached 命令行的三种方式stats命令要发挥作用你得先能跟 Memcached 对话。Memcached 默认监听 TCP 11211 端口走的是自己的文本协议说白了就是你能用任意一个 TCP 客户端连上去发命令、收响应。常见的连接方式有三种。2.1 用 telnet 直连最经典的方式内存里敲几行命令就能看结果telnet 127.0.0.1 11211连上之后直接敲stats回车响应是一堆STAT开头的键值对最后一行是END。如果你在 Windows 上遇到telnet命令找不到那是系统默认没装 Telnet 客户端去“控制面板 - 程序 - 启用或关闭 Windows 功能”里勾选“Telnet 客户端”即可。2.2 用 ncnetcat更顺手telnet 交互式体验其实有点别扭尤其你想在脚本里跑stats抓结果时。更推荐用 ncprintf stats\nquit\n | nc 127.0.0.1 11211或者用 bash 的/dev/tcp虚拟设备不需要装任何额外工具exec 3/dev/tcp/127.0.0.1/11211 printf stats\nquit\n 3 cat 32.3 程序里怎么调用如果你是开发者想在自己的服务里探一下某个 Memcached 实例的状态不用绕弯子直接用客户端的 API。PHP 的Memcached::getStats()、Python 的pymemcache.Client.stats()、Go 的github.com/bradfitz/gomemcache里遍历服务器逐个Stats()都能拿到和命令行一样的字段。这个在排查多实例部署时特别有用不用挨个 telnet 上去。需要注意的是Memcached 默认配置允许来自任意地址的访问这属于历史遗留设计。生产环境务必加-l 127.0.0.1只监听本机或者用防火墙限制 11211 的访问来源。如果外网能直接连到你的 11211别人不用入侵你的业务系统先把你缓存里的数据拖走再说这个不是危言耸听。3. 基础 stats一整块实例状态的“体检报告”连上之后第一条命令就是stats不带任何子参数。它会返回当前实例所有可访问的统计指标。这里我不打算逐个字段复读手册而是挑出在实战中真正需要盯的字段讲讲它们能说明什么问题。3.1 先看几个“时长”类字段instance 活了多久响应里的uptime字段是实例自启动以来经过的秒数time是当前服务器时间戳version是版本号。这三个字段要合在一起看。有一次我排查一个诡异的“缓存变慢”问题一查uptime发现实例才跑了不到 200 秒说明 Memcached 刚被 OOM 干掉又被守护进程拉起来了——监控指标曲线看半天没看出名堂其实实例根本就是刚重启的“新家伙”。所以看到任何异常指标先确认uptime是否足够长排查思路会清晰很多。3.2 命中率相关字段命中率低不要慌先分场景get_hits和get_misses是 Memcached 收到 get 请求后命中和未命中的累计次数。命中率就是get_hits / (get_hits get_misses)。很多文章直接说“命中率低于 90% 就不正常”但我想给个补充视角命中率低不一定代表缓存配置有问题要结合业务场景判断。比如业务刚上线缓存里没有数据冷启动时期命中率低是正常的再比如缓存的数据天然就不是高频访问型比如后端回源也很快那命中率低也未必是问题。关键要看命中率的趋势是否稳定、是否随流量正常波动。更值得关注的字段其实是cmd_get和cmd_set的比例。如果你发现cmd_set远远大于cmd_get说明业务在疯狂写缓存但读得非常少——这种场景下缓存大概率没起到应有的作用很可能是代码逻辑把缓存当临时存储用了。3.3 连接相关字段不是连接数越多越好curr_connections是当前打开的连接数total_connections是实例启动以来累计接纳的连接数。有个新手容易踩的坑一看curr_connections很高就觉得有问题。实际上Memcached 对每个 TCP 连接内部会维护一个结构体连接数太多确实会占用内存但判断标准要看curr_connections相对maxconns的比例。默认maxconns是 1024如果连接数持续贴着上限客户端拿不到连接就会超时这时候才需要认真处理。rejected_connections部分新版才有表示因超过最大连接数而被拒绝的连接数这个值只要在增长说明客户端连接池配置不合理的可能性非常大。3.4 线程相关字段确认是不是多线程在干活threads字段显示当前 worker 线程数默认是 4可以通过-t参数调整。大多数场景下 4 个线程足够用了因为它处理的是内存操作不像磁盘 IO 容易卡。但如果你的日志里频繁出现Memcached: connection reset by peer同时 CPU 使用率又很高可以尝试把线程数调高到 8 或 16实测下来对高并发读场景有一定改善。3.5 字节类字段估算内存占用时别忽略连接结构bytes是当前存储数据占用的字节数bytes_read和bytes_written是网络 IO 累计读写的字节数。这里要特别说明bytes只是数据本身占用的内存不算 Memcached 自身管理元数据和连接结构的开销。实际每个 item 还会带着 key、标志位、过期时间等元数据所以当你看到bytes离limit_maxbytes也就是最大内存上限通过-m参数设置还很远时不代表内存一定安全。真实内存占用会明显高于bytes。我在排查一次内存溢出问题时bytes显示只用了 3GB但实际进程已经吃掉 5GB 了。3.6 淘汰类字段这三兄弟要连起来读evictions、reclaimed、expired_unfetched这三个字段是判断缓存健康度的关键放在 3.7 细讲。evictions是内存不足时被强制淘汰的 item 数量。正常情况下这个值会缓慢增长。但如果它在短时间内暴涨意味着内存容量触及上限并且有大量新数据写入把旧数据挤了出去。你可能会问缓存本来就有淘汰机制淘汰不是正常的吗问题在于淘汰意味着该数据后续访问时必然 miss如果淘汰的数据恰好是热点数据就会引发缓存雪崩级别的一连串回源压力。3.7 三个容易看走眼的字段curr_items、total_items、expired_unfetchedcurr_items是当前存储的 item 总数total_items是启动以来累计写入的 item 总数。注意total_items包括了被写入又淘汰掉的所以这个值只涨不跌。如果你发现total_items增长非常快但curr_items保持稳定说明数据处于高频写入高频淘汰的状态需要思考是不是 key 设计得太碎、TTL 设置得太短。expired_unfetched是“已过期但从未被读取过”的 item 数量。这个字段特别有意思它反映的是那些写入之后压根没人读的数据属于纯浪费。如果这个值占curr_items的比例很高说明业务代码里有一批没有被消费的“死数据”排查思路是去检查写入缓存的 key 是否真的被读取过。3.8 哈希表相关字段hash_power_level和hash_byteshash_power_level是哈希表的幂次hash_bytes是哈希表占用的内存。Memcached 会自动扩容哈希表。当你curr_items很多但hash_power_level很低时理论上查找速度会变慢不过 Memcached 对这种场景做过多轮优化实际影响有限。我提它的目的在于有些“性能问题”其实是哈希表在扩容时短暂锁表导致的延迟尖刺基本面查这个字段能帮你快速排除。提示基础stats命令返回的字段在不同版本之间略有差异——比如老版本没有rejected_connections和expired_unfetched。如果你在对比不同版本实例的字段先确认版本别拿着新版字段去比旧版数据容易得出错误结论。实战中我通常会写一个简化版脚本把stats输出解析成可读格式。这就涉及到几乎所有 Memcached 命令的统一格式响应是STAT 字段名 值以END结束。解析时逐行处理即可。为了验证命中率脚本里算了get_hits/(get_hitsget_misses)为了看内存余量算了limit_maxbytes - bytes。这个小脚本比很多监控面板直观得多监控面板的采样周期内如果实例重启过很多指标就失真了。4. stats settings核对“你以为的配置”和“实际生效的配置”配置参数这件事我吃过不止一次亏。启动 Memcached 时敲的参数你以为生效了实际上可能因为多个启动脚本互相覆盖、环境变量优先级等问题最终跑起来的配置跟你预期完全不一样。stats settings就是用来核对运行时真实配置的它把当前实例有效配置项全部拉出来。4.1 核心内存参数maxbytes和factormaxbytes对应-m参数单位是字节。比如你想设置 512MB启动参数写-m 512这里就显示 536870912。factor对应-f参数默认是 1.25它决定 slab 内存分配时各个 class 之间的内存块大小增长倍数后面讲stats slabs时你会看到它的实际作用。4.2 过期与淘汰策略参数maxbytes决定了总容量但具体怎么淘汰要看eviction策略。stats settings里的evictions字段注意跟基础 stats 里的 evictions 字段重名但含义不同settings 里的是配置策略值显示当前淘汰策略默认是lru也就是当内存满时按 LRU 顺序淘汰。如果你改成unfetched或notransfer优先级逻辑会变生产环境默认lru基本是正确的选择不太需要动。expirezero_holds_empty是一个很容易被忽略的字段当设置为 true 时TTL 为 0永不过期的 item 在内存压力下即使变成空也不会被立即回收。这个配置直接影响stats里curr_items和expired_unfetched的数值关系排查“内存没降下来”的问题时需要关注。4.3 连接与协议参数maxconns、tcpport、udpport这些很好理解。binding_protocol显示当前协议是auto-negotiation、binary还是ascii。老的客户端只支持 ascii 协议新的二进制协议性能更优。这里的坑在于如果你在配置文件里指定了二进制协议但客户端库用的是老版本只支持 ascii连接会失败或者表现怪异。这时候stats settings一查一目了然。4.4 从排查场景反推 settings 使用技巧举个例子线上缓存 miss 率突然飙升你想确认是不是缓存服务被重启了最简单的办法是看stats的uptime和time但如果你想确认是不是启动参数里的-m被人改小过就必须stats settings看maxbytes。有一次我的经历是明明部署文档里写了-m 2048结果maxbytes显示只有 268435456256MB一追查发现运维脚本里有一行旧配置覆盖了启动参数。这种问题如果不查运行时配置单靠看部署文档根本发现不了。stats settings还有一个常用场景是排查客户端超时问题。客户端连不上、读超时除了查网络还要确认服务端maxconns是不是太小、连接是否被拒绝。stats settings查完maxconns、stats查完curr_connections基本能定性。4.5 关于统计子命令的一个关键错误观念很多人以为stats settings里能看到统计功能开关。实际上Memcached 的统计收集机制不是“可开关”的而是常开的。统计本身对性能的影响很小主要是原子计数器增加所以不存在“为了性能关闭统计”这种操作。真正跟“开关”有关的是stats detail on/off它控制的是更细粒度的 per-slab 统计是否收集默认关闭。如果你需要看stats items的详细分布偶尔需要先开启 detail 模式但生产环境不建议长期开着因为会额外增加少量开销。5. stats slabs 和 stats items内存分配的“透视镜”这两条命令是排查内存问题时的核心工具但很多人把它们混为一谈。简单区分stats slabs以 slab class内存分块等级为维度告诉你每个等级的内存块分配了多少、用了多少stats items以 item 为维度告诉你每个 slab class 里有多少 item、过期情况、淘汰情况。两者要配合着看才能完整还原内存分配全貌。5.1 slab 机制Memcached 内存分配器是怎么工作的不理解 slab 机制看stats slabs会一头雾水。Memcached 为了避免频繁调用 malloc/free 造成内存碎片把内存按“块大小等级”预先切分。启动时-f指定增长因子默认 1.25也就是 96 字节、120 字节、150 字节……逐级增长。每个等级称为一个 slab class编号从 1 开始每个 class 内有多个 page默认 1MB 一个每个 page 又切分成若干固定大小的 chunk。用停车场来类比停车场划分了若干区域每个区域只停一种尺寸的车。来了一辆尺寸接近某一区域的车就停到该区域对应的车位上如果某个区域的车位满了后来的车只能去更大的区域找位置或者直接走人淘汰。这解释了为什么一个 key 只有 50 字节可能占用 96 字节的 chunk——存不下更小的 chunk 了这就是“内存浪费”的根源。stats slabs的每个 class 会返回若干字段其中几个关键字段chunk_size这个 class 内每个 chunk 的字节数。chunks_per_page一个 page 能切出多少个 chunk。total_pages分配给这个 class 的 page 数量。used_chunks已经被使用的 chunk 数量。free_chunks尚未分配出去的 chunk 数量。get_hits/get_misses针对这个 class 的命中情况。5.2 看懂 slab class 分配是否健康正常情况下不同大小的 key 会落在不同 slab class 里。如果某个 class 的free_chunks长期为 0而total_pages快速增长说明该尺寸的数据在大量写入。如果新增数据用光了所有 page就会触发 evictionstats items里对应 class 的evicted字段会增长。真正的判断技巧在于观察total_pages的分布是否与业务数据大小分布匹配。我有一个实际案例业务里大量存储 200 字节左右的小对象理论上应该集中在某个低编号 class但stats slabs显示高编号 class 占了大量 page低编号 class 的free_chunks却有很多空余。一查代码发现存储时顺手把数据序列化成了 JSON 字符串再加上一个很长的 key实际 item 膨胀到了好几 KB导致落在高编号 class 里。这解释了为什么内存老是不够用——数据本身的膨胀远比数量增长更致命。5.3 stats items过期和淘汰的细节都在这里stats items的输出按 slab class 分组格式类似STAT items:1:number 123。新版本还支持按 TTL 维度拆分统计。几个重点字段number该 class 内当前 item 数量。age该 class 内最老 item 存活时长秒。evicted该 class 内被淘汰的 item 累计数量。evicted_time最近一次淘汰距离现在多少秒。outofmemory因内存不足无法写入而被拒绝的操作次数。tailrepairsLRU 尾部修复操作次数这个属于比较深的领域正常情况忽略。这里有个关键认知stats items里的age能帮你判断冷热数据分布。如果有个 class 的age特别大比如几百秒甚至几千秒说明有一条长期不更新的数据躺在缓存里。如果业务预期是短缓存比如 TTL 30 秒但age却上千秒说明 TTL 没传对代码里可能把过期时间写成了 0永不过期。最常见的一个误判场景stats items显示某 class 的evicted在涨你以为是内存不足。但结合stats slabs看该 class 的total_pages未达到上限其他 class 还有充足空余。这种“局部淘汰”往往不是全局内存不足而是该尺寸类的 chunk 不够用其他 class 帮不上忙。加上-f的分配粒度限制这种不均衡其实很难完全避免。优化思路包括调整-f因子让分配更细或者在业务侧统一 key 和 value 的大小范围。5.4 从内存视角看什么时候该报警我自己的经验阈值是这样的evictions持续增长且每秒超过几十次——需要立即关注。outofmemory大于 0——说明有新数据因为内存不足写不进去对业务来说这是比淘汰更严重的问题。stats slabs显示某个 classfree_chunks几乎为 0 但其他 class 大量空闲——先考虑业务侧数据大小分布再决定是否调-f。stats items的age远大于业务 TTL——优先查代码里过期时间参数是否被忽略。可以做一个简化版的内存分配报告脚本把stats slabs和stats items合并起来按 class 输出“使用率、chunk 浪费率、淘汰数”再配合stats settings里的maxbytes算总占用率。这套东西跑出来比商业监控面板的“内存使用率”曲线更有诊断价值因为后者只告诉你“满了没满”前者能定位“哪里满的、为什么满的”。6. stats cachedump 和 stats sizes探查具体缓存的“显微镜”如果说前面几组命令是宏观体检stats cachedump和stats sizes就是微观切片。它们的场景是你想知道某个 slab class 里到底存了哪些 key、一个 key 大概占多大。6.1 stats cachedump 的基本用法与限制stats cachedump slab_class limit可以列出一个 slab class 里最多limit个 item 的 key、expiration time 和 value 大小。示例stats cachedump 5 100注意它的使用限制只支持 ASCII 协议二进制协议客户端不一定能直接调用只返回指定 slab class 的 item而且受限于 LRU 尾部扫描机制不是全量精确列表更接近“抽样”。所以它适合用来确认某个 class 里大概存了什么数据不适合用来做全量 key 枚举。实际场景里最有用的用法是“定位异常 key”当你发现某个 slab class 的evicted和outofmemory同时增长你很好奇是谁占的空间就可以stats cachedump看看。我排查过的一个案例某个 class 里全是带时间戳的日志 keyvalue 动辄几 KB导致该 class 频繁淘汰。stats cachedump把这个 class 的 key 列出来之后问题立刻清楚了——业务代码把缓存当日志存储使用了。6.2 从 cachedump 反推 key 设计是否合理stats cachedump还有一个更高级的用法验证 key 是否可预测。如果你发现某个 class 里大量的 key 带有极长前缀、带随机字符串或时间戳说明 key 设计不合理。这会导致两个问题一是 key 本身占用 chunk 空间二是前缀过于随机可能影响哈希分布的局部性从而影响查找效率。业务侧应尽量使用短且有意义的 key同时统一长度范围。6.3 stats sizes快速掌握 value 大小分布stats sizes输出当前各 item 大小分布。它会按 value 大小的幂次区间统计例如小于 64 字节、64-128 字节、128-256 字节等各个区间的 item 数量。这个命令在以下场景特别好用你想评估-f因子是否需要调整。如果大量数据集中在 128-256 字节区间你却用默认 1.25 的因子把 chunk 等级在 96、120、150、188 这种步长上切分就会有明显的空间浪费。调整方案可以是改用-f 1.10或者-f 1.05让 chunk 粒度更细减少小对象占用大 chunk 的浪费。不过要注意stats sizes在 Memcached 1.5.x 及更早版本里性能较差因为它需要遍历整个缓存项列表来计算分布对高并发实例影响明显。如果实例正在承担大量业务流量我不建议随手执行这条命令建议在低峰期使用或者只在测试环境验证。6.4 flush_all一个和统计强相关的“危险命令”排查过程中很多人会顺手执行flush_all清空缓存。这里面有个容易被忽略的事实flush_all并不是“立刻清空所有 item”而是通过“逻辑失效”机制——所有新写入的数据会替换旧数据但旧数据占用的内存不会瞬间释放而是等自然过期或被淘汰。所以你在执行flush_all之后立即看statscurr_items可能没有变成 0bytes也可能还有残值。这种现象让不少人误以为flush_all没生效其实是理解错了机制。更关键的是生产环境执行flush_all前必须确认自己对业务影响是否有完整预期。清空之后所有客户端请求都会 miss 并回源如果回源数据库扛不住那就不是缓存命中率问题而是整个服务雪崩的问题。我在一个高并发项目里见过一次误操作flush_all之后数据库连接数被打满直接引起线上故障。所以我的建议是排查阶段先用stats系列定位问题别动不动就 flush。7. 通用参数reset和detail on/off统计数据的“清零”与“加细”stats系列的累计计数器有个特点从实例启动开始累计。这带来一个问题你无法知道某个时段内的增量变化只能看整体累计。这时候stats reset就派上用场了。stats reset会把所有累计计数器如get_hits、get_misses、cmd_get、cmd_set、evictions等清零。注意curr_items、uptime、bytes这类“状态值”不会被清零因为它们不是累计值。实际操作建议清空之前先记录一份基线数据清空后过一段时间再拉数据这样能快速算出该时段内的真实增量。比如怀疑线上在某个时间点开始出现大量淘汰你可以在修复后执行stats reset过 15 分钟再拉一次看evictions涨了多少。这个方法比对比两个大时间点的差值来得更直观。stats detail on开启 per-key 级别的计数统计stats detail off关闭stats detail dump输出统计结果。这个功能主要用来定位“哪个 key 被访问最多”但开启后每台服务器上额外维护的信息会增加内存和 CPU 开销所以线上默认不开启。如果你需要做短期的热点 key 分析可以在低峰期开启跑一段时间分析完立刻关掉。8. 实操实录一套 stats 排查流程的完整推演空谈理论没意思我拿一个真实的排查场景完整走一遍流程你看完就能照搬。8.1 场景描述某在线服务高峰期缓存命中率从 96% 跌到 80%监控面板显示内存使用率接近 90%CPU 没明显异常。业务侧反馈有大量请求回源数据库数据库负载明显上升。8.2 排查步骤第一步连上实例执行基础stats先看uptime和version确认实例没被重启版本正常。第二步仔细读几个关键字段get_hits和get_misses计算命中率确认 80% 属实再看curr_items、bytes、limit_maxbytes确认内存确实接近满。第三步执行stats settings查maxbytes和maxconns确认配置未被改动。第四步执行stats slabs看各 class 的total_pages、used_chunks、free_chunks。发现编号较高对应 2KB-4KB 尺寸的 class 占用了大量 page且其free_chunks极低evicted在增长。而编号较低的 class几十到几百字节反而有大量空闲 chunk。第五步执行stats items定位具体 class 的evicted、evicted_time、age等字段确认淘汰集中发生在高编号 class且淘汰频繁程度在秒级。第六步执行stats cachedump抽查该 class 的 key 列表。发现里面有大量以“temp_report”为前缀、value 约 2KB 的数据。结合业务知识一核对这是业务侧某个后台任务把用户行为report缓存到了 Memcached且未设置 TTL导致数据长期占用内存无法释放最终把其他 class 的内存挤占影响正常缓存命中。8.3 问题根因与解决根因清楚了后台任务写入的“僵尸数据”占了内存大头触发了淘汰风暴。解决方式是给这类任务数据设置较短 TTL比如 10 分钟同时在代码层面做数据大小限制对已经存在的脏数据使用flush_all或通过程序逐步删除。实际操作中我们用stats reset清零计数观察 10 分钟后的evictions增量来验证修复效果明显看到淘汰量下降。这套流程从接到反馈到定位根因大概用了不到半小时效率远高于翻日志。9. 避坑速查表排查 Memcached 时最容易犯的错为了让这篇内容能直接当工具用我把这多年踩过的坑整理成一张速查表每条都对应一个具体命令和判断方法。现象可能原因用哪条命令验证规避要点命中率突然下跌实例重启、key 前缀变更、数据冷启动stats看uptime先确认 uptime别急着动缓存代码内存“没满”却大量淘汰单 class 内 chunk 耗尽全局内存却有富余stats slabsstats items关注各 class 分配不均而非只看总内存flush_all后curr_items没归零逻辑失效机制导致内存未立即释放stats看curr_items不要重复执行 flush_all连接数持续走高且拒绝增长客户端连接池未复用或配置过大stats看连接字段 stats settings看maxconns检查客户端连接池配置而不是盲目调高 maxconnsstats sizes执行后性能下降该命令遍历全部 item开销较大用stats slabs替代或低峰期执行高并发实例慎用配置了-m 1024但maxbytes不对有启动参数覆盖或环境变量干扰stats settings以运行时配置为准别信启动脚本stats cachedump看不到某些 key二进制协议或 LRU 尾部扫描限制确认调用端协议类型用 ASCII 协议工具执行这张表并不能覆盖所有情况但覆盖了大部分真实世界中会遇到的问题。收藏下来排查时对照着看能省下不少冤枉时间。10. 我个人最后想分享的一点经验Memcached 这套stats族命令的真正价值不在于让你能背出每个字段而在于它能让你用一种“立体”的视角去看缓存系统。初学者往往只看stats的基础字段仿佛那就能说明一切真正排过几次大故障之后你会发现组合使用stats settings、stats slabs、stats items、stats cachedump这四位一体才能构建出完整的问题叙事。而且这种能力跟用不用商业监控无关——就算监控平台能力再强你亲手在命令行里敲出来的数据永远是最真实的因为它没有采样丢失、没有时序偏差。还有一个很小的技巧想分享给看这篇内容的读者在做任何 Memcached 变更前后都设计一个“前后对照”习惯。变更前拉一次完整stats记录关键字段的值变更后再拉一次对比增量。这看起来很简单但能省掉大量“做了操作但不确定有没有生效”的纠结。我就靠这个习惯解决过不少配置没刷上去、修改没生效的疑难杂症。工具本身是死的怎么用、用得好不好全看平时的积累和习惯。
返回列表