Memcached监控与调试 #
一、监控概述 #
1.1 为什么需要监控 #
text
监控的重要性:
1. 性能优化
- 发现性能瓶颈
- 优化配置参数
2. 故障预警
- 提前发现问题
- 避免服务中断
3. 容量规划
- 了解资源使用
- 合理规划扩容
4. 问题排查
- 快速定位问题
- 提供诊断信息
1.2 监控指标 #
text
关键监控指标:
1. 性能指标
- QPS(每秒查询数)
- 命中率
- 响应时间
2. 资源指标
- 内存使用率
- 连接数
- CPU使用率
3. 业务指标
- 数据量
- 淘汰次数
- 错误率
二、stats命令详解 #
2.1 stats - 基本信息 #
bash
# 查看所有统计信息
stats
# 输出示例
STAT pid 1234 # 进程ID
STAT uptime 123456 # 运行时间(秒)
STAT time 1704067200 # 当前时间(Unix时间戳)
STAT version 1.6.29 # 版本号
STAT libevent 2.1.12-stable # libevent版本
STAT pointer_size 64 # 指针大小(位)
STAT rusage_user 123.456 # 用户态CPU时间
STAT rusage_system 234.567 # 内核态CPU时间
STAT max_connections 1024 # 最大连接数
STAT curr_connections 10 # 当前连接数
STAT total_connections 1000 # 总连接数
STAT connection_structures 20 # 连接结构数
STAT cmd_get 10000 # get命令次数
STAT cmd_set 5000 # set命令次数
STAT cmd_flush 10 # flush命令次数
STAT cmd_touch 100 # touch命令次数
STAT get_hits 8000 # 命中次数
STAT get_misses 2000 # 未命中次数
STAT delete_misses 100 # delete未命中次数
STAT delete_hits 50 # delete命中次数
STAT incr_misses 20 # incr未命中次数
STAT incr_hits 80 # incr命中次数
STAT decr_misses 10 # decr未命中次数
STAT decr_hits 40 # decr命中次数
STAT cas_misses 5 # cas未命中次数
STAT cas_hits 15 # cas命中次数
STAT cas_badval 3 # cas失败次数
STAT touch_hits 50 # touch命中次数
STAT touch_misses 10 # touch未命中次数
STAT auth_cmds 0 # 认证命令次数
STAT auth_errors 0 # 认证失败次数
STAT bytes_read 1000000 # 读取字节数
STAT bytes_written 2000000 # 写入字节数
STAT limit_maxbytes 67108864 # 最大内存限制
STAT accepting_conns 1 # 是否接受连接
STAT listen_disabled_num 0 # 监听禁用次数
STAT threads 4 # 线程数
STAT conn_yields 0 # 连接让出次数
STAT hash_power_level 16 # 哈希表大小级别
STAT hash_bytes 524288 # 哈希表大小
STAT hash_is_expanding 0 # 哈希表是否扩展
STAT slab_reassign_rescues 0 # Slab重新分配救援次数
STAT slab_reassign_chunk_rescues 0
STAT slab_reassign_evictions_nomem 0
STAT slab_reassign_inline_reclaim 0
STAT slab_reassign_busy_items 0
STAT slab_reassign_busy_deletes 0
STAT slab_reassign_running 0 # Slab重新分配是否运行
STAT slabs_moved 0 # 移动的Slab数
STAT lru_hits 0 # LRU命中次数
STAT lru_tail_repairs 0 # LRU尾部修复次数
STAT moves_to_cold 0 # 移动到冷数据次数
STAT moves_to_warm 0 # 移动到热数据次数
STAT moves_within_lru 0 # LRU内部移动次数
STAT direct_reclaims 0 # 直接回收次数
STAT lru_bumps_dropped 0 # LRU丢弃次数
END
2.2 stats slabs - Slab统计 #
bash
# 查看Slab统计
stats slabs
# 输出示例
STAT 1:chunk_size 96 # Chunk大小
STAT 1:chunks_per_page 10922 # 每页Chunk数
STAT 1:total_pages 1 # 总页数
STAT 1:total_chunks 10922 # 总Chunk数
STAT 1:used_chunks 100 # 已用Chunk数
STAT 1:free_chunks 10822 # 空闲Chunk数
STAT 1:free_chunks_end 0 # 末尾空闲Chunk数
STAT 1:get_hits 5000 # get命中次数
STAT 1:cmd_set 2000 # set命令次数
STAT 1:delete_hits 50 # delete命中次数
STAT 1:incr_hits 10 # incr命中次数
STAT 1:decr_hits 5 # decr命中次数
STAT 1:cas_hits 3 # cas命中次数
STAT 1:cas_badval 2 # cas失败次数
STAT 1:touch_hits 20 # touch命中次数
STAT active_slabs 1 # 活跃Slab数
STAT total_malloced 1048576 # 已分配内存
END
2.3 stats items - Item统计 #
bash
# 查看Item统计
stats items
# 输出示例
STAT items:1:number 100 # Item数量
STAT items:1:age 3600 # 最老Item年龄
STAT items:1:evicted 0 # 淘汰次数
STAT items:1:evicted_nonzero 0 # 非零过期淘汰次数
STAT items:1:evicted_time 0 # 最后淘汰时间
STAT items:1:outofmemory 0 # 内存不足次数
STAT items:1:tailrepairs 0 # 尾部修复次数
STAT items:1:reclaimed 0 # 回收次数
STAT items:1:expired_unfetched 0 # 过期未获取次数
STAT items:1:evicted_unfetched 0 # 淘汰未获取次数
STAT items:1:evicted_active 0 # 活跃淘汰次数
STAT items:1:crawler_reclaimed 0 # 爬虫回收次数
STAT items:1:crawler_items_checked 0
STAT items:1:lrutail_reflocked 0
STAT items:1:moves_to_cold 0
STAT items:1:moves_to_warm 0
STAT items:1:moves_within_lru 0
STAT items:1:direct_reclaims 0
STAT items:1:hits_to_hot 0
STAT items:1:hits_to_warm 0
STAT items:1:hits_to_cold 0
STAT items:1:hits_to_temp 0
END
2.4 stats sizes - 数据大小分布 #
bash
# 查看数据大小分布
stats sizes
# 输出示例
STAT 96 50 # 96字节的数据有50个
STAT 120 30 # 120字节的数据有30个
STAT 152 20 # 152字节的数据有20个
STAT 192 10 # 192字节的数据有10个
END
2.5 stats conns - 连接统计 #
bash
# 查看连接统计(需要启用)
stats conns
# 输出示例
STAT 10:addr_tcp 127.0.0.1:12345
STAT 10:state conn_read
STAT 10:secs_since_last_cmd 0
END
三、监控工具 #
3.1 memcached-tool #
bash
# 查看统计信息
memcached-tool 127.0.0.1:11211 stats
# 查看Slab信息
memcached-tool 127.0.0.1:11211 display
# 输出示例
# Item_Size Max_age Pages Count Full? Evicted Evict_Time OOM
1 96B 3600s 1 100 no 0 0 0
2 120B 3600s 1 50 no 0 0 0
3 152B 3600s 1 30 no 0 0 0
# 导出数据
memcached-tool 127.0.0.1:11211 dump
# 输出示例
add key1 0 3600 5
hello
add key2 0 3600 5
world
3.2 memcstat #
bash
# 查看统计信息
memcstat --servers=127.0.0.1:11211
# 查看多个服务器
memcstat --servers=127.0.0.1:11211,127.0.0.1:11212
# 输出示例
Server: 127.0.0.1 (11211)
pid: 1234
uptime: 123456
time: 1704067200
version: 1.6.29
...
3.3 nc命令 #
bash
# 发送命令
echo "stats" | nc 127.0.0.1 11211
# 获取特定统计
echo "stats slabs" | nc 127.0.0.1 11211
# 获取数据
echo "get key" | nc 127.0.0.1 11211
四、监控脚本 #
4.1 基础监控脚本 #
bash
#!/bin/bash
# monitor_memcached.sh
HOST="127.0.0.1"
PORT="11211"
# 获取统计信息
stats=$(echo "stats" | nc $HOST $PORT)
# 解析数据
get_hits=$(echo "$stats" | grep "STAT get_hits" | awk '{print $3}')
get_misses=$(echo "$stats" | grep "STAT get_misses" | awk '{print $3}')
curr_connections=$(echo "$stats" | grep "STAT curr_connections" | awk '{print $3}')
bytes=$(echo "$stats" | grep "STAT bytes " | awk '{print $3}')
limit_maxbytes=$(echo "$stats" | grep "STAT limit_maxbytes" | awk '{print $3}')
cmd_get=$(echo "$stats" | grep "STAT cmd_get" | awk '{print $3}')
cmd_set=$(echo "$stats" | grep "STAT cmd_set" | awk '{print $3}')
evictions=$(echo "$stats" | grep "STAT evictions" | awk '{print $3}')
# 计算指标
if [ $((get_hits + get_misses)) -gt 0 ]; then
hit_rate=$(echo "scale=2; $get_hits * 100 / ($get_hits + $get_misses)" | bc)
else
hit_rate=0
fi
mem_usage=$(echo "scale=2; $bytes * 100 / $limit_maxbytes" | bc)
# 输出结果
echo "================================"
echo "Memcached监控报告"
echo "================================"
echo "时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo "--------------------------------"
echo "性能指标:"
echo " 命中率: ${hit_rate}%"
echo " GET请求数: $cmd_get"
echo " SET请求数: $cmd_set"
echo "--------------------------------"
echo "资源指标:"
echo " 内存使用率: ${mem_usage}%"
echo " 已用字节: $bytes"
echo " 最大字节: $limit_maxbytes"
echo " 当前连接数: $curr_connections"
echo "--------------------------------"
echo "业务指标:"
echo " 淘汰次数: $evictions"
echo "================================"
4.2 持续监控脚本 #
bash
#!/bin/bash
# continuous_monitor.sh
HOST="127.0.0.1"
PORT="11211"
INTERVAL=5
echo "开始监控Memcached (每${INTERVAL}秒刷新一次)"
echo "按Ctrl+C停止"
echo ""
while true; do
# 获取统计信息
stats=$(echo "stats" | nc $HOST $PORT)
# 解析数据
get_hits=$(echo "$stats" | grep "STAT get_hits" | awk '{print $3}')
get_misses=$(echo "$stats" | grep "STAT get_misses" | awk '{print $3}')
curr_connections=$(echo "$stats" | grep "STAT curr_connections" | awk '{print $3}')
bytes=$(echo "$stats" | grep "STAT bytes " | awk '{print $3}')
limit_maxbytes=$(echo "$stats" | grep "STAT limit_maxbytes" | awk '{print $3}')
# 计算指标
if [ $((get_hits + get_misses)) -gt 0 ]; then
hit_rate=$(echo "scale=2; $get_hits * 100 / ($get_hits + $get_misses)" | bc)
else
hit_rate=0
fi
mem_usage=$(echo "scale=2; $bytes * 100 / $limit_maxbytes" | bc)
# 输出
clear
echo "Memcached实时监控"
echo "时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo "--------------------------------"
echo "命中率: ${hit_rate}%"
echo "内存使用率: ${mem_usage}%"
echo "当前连接数: $curr_connections"
echo "--------------------------------"
sleep $INTERVAL
done
4.3 Python监控脚本 #
python
#!/usr/bin/env python3
# monitor_memcached.py
import time
import socket
from datetime import datetime
class MemcachedMonitor:
def __init__(self, host='127.0.0.1', port=11211):
self.host = host
self.port = port
def get_stats(self):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((self.host, self.port))
sock.send(b"stats\n")
stats = {}
while True:
line = sock.recv(1024).decode()
if line.startswith('END'):
break
if line.startswith('STAT'):
parts = line.split()
key = parts[1]
value = parts[2]
stats[key] = value
sock.close()
return stats
def calculate_metrics(self, stats):
get_hits = int(stats.get('get_hits', 0))
get_misses = int(stats.get('get_misses', 0))
bytes_stored = int(stats.get('bytes', 0))
limit_maxbytes = int(stats.get('limit_maxbytes', 1))
# 计算命中率
if get_hits + get_misses > 0:
hit_rate = get_hits / (get_hits + get_misses) * 100
else:
hit_rate = 0
# 计算内存使用率
mem_usage = bytes_stored / limit_maxbytes * 100
return {
'hit_rate': round(hit_rate, 2),
'mem_usage': round(mem_usage, 2),
'curr_connections': int(stats.get('curr_connections', 0)),
'cmd_get': int(stats.get('cmd_get', 0)),
'cmd_set': int(stats.get('cmd_set', 0)),
'evictions': int(stats.get('evictions', 0))
}
def print_report(self, metrics):
print("=" * 50)
print(f"Memcached监控报告 - {datetime.now()}")
print("=" * 50)
print(f"命中率: {metrics['hit_rate']}%")
print(f"内存使用率: {metrics['mem_usage']}%")
print(f"当前连接数: {metrics['curr_connections']}")
print(f"GET请求数: {metrics['cmd_get']}")
print(f"SET请求数: {metrics['cmd_set']}")
print(f"淘汰次数: {metrics['evictions']}")
print("=" * 50)
def main():
monitor = MemcachedMonitor()
while True:
stats = monitor.get_stats()
metrics = monitor.calculate_metrics(stats)
# 清屏
print("\033[2J\033[H")
monitor.print_report(metrics)
time.sleep(5)
if __name__ == '__main__':
main()
五、告警配置 #
5.1 告警规则 #
bash
#!/bin/bash
# alert_memcached.sh
HOST="127.0.0.1"
PORT="11211"
# 获取统计信息
stats=$(echo "stats" | nc $HOST $PORT)
# 解析数据
get_hits=$(echo "$stats" | grep "STAT get_hits" | awk '{print $3}')
get_misses=$(echo "$stats" | grep "STAT get_misses" | awk '{print $3}')
bytes=$(echo "$stats" | grep "STAT bytes " | awk '{print $3}')
limit_maxbytes=$(echo "$stats" | grep "STAT limit_maxbytes" | awk '{print $3}')
evictions=$(echo "$stats" | grep "STAT evictions" | awk '{print $3}')
curr_connections=$(echo "$stats" | grep "STAT curr_connections" | awk '{print $3}')
max_connections=$(echo "$stats" | grep "STAT max_connections" | awk '{print $3}')
# 计算指标
if [ $((get_hits + get_misses)) -gt 0 ]; then
hit_rate=$(echo "scale=2; $get_hits * 100 / ($get_hits + $get_misses)" | bc)
else
hit_rate=0
fi
mem_usage=$(echo "scale=2; $bytes * 100 / $limit_maxbytes" | bc)
conn_usage=$(echo "scale=2; $curr_connections * 100 / $max_connections" | bc)
# 告警检查
ALERTS=()
# 命中率告警
if [ $(echo "$hit_rate < 80" | bc) -eq 1 ]; then
ALERTS+=("警告:命中率低于80% (当前: ${hit_rate}%)")
fi
# 内存使用率告警
if [ $(echo "$mem_usage > 90" | bc) -eq 1 ]; then
ALERTS+=("警告:内存使用率超过90% (当前: ${mem_usage}%)")
fi
# 连接数告警
if [ $(echo "$conn_usage > 80" | bc) -eq 1 ]; then
ALERTS+=("警告:连接数使用率超过80% (当前: ${conn_usage}%)")
fi
# 淘汰告警
if [ $evictions -gt 1000 ]; then
ALERTS+=("警告:淘汰次数过多 (当前: $evictions)")
fi
# 发送告警
if [ ${#ALERTS[@]} -gt 0 ]; then
echo "Memcached告警报告 - $(date '+%Y-%m-%d %H:%M:%S')"
echo "================================"
for alert in "${ALERTS[@]}"; do
echo "$alert"
done
# 这里可以添加发送邮件、短信等通知逻辑
# send_email "${ALERTS[@]}"
fi
5.2 集成Prometheus #
yaml
# prometheus.yml
scrape_configs:
- job_name: 'memcached'
static_configs:
- targets: ['localhost:9150']
# 使用memcached_exporter
# https://github.com/prometheus/memcached_exporter
5.3 集成Grafana #
text
Grafana Dashboard配置:
1. 数据源:Prometheus
2. 面板配置:
- 命中率
- 内存使用率
- 连接数
- QPS
- 淘汰次数
推荐Dashboard:
- https://grafana.com/grafana/dashboards/3746
六、调试技巧 #
6.1 连接调试 #
bash
# 使用telnet连接
telnet 127.0.0.1 11211
# 测试命令
stats
version
quit
# 使用nc连接
nc 127.0.0.1 11211
# 测试UDP连接
nc -u 127.0.0.1 11211
6.2 数据调试 #
bash
# 查看特定键
get key
# 查看键和CAS ID
gets key
# 查看所有键(不推荐,数据量大时会很慢)
stats cachedump 1 0
# 查看特定Slab的键
stats cachedump 1 100
6.3 性能调试 #
bash
# 查看慢查询(需要客户端记录)
# 查看内存使用
stats slabs
# 查看淘汰情况
stats items | grep evicted
# 查看连接状态
stats conns
6.4 日志调试 #
bash
# 启动时开启详细日志
memcached -vv
# 启动时开启最详细日志
memcached -vvv
# 输出到文件
memcached -vv >> /var/log/memcached.log 2>&1
七、故障排查 #
7.1 连接失败 #
bash
# 检查服务是否运行
ps aux | grep memcached
# 检查端口是否监听
netstat -tlnp | grep 11211
# 检查防火墙
sudo ufw status
sudo firewall-cmd --list-all
# 检查SELinux
getenforce
# 测试连接
telnet 127.0.0.1 11211
7.2 性能问题 #
bash
# 查看命中率
stats | grep -E "get_hits|get_misses"
# 查看内存使用
stats | grep -E "bytes|limit_maxbytes"
# 查看淘汰情况
stats items | grep evicted
# 查看连接数
stats | grep -E "curr_connections|max_connections"
# 查看Slab使用
memcached-tool 127.0.0.1:11211
7.3 内存问题 #
bash
# 查看内存使用
stats | grep bytes
# 查看Slab分布
stats slabs
# 查看数据大小分布
stats sizes
# 查看淘汰统计
stats items | grep evicted
# 查看内存碎片
memcached-tool 127.0.0.1:11211
7.4 数据丢失 #
bash
# 检查是否重启
stats | grep uptime
# 检查淘汰
stats items | grep evicted
# 检查过期时间
get key
# 检查flush_all
stats | grep cmd_flush
八、总结 #
监控要点:
| 指标 | 命令 | 说明 |
|---|---|---|
| 基本信息 | stats | 全局统计 |
| Slab信息 | stats slabs | 内存分配 |
| Item信息 | stats items | 数据统计 |
| 大小分布 | stats sizes | 数据大小 |
最佳实践:
- 定期监控关键指标
- 设置合理的告警阈值
- 使用可视化工具
- 保存历史数据
- 建立故障排查流程
恭喜你完成了Memcached的学习!
最后更新:2026-03-27