memcached 的 stats items 命令用于查看 每个 slab 中 items 的详细信息,帮助分析缓存中键值对(items)的分布、年龄、淘汰情况等。它是排查 OOM、热点 slab、内存碎片等问题的重要工具。
命令格式
stats items
输出字段详解
典型输出示例:
STAT items:1:number 25
STAT items:1:number_hot 0
STAT items:1:number_warm 0
STAT items:1:number_cold 25
STAT items:1:age 3600
STAT items:1:mem_requested 1250
STAT items:1:evicted 0
STAT items:1:evicted_time 0
STAT items:1:evicted_nonzero 0
STAT items:1:outofmemory 0
STAT items:1:tailrepairs 0
STAT items:1:reclaimed 5
STAT items:1:crawler_reclaimed 0
...
STAT items:2:number 100
...
END
字段说明:
| 字段 | 说明 |
|---|---|
items:<slab_id>:number | 该 slab 中当前存储的 item 数量 |
items:<slab_id>:number_hot | 在 LRU hot 队列 中的 item 数(启用 -M 或温度分层时) |
items:<slab_id>:number_warm | 在 LRU warm 队列 中的 item 数 |
items:<slab_id>:number_cold | 在 LRU cold 队列 最尾部(最不活跃)的 item 数 |
items:<slab_id>:age | 该 slab 中 最老 item 的年龄(秒),即最久未被访问的 item 存活时间 |
items:<slab_id>:mem_requested | 该 slab 中所有 item 实际请求的内存字节数(不含 overhead) |
items:<slab_id>:evicted | 该 slab 累计 被驱逐(evicted)的 item 数 |
items:<slab_id>:evicted_time | 最近一次驱逐发生的时间戳(秒,自启动算起) |
items:<slab_id>:evicted_nonzero | 驱逐时 过期时间不为 0 的 item 数(即非永久存储被驱逐) |
items:<slab_id>:outofmemory | 该 slab 因空间不足拒绝写入的次数(OOM) |
items:<slab_id>:tailrepairs | LRU 尾部修复次数(内部维护) |
items:<slab_id>:reclaimed | 使用 已过期 item 的空间 存储新 item 的次数(节省内存) |
items:<slab_id>:crawler_reclaimed | 由 item crawler 回收的过期 item 数(需启用 -crawl) |
配合其他命令使用
- 查看 slab 分配情况:
stats slabs
- 看每个 slab 的
chunk_size、chunks_per_page、total_pages等。
- 查看整体统计:
stats
- 包含
total_items、curr_items、evictions等。
- 查看具体 slab 的内存使用:
stats slabs
# 结合 stats items 的 number 和 chunk_size 计算占用
实用分析技巧
1. 找“最老”的 item(判断缓存有效性)
stats items | grep age | sort -nk3
age越大,说明该 slab 数据很久没被访问,可能被浪费。
2. 找 OOM 的 slab
stats items | grep outofmemory | grep -v ":0$"
outofmemory > 0表示该 slab 内存不足,频繁拒绝写入。
3. 找被频繁驱逐的 slab
stats items | grep evicted | grep -v ":0$"
evicted高的 slab 说明热点数据被挤出,需调整大小或加内存。
4. 计算每个 slab 实际占用内存
stats slabs | grep "^STAT [0-9]\+:" | awk '{print $1,$3,$5}' > slabs.txt
stats items | grep "items:[0-9]\+:number " > items.txt
# 然后用脚本计算:number * chunk_size
示例脚本(计算每个 slab 占用)
#!/bin/bash
echo "SlabID Items ChunkSize UsedMB Age(s)"
stats items | grep -E "(items:[0-9]+:number|items:[0-9]+:age)" | paste - - | \
awk '{
split($1,a,":"); slab=a[2];
gsub(/.*:/,"",$2); items[slab]=$2;
gsub(/.*:/,"",$4); age[slab]=$4;
}
END{ for(s in items) print s, items[s], "", "", age[s] }' > /tmp/items.tmp
stats slabs | grep -E ":[0-9]+:chunk_size" | awk '{split($1,a,":"); print a[2], $3}' > /tmp/chunk.tmp
join /tmp/chunk.tmp /tmp/items.tmp | awk '{
used = $2 * $3 / 1024 / 1024;
printf "%-6s %-6s %8sB %8.2fMB %8s\n", $1, $3, $2, used, $5
}'
常见问题
| 问题 | 原因 | 建议 |
|---|---|---|
outofmemory 高 | slab 太小,装不下新 item | 调整 key 大小分布,或增加内存 |
evicted 高 | 内存不足,LRU 淘汰频繁 | 扩容或优化缓存策略 |
age 很大 | 数据长期不访问 | 设置合理 TTL,或分热冷缓存 |
reclaimed 高 | 很多过期 item 被复用 | 正常现象,说明 TTL 生效 |
相关命令总结
| 命令 | 用途 |
|---|---|
stats | 总体统计 |
stats slabs | 每个 slab 的分配详情 |
stats items | 每个 slab 中 items 的状态 |
stats sizes | (已废弃)曾用于查看 item 大小分布 |
如需查看 具体某个 item,可用 get key;如需清空 slab,可用 flush_all(慎用)。
官方文档参考:
https://github.com/memcached/memcached/wiki/Commands#stats-items
如有实际输出,我可以帮你分析具体问题。