Memcached教程FG005-Memcached过期策略与LRU实战
本文档风哥主要介绍Memcached数据库过期策略与LRU机制相关知识,包括Memcached数据库过期机制原理、LRU算法原理、LRU结构解析、过期时间规划、LRU配置规划、淘汰策略规划、过期机制实战、LRU配置实战、LRU监控实战等内容,风哥教程参考Memcached官方文档LRU Algorithm、Cache Management等内容编写,适合DBA人员和运维人员在学习和测试中使用,如果要应用于生产环境则需要自行确认。
Part01-基础概念与理论知识
1.1 Memcached数据库过期机制原理
Memcached的过期机制是缓存管理的核心特性之一,理解其工作原理对于正确使用缓存至关重要。更多视频教程www.fgedu.net.cn
1.1.1 过期时间类型
# 1. 相对时间(秒数)
– 范围:0 – 2592000秒(30天)
– 含义:从当前时间开始的秒数
– 示例:3600表示1小时后过期
# 2. 绝对时间(Unix时间戳)
– 范围:大于2592000秒
– 含义:具体的Unix时间戳
– 示例:1712534400表示2024年4月8日
# 3. 永不过期
– 值:0
– 含义:数据永不过期(除非被淘汰)
– 注意:不推荐使用
# 过期时间判断逻辑
if (exptime == 0) {
// 永不过期
} else if (exptime <= 2592000) {
// 相对时间:当前时间 + exptime
real_exptime = current_time + exptime;
} else {
// 绝对时间:直接使用
real_exptime = exptime;
}
1.1.2 惰性过期机制
# 工作原理
Memcached不会主动扫描过期数据,而是在访问时检查
# 过期检查时机
1. get操作时检查
2. gets操作时检查
3. touch操作时检查
# 过期处理流程
┌─────────────────────────────────────────┐
│ 客户端发起get请求 │
└─────────────────┬───────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ 查找Key对应的数据 │
└─────────────────┬───────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ 检查数据是否过期 │
└─────────────────┬───────────────────────┘
│
┌─────────┴─────────┐
│ │
▼ ▼
┌───────────────┐ ┌───────────────┐
│ 未过期 │ │ 已过期 │
│ 返回数据 │ │ 删除数据 │
└───────────────┘ │ 返回空 │
└───────────────┘
# 惰性过期的优点
– 减少CPU开销
– 不需要后台线程扫描
– 简单高效
# 惰性过期的缺点
– 过期数据占用内存直到被访问
– 可能导致内存浪费
1.1.3 LRU Crawler机制
# 启用LRU Crawler
-o lru_crawler
# 工作原理
后台线程定期扫描LRU链表,主动清理过期数据
# 配置参数
-o lru_crawler 启用LRU爬虫
-o lru_maintainer 启用LRU维护线程
# LRU Crawler优势
– 主动清理过期数据
– 释放内存空间
– 减少惰性过期的内存浪费
# 查看Crawler状态
$ echo “stats” | nc 192.168.1.100 11211 | grep crawler
STAT crawler_reclaimed 1000
STAT crawler_items_checked 10000
# crawler_reclaimed: Crawler回收的过期Item数
# crawler_items_checked: Crawler检查的Item数
1.2 Memcached数据库LRU算法原理
LRU(Least Recently Used,最近最少使用)是Memcached的默认淘汰策略,学习交流加群风哥微信: itpux-com
1.2.1 LRU算法概述
# 核心思想
当内存不足时,淘汰最近最少使用的数据
# 实现方式
维护一个按访问时间排序的链表
– 新访问的数据移到链表头部
– 淘汰时从链表尾部删除
# LRU链表结构
┌─────────────────────────────────────────────────────┐
│ LRU链表 │
│ │
│ HEAD ←→ Item1 ←→ Item2 ←→ Item3 ←→ … ←→ TAIL │
│ ↑ ↑ │
│ 最近访问 最久未访问 │
│ (热点数据) (淘汰候选) │
└─────────────────────────────────────────────────────┘
# LRU操作
1. 访问数据:将数据移到链表头部
2. 存储数据:将数据插入链表头部
3. 淘汰数据:从链表尾部删除数据
# LRU优势
– 自动识别热点数据
– 公平淘汰冷数据
– 简单高效
1.2.2 分层LRU结构
# 新版Memcached采用分层LRU
HOT LRU → WARM LRU → COLD LRU → TEMP LRU
# 各层作用
┌─────────────────────────────────────────────────────┐
│ HOT LRU │
│ – 存储新写入的数据 │
│ – 容量占比:20%(可配置) │
│ – 数据访问后可能升级到WARM │
└─────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ WARM LRU │
│ – 存储被访问过的数据 │
│ – 容量占比:40%(可配置) │
│ – 数据长时间未访问降级到COLD │
└─────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ COLD LRU │
│ – 存储长时间未访问的数据 │
│ – 容量占比:剩余空间 │
│ – 淘汰时从此层选择 │
└─────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ TEMP LRU │
│ – 存储临时数据(短TTL) │
│ – 独立管理,不影响其他LRU │
└─────────────────────────────────────────────────────┘
# 配置参数
-o hot_lru_pct=20 # HOT LRU占比
-o warm_lru_pct=40 # WARM LRU占比
-o temporary_ttl=N # TEMP LRU的TTL阈值
1.3 Memcached数据库LRU结构解析
1.3.1 LRU维护线程
# 启用LRU维护线程
-o lru_maintainer
# 工作职责
1. 在各LRU层之间移动数据
2. 维护LRU链表结构
3. 处理数据淘汰
# 数据移动规则
HOT → WARM:数据被访问
WARM → COLD:数据长时间未访问
COLD → WARM:数据被访问
# 查看LRU维护状态
$ echo “stats” | nc 192.168.1.100 11211 | grep -E “lru_maintainer|moves”
STAT lru_maintainer_juggles 1000
STAT moves_to_cold 5000
STAT moves_to_warm 3000
STAT moves_within_lru 2000
# 字段说明
lru_maintainer_juggles: 维护线程执行次数
moves_to_cold: 移动到COLD的次数
moves_to_warm: 移动到WARM的次数
moves_within_lru: LRU内部移动次数
1.3.2 淘汰机制详解
# 触发条件
1. 内存不足时(没有空闲Chunk)
2. 需要存储新数据时
# 淘汰流程
┌─────────────────────────────────────────────────────┐
│ 需要存储新数据 │
└─────────────────┬───────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ 查找对应Slab Class的空闲Chunk │
└─────────────────┬───────────────────────────────────┘
│
┌─────────┴─────────┐
│ │
▼ ▼
┌───────────────┐ ┌───────────────┐
│ 有空闲Chunk │ │ 无空闲Chunk │
│ 直接使用 │ │ 触发淘汰 │
└───────────────┘ └───────┬───────┘
│
▼
┌───────────────────────────┐
│ 从COLD LRU尾部选择 │
│ 淘汰最近最少使用的数据 │
└───────────────────────────┘
# 淘汰统计
$ echo “stats” | nc 192.168.1.100 11211 | grep evict
STAT evictions 1000
STAT evicted_unfetched 500
STAT evicted_nonzero 800
STAT evicted_time 1712534400
# 字段说明
evictions: 总淘汰次数
evicted_unfetched: 未被访问就被淘汰的数据
evicted_nonzero: 非零过期时间被淘汰的数据
evicted_time: 最近淘汰的时间
Part02-生产环境规划与建议
2.1 Memcached数据库过期时间规划
合理的过期时间规划是缓存有效性的关键。学习交流加群风哥QQ113257174
2.1.1 过期时间设置原则
# 1. 根据数据更新频率设置
– 高频更新:短过期时间(分钟级)
– 中频更新:中等过期时间(小时级)
– 低频更新:长过期时间(天级)
# 2. 根据数据重要性设置
– 关键数据:短过期时间,确保及时更新
– 非关键数据:长过期时间,减少数据库压力
# 3. 根据业务场景设置
– 用户会话:30分钟 – 2小时
– 用户资料:1小时 – 24小时
– 商品信息:5分钟 – 1小时
– 页面缓存:1分钟 – 5分钟
– 配置数据:1天 – 7天
# 4. 避免设置
– 过期时间为0(永不过期)
– 过期时间过长(超过数据有效期)
– 过期时间过短(缓存命中率低)
2.1.2 不同场景的过期时间建议
# 电商场景
商品基本信息:300秒(5分钟)
商品库存:60秒(1分钟)
商品价格:300秒(5分钟)
用户购物车:1800秒(30分钟)
订单信息:3600秒(1小时)
# 社交场景
用户资料:3600秒(1小时)
好友列表:1800秒(30分钟)
动态列表:300秒(5分钟)
评论数据:600秒(10分钟)
消息列表:60秒(1分钟)
# 内容场景
文章内容:3600秒(1小时)
文章列表:300秒(5分钟)
分类信息:86400秒(1天)
标签信息:86400秒(1天)
热门内容:60秒(1分钟)
# 系统场景
系统配置:86400秒(1天)
权限信息:3600秒(1小时)
字典数据:86400秒(1天)
验证码:300秒(5分钟)
2.2 Memcached数据库LRU配置规划
2.2.1 LRU参数配置
# 启用LRU相关功能
-o lru_crawler # 启用LRU爬虫
-o lru_maintainer # 启用LRU维护线程
# LRU层配置
-o hot_lru_pct=20 # HOT LRU占比(默认20%)
-o warm_lru_pct=40 # WARM LRU占比(默认40%)
# COLD LRU占比 = 100% – hot_lru_pct – warm_lru_pct
# TEMP LRU配置
-o temporary_ttl=61 # TTL小于此值的数据放入TEMP LRU
# 完整配置示例
$ /memcached/app/bin/memcached -p 11211 -m 8192 \
-o lru_crawler \
-o lru_maintainer \
-o hot_lru_pct=20 \
-o warm_lru_pct=40 \
-o temporary_ttl=61 \
-d
# 不同场景的LRU配置建议
# 热点数据多的场景
-o hot_lru_pct=30
-o warm_lru_pct=40
# 冷数据多的场景
-o hot_lru_pct=10
-o warm_lru_pct=30
# 临时数据多的场景
-o temporary_ttl=300
2.2.2 LRU配置优化建议
- 启用lru_crawler:主动清理过期数据,释放内存
- 启用lru_maintainer:自动维护LRU结构
- 合理设置LRU占比:根据业务特点调整
- 使用TEMP LRU:短TTL数据单独管理
- 监控淘汰次数:及时发现问题
2.3 Memcached数据库淘汰策略规划
2.3.1 淘汰策略选择
# 策略1:LRU淘汰(默认)
内存不足时淘汰最近最少使用的数据
适用:大多数场景
# 策略2:拒绝写入(-M参数)
内存不足时返回错误,不淘汰数据
适用:数据不能丢失的场景
# 配置方式
# 默认LRU淘汰
$ /memcached/app/bin/memcached -p 11211 -m 8192 -d
# 拒绝写入模式
$ /memcached/app/bin/memcached -p 11211 -m 8192 -M -d
# 两种策略对比
┌─────────────────┬─────────────────┬─────────────────┐
│ 特性 │ LRU淘汰 │ 拒绝写入 │
├─────────────────┼─────────────────┼─────────────────┤
│ 内存满时行为 │ 淘汰旧数据 │ 返回错误 │
│ 数据安全性 │ 可能丢失数据 │ 数据不丢失 │
│ 写入成功率 │ 高 │ 内存满时失败 │
│ 适用场景 │ 缓存场景 │ 数据重要场景 │
└─────────────────┴─────────────────┴─────────────────┘
2.3.2 淘汰监控指标
# 关键指标
1. evictions:总淘汰次数
2. evicted_unfetched:未被访问就被淘汰的数据
3. evicted_nonzero:非零过期时间被淘汰的数据
4. reclaimed:回收的过期数据
# 监控脚本
$ cat > /tmp/eviction_monitor.sh << 'EOF'
#!/bin/bash
# eviction_monitor.sh
# from:www.itpux.com.qq113257174.wx:itpux-com
# web: http://www.fgedu.net.cn
HOST="192.168.1.100"
PORT="11211"
STATS=$(echo "stats" | nc $HOST $PORT)
evictions=$(echo "$STATS" | grep "^STAT evictions" | awk '{print $3}')
evicted_unfetched=$(echo "$STATS" | grep "evicted_unfetched" | awk '{print $3}')
reclaimed=$(echo "$STATS" | grep "reclaimed" | awk '{print $3}')
echo "淘汰统计:"
echo "总淘汰次数: $evictions"
echo "未访问淘汰: $evicted_unfetched"
echo "回收过期: $reclaimed"
# 计算淘汰率
cmd_set=$(echo "$STATS" | grep "^STAT cmd_set" | awk '{print $3}')
if [ -n "$cmd_set" ] && [ $cmd_set -gt 0 ]; then
eviction_rate=$(echo "scale=4; $evictions * 100 / $cmd_set" | bc)
echo "淘汰率: ${eviction_rate}%"
fi
EOF
$ chmod +x /tmp/eviction_monitor.sh
$ /tmp/eviction_monitor.sh
淘汰统计:
总淘汰次数: 1000
未访问淘汰: 500
回收过期: 800
淘汰率: 0.10%
Part03-生产环境项目实施方案
3.1 Memcached数据库过期机制实战
3.1.1 设置过期时间实战
$ telnet 192.168.1.100 11211
Trying 192.168.1.100…
Connected to 192.168.1.100.
Escape character is ‘^]’.
# 设置10秒过期
set fgedu_temp 0 10 8
tempdata
STORED
# 立即获取
get fgedu_temp
VALUE fgedu_temp 0 8
tempdata
END
# 等待10秒后获取
get fgedu_temp
END
# 设置1小时过期
set fgedu_hour 0 3600 8
hourdata
STORED
# 设置1天过期
set fgedu_day 0 86400 7
daydata
STORED
# 设置永不过期(不推荐)
set fgedu_forever 0 0 9
foreverdata
STORED
# 使用touch更新过期时间
touch fgedu_hour 7200
TOUCHED
# 验证过期时间已更新
# 数据将在2小时后过期
3.1.2 过期时间计算实战
# 相对时间(秒)
# 1分钟 = 60秒
# 1小时 = 3600秒
# 1天 = 86400秒
# 1周 = 604800秒
# 30天 = 2592000秒
# 绝对时间(Unix时间戳)
# 获取当前Unix时间戳
$ date +%s
1712534400
# 计算1小时后的时间戳
$ echo $(($(date +%s) + 3600))
1712538000
# 计算1天后的时间戳
$ echo $(($(date +%s) + 86400))
1712620800
# 使用绝对时间设置过期
# 假设要在2024年4月8日12:00过期
# 对应时间戳:1712558400
set fgedu_absolute 0 1712558400 8
abs_data
STORED
# 验证过期时间
# 可以通过stats items查看
3.1.3 LRU Crawler配置实战
# 方式1:启动时配置
$ /memcached/app/bin/memcached -p 11211 -m 8192 \
-o lru_crawler \
-o lru_maintainer \
-d
# 方式2:修改Systemd服务文件
$ sudo vi /etc/systemd/system/memcached.service
[Service]
ExecStart=/memcached/app/bin/memcached -u memcached -p 11211 -m 8192 -o lru_crawler -o lru_maintainer -v
# 重载配置
$ sudo systemctl daemon-reload
$ sudo systemctl restart memcached
# 验证LRU Crawler是否启用
$ echo “stats settings” | nc 192.168.1.100 11211 | grep lru
STAT lru_crawler true
STAT lru_maintainer true
STAT hot_lru_pct 20
STAT warm_lru_pct 40
# 查看Crawler工作状态
$ echo “stats” | nc 192.168.1.100 11211 | grep crawler
STAT crawler_reclaimed 1000
STAT crawler_items_checked 10000
STAT lrutail_reflocked 10
# 手动触发LRU爬虫(高级)
$ echo “lru_crawler enable” | nc 192.168.1.100 11211
OK
3.2 Memcached数据库LRU配置实战
3.2.1 LRU层配置实战
# 场景1:热点数据多
$ /memcached/app/bin/memcached -p 11211 -m 8192 \
-o lru_crawler \
-o lru_maintainer \
-o hot_lru_pct=30 \
-o warm_lru_pct=40 \
-d
# 场景2:冷数据多
$ /memcached/app/bin/memcached -p 11211 -m 8192 \
-o lru_crawler \
-o lru_maintainer \
-o hot_lru_pct=10 \
-o warm_lru_pct=30 \
-d
# 场景3:临时数据多
$ /memcached/app/bin/memcached -p 11211 -m 8192 \
-o lru_crawler \
-o lru_maintainer \
-o temporary_ttl=300 \
-d
# 查看各LRU层的数据分布
$ echo “stats items” | nc 192.168.1.100 11211 | grep number
STAT items:1:number 5000
STAT items:1:number_hot 1000
STAT items:1:number_warm 2000
STAT items:1:number_cold 2000
# 计算各层占比
# HOT: 1000/5000 = 20%
# WARM: 2000/5000 = 40%
# COLD: 2000/5000 = 40%
3.2.2 LRU维护线程监控
# 查看LRU维护统计
$ echo “stats” | nc 192.168.1.100 11211 | grep -E “lru|moves”
STAT lru_maintainer_juggles 10000
STAT moves_to_cold 5000
STAT moves_to_warm 3000
STAT moves_within_lru 2000
STAT direct_reclaims 100
# 字段说明
# lru_maintainer_juggles: 维护线程执行次数
# moves_to_cold: 移动到COLD LRU的次数
# moves_to_warm: 移动到WARM LRU的次数
# moves_within_lru: LRU内部移动次数
# direct_reclaims: 直接回收次数
# 创建LRU监控脚本
$ cat > /tmp/lru_monitor.sh << 'EOF'
#!/bin/bash
# lru_monitor.sh
# from:www.itpux.com.qq113257174.wx:itpux-com
# web: http://www.fgedu.net.cn
HOST="192.168.1.100"
PORT="11211"
echo "LRU状态监控"
echo "============"
STATS=$(echo "stats" | nc $HOST $PORT)
echo "LRU维护统计:"
echo "$STATS" | grep -E "lru_maintainer|moves|direct_reclaims"
echo ""
echo "淘汰统计:"
echo "$STATS" | grep -E "evictions|reclaimed"
echo ""
echo "各Slab Class的LRU分布:"
echo "stats items" | nc $HOST $PORT | grep -E "number_hot|number_warm|number_cold" | \
awk -F: '{class=$2} {gsub(/STAT items:/, "", class); gsub(/:.*/, "", class)} \
{print "Class", class, $0}'
EOF
$ chmod +x /tmp/lru_monitor.sh
$ /tmp/lru_monitor.sh
LRU状态监控
============
LRU维护统计:
STAT lru_maintainer_juggles 10000
STAT moves_to_cold 5000
STAT moves_to_warm 3000
STAT moves_within_lru 2000
STAT direct_reclaims 100
淘汰统计:
STAT evictions 1000
STAT reclaimed 800
3.3 Memcached数据库LRU监控实战
3.3.1 实时监控脚本
$ cat > /tmp/realtime_lru_monitor.sh << 'EOF' #!/bin/bash # realtime_lru_monitor.sh # from:www.itpux.com.qq113257174.wx:itpux-com # web: http://www.fgedu.net.cn HOST="192.168.1.100" PORT="11211" INTERVAL=5 echo "时间,内存使用率,Item数,淘汰次数,回收次数,移动到COLD,移动到WARM" while true; do STATS=$(echo "stats" | nc $HOST $PORT) bytes=$(echo "$STATS" | grep "^STAT bytes" | awk '{print $3}') limit=$(echo "$STATS" | grep "limit_maxbytes" | awk '{print $3}') items=$(echo "$STATS" | grep "curr_items" | awk '{print $3}') evictions=$(echo "$STATS" | grep "^STAT evictions" | awk '{print $3}') reclaimed=$(echo "$STATS" | grep "reclaimed" | awk '{print $3}') moves_cold=$(echo "$STATS" | grep "moves_to_cold" | awk '{print $3}') moves_warm=$(echo "$STATS" | grep "moves_to_warm" | awk '{print $3}') if [ -n "$bytes" ] && [ -n "$limit" ] && [ $limit -gt 0 ]; then usage=$(echo "scale=2; $bytes * 100 / $limit" | bc) timestamp=$(date '+%H:%M:%S') echo "$timestamp,$usage,$items,$evictions,$reclaimed,$moves_cold,$moves_warm" fi sleep $INTERVAL done EOF $ chmod +x /tmp/realtime_lru_monitor.sh $ /tmp/realtime_lru_monitor.sh 时间,内存使用率,Item数,淘汰次数,回收次数,移动到COLD,移动到WARM 10:00:00,75.50,50000,1000,800,5000,3000 10:00:05,75.60,50100,1005,805,5010,3010 10:00:10,75.70,50200,1010,810,5020,3020
3.3.2 淘汰分析脚本
$ cat > /tmp/eviction_analysis.sh << 'EOF' #!/bin/bash # eviction_analysis.sh # from:www.itpux.com.qq113257174.wx:itpux-com # web: http://www.fgedu.net.cn HOST="192.168.1.100" PORT="11211" echo "淘汰分析报告" echo "============" STATS=$(echo "stats" | nc $HOST $PORT) # 获取关键指标 evictions=$(echo "$STATS" | grep "^STAT evictions" | awk '{print $3}') evicted_unfetched=$(echo "$STATS" | grep "evicted_unfetched" | awk '{print $3}') evicted_nonzero=$(echo "$STATS" | grep "evicted_nonzero" | awk '{print $3}') reclaimed=$(echo "$STATS" | grep "reclaimed" | awk '{print $3}') cmd_set=$(echo "$STATS" | grep "^STAT cmd_set" | awk '{print $3}') curr_items=$(echo "$STATS" | grep "curr_items" | awk '{print $3}') echo "" echo "基本统计:" echo "当前Item数: $curr_items" echo "总存储次数: $cmd_set" echo "总淘汰次数: $evictions" echo "" echo "淘汰详情:" echo "未访问淘汰: $evicted_unfetched" echo "非零过期淘汰: $evicted_nonzero" echo "回收过期: $reclaimed" echo "" echo "淘汰分析:" # 计算淘汰率 if [ -n "$cmd_set" ] && [ $cmd_set -gt 0 ]; then eviction_rate=$(echo "scale=4; $evictions * 100 / $cmd_set" | bc) echo "淘汰率: ${eviction_rate}%" fi # 计算未访问淘汰比例 if [ -n "$evictions" ] && [ $evictions -gt 0 ]; then unfetched_rate=$(echo "scale=2; $evicted_unfetched * 100 / $evictions" | bc) echo "未访问淘汰比例: ${unfetched_rate}%" fi echo "" echo "建议:" if [ $evictions -gt 10000 ]; then echo "- 淘汰次数较多,建议增加内存" fi if [ -n "$unfetched_rate" ] && [ $(echo "$unfetched_rate > 50″ | bc) -eq 1 ]; then
echo “- 未访问淘汰比例高,建议优化过期时间设置”
fi
EOF
$ chmod +x /tmp/eviction_analysis.sh
$ /tmp/eviction_analysis.sh
淘汰分析报告
============
基本统计:
当前Item数: 50000
总存储次数: 100000
总淘汰次数: 1000
淘汰详情:
未访问淘汰: 500
非零过期淘汰: 800
回收过期: 800
淘汰分析:
淘汰率: 1.0000%
未访问淘汰比例: 50.00%
建议:
– 未访问淘汰比例高,建议优化过期时间设置
Part04-生产案例与实战讲解
4.1 Memcached数据库数据淘汰案例
以下是一个真实的数据淘汰问题排查案例。更多学习教程公众号风哥教程itpux_com
4.1.1 问题现象
缓存命中率突然下降,数据库压力增大
# 排查步骤
# 1. 查看淘汰统计
$ echo “stats” | nc 192.168.1.100 11211 | grep -E “evictions|get_hits|get_misses”
STAT get_hits 45000
STAT get_misses 5000
STAT evictions 50000
# 发现淘汰次数异常高
# 2. 查看内存使用
$ echo “stats” | nc 192.168.1.100 11211 | grep -E “bytes|limit_maxbytes”
STAT bytes 8589934592
STAT limit_maxbytes 8589934592
# 内存已满
# 3. 查看Item数量
$ echo “stats” | nc 192.168.1.100 11211 | grep curr_items
STAT curr_items 100000
# 4. 分析Slab使用情况
$ echo “stats slabs” | nc 192.168.1.100 11211 | grep “used_chunks” | \
awk ‘{sum+=$3} END {print “Total used chunks:”, sum}’
Total used chunks: 100000
# 5. 计算命中率
# 命中率 = 45000 / (45000 + 5000) = 90%
# 命中率正常,但淘汰次数异常
4.1.2 问题分析与解决
# 淘汰次数高说明内存不足,数据频繁被淘汰
# 解决方案
# 方案1:增加内存
$ sudo vi /etc/systemd/system/memcached.service
ExecStart=/memcached/app/bin/memcached -u memcached -p 11211 -m 16384 …
# 内存从8GB增加到16GB
$ sudo systemctl daemon-reload
$ sudo systemctl restart memcached
# 方案2:优化过期时间
# 检查是否有大量数据未设置过期时间
$ echo “stats items” | nc 192.168.1.100 11211 | grep “evicted_nonzero”
STAT items:1:evicted_nonzero 10000
# 发现大量非零过期时间的数据被淘汰
# 说明过期时间设置不合理
# 方案3:启用LRU Crawler
$ /memcached/app/bin/memcached -p 11211 -m 8192 \
-o lru_crawler \
-o lru_maintainer \
-d
# 方案4:调整LRU层占比
# 如果热点数据多
$ /memcached/app/bin/memcached -p 11211 -m 8192 \
-o lru_crawler \
-o lru_maintainer \
-o hot_lru_pct=30 \
-d
# 验证效果
$ echo “stats” | nc 192.168.1.100 11211 | grep evictions
STAT evictions 100
# 淘汰次数明显下降
4.2 Memcached数据库LRU调优案例
4.2.1 LRU调优场景
# 问题
# 商品访问模式:少量热门商品访问频繁,大量冷门商品访问少
# 导致冷门商品占用大量内存,热门商品可能被淘汰
# 分析
$ echo “stats items” | nc 192.168.1.100 11211 | grep -E “number_hot|number_warm|number_cold”
STAT items:1:number_hot 500
STAT items:1:number_warm 1000
STAT items:1:number_cold 4500
# COLD LRU占比过高(75%)
# 调优方案
# 增加HOT和WARM LRU占比
$ /memcached/app/bin/memcached -p 11211 -m 8192 \
-o lru_crawler \
-o lru_maintainer \
-o hot_lru_pct=30 \
-o warm_lru_pct=50 \
-d
# 验证调优效果
$ echo “stats items” | nc 192.168.1.100 11211 | grep -E “number_hot|number_warm|number_cold”
STAT items:1:number_hot 1500
STAT items:1:number_warm 2500
STAT items:1:number_cold 1000
# HOT和WARM占比提高,热门商品更容易保留
4.2.2 TEMP LRU应用案例
# 问题
# 验证码TTL很短(5分钟),但占用大量内存
# 影响其他重要数据的缓存
# 解决方案:使用TEMP LRU
$ /memcached/app/bin/memcached -p 11211 -m 8192 \
-o lru_crawler \
-o lru_maintainer \
-o temporary_ttl=300 \
-d
# 验证码数据(TTL=300秒)将存入TEMP LRU
# 不影响HOT/WARM/COLD LRU
# 存储验证码
set verify:phone:13800138000 0 300 6
123456
STORED
# 查看TEMP LRU状态
$ echo “stats items” | nc 192.168.1.100 11211 | grep “number_temp”
STAT items:1:number_temp 1000
# TEMP LRU独立管理,不影响其他数据
4.3 Memcached数据库过期优化案例
4.3.1 过期时间优化案例
# 问题
# 用户资料更新频率低,但缓存过期时间设置过短
# 导致频繁查询数据库
# 分析
# 当前过期时间:300秒(5分钟)
# 实际更新频率:平均每天更新1次
# 优化方案
# 1. 延长过期时间
# 用户资料:3600秒(1小时)
# 2. 更新时主动刷新缓存
# 用户更新资料后,立即更新缓存
# 优化前
set user:profile:1001 1 300 100
{“id”:1001,”name”:”fgedu”,”age”:30}
# 优化后
set user:profile:1001 1 3600 100
{“id”:1001,”name”:”fgedu”,”age”:30}
# 效果对比
# 优化前:缓存命中率 60%
# 优化后:缓存命中率 95%
4.3.2 惰性过期问题优化
# 大量过期数据未被访问,占用内存
# 分析
$ echo “stats” | nc 192.168.1.100 11211 | grep -E “bytes|curr_items|expired_unfetched”
STAT bytes 8000000000
STAT curr_items 100000
STAT expired_unfetched 50000
# 有大量过期数据未被访问
# 解决方案:启用LRU Crawler
$ /memcached/app/bin/memcached -p 11211 -m 8192 \
-o lru_crawler \
-d
# 验证效果
$ echo “stats” | nc 192.168.1.100 11211 | grep crawler
STAT crawler_reclaimed 45000
# Crawler主动回收了过期数据
# 内存使用下降
$ echo “stats” | nc 192.168.1.100 11211 | grep bytes
STAT bytes 6000000000
Part05-风哥经验总结与分享
5.1 Memcached数据库过期策略最佳实践
5.1.1 过期时间设置建议
- 根据数据更新频率设置合理的过期时间
- 避免设置过期时间为0(永不过期)
- 热点数据可设置较长的过期时间
- 实时性要求高的数据设置较短的过期时间
- 使用touch命令动态更新过期时间
5.1.2 过期机制配置建议
# 1. 启用LRU Crawler
-o lru_crawler
# 2. 启用LRU维护线程
-o lru_maintainer
# 3. 合理配置TEMP LRU
-o temporary_ttl=300
# 4. 监控过期相关指标
– expired_unfetched
– crawler_reclaimed
– reclaimed
5.2 Memcached数据库LRU最佳实践
5.2.1 LRU配置建议
# 基础配置
-o lru_crawler # 必须启用
-o lru_maintainer # 必须启用
# 根据业务特点调整LRU占比
# 热点数据多
-o hot_lru_pct=30
-o warm_lru_pct=40
# 冷数据多
-o hot_lru_pct=10
-o warm_lru_pct=30
# 临时数据多
-o temporary_ttl=300
# 监控关键指标
– evictions
– moves_to_cold
– moves_to_warm
– lru_maintainer_juggles
5.2.2 淘汰策略选择建议
- 缓存场景:使用默认LRU淘汰
- 数据重要场景:使用-M参数拒绝写入
- 混合场景:根据数据重要性选择
5.3 Memcached数据库过期与LRU常见问题
5.3.1 缓存命中率低
# 1. 过期时间设置过短
# 2. 内存不足导致频繁淘汰
# 3. 数据访问模式问题
# 解决方案
# 1. 延长过期时间
# 2. 增加内存
# 3. 优化LRU配置
# 4. 分析访问模式,调整缓存策略
5.3.2 内存使用率高但淘汰少
# 1. 数据过期时间过长
# 2. 存在大量永不过期的数据
# 3. 惰性过期导致过期数据未被清理
# 解决方案
# 1. 检查过期时间设置
# 2. 启用LRU Crawler主动清理
# 3. 分析数据分布,优化存储策略
5.3.3 淘汰次数异常高
# 1. 内存不足
# 2. 数据量增长过快
# 3. 过期时间设置不合理
# 解决方案
# 1. 增加内存
# 2. 优化过期时间
# 3. 启用LRU Crawler
# 4. 分析数据访问模式
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
