一、Redis过期策略基础
1.1 为什么需要过期策略
Redis作为内存数据库,存储空间有限。合理配置过期策略可以:
- 节省内存:自动清理不再需要的数据
- 保证数据时效性:确保缓存数据不会过时
- 提升性能:减少无效数据的IO开销
- 降低成本:减少内存使用量,节省服务器费用
1.2 Redis过期策略类型
Redis采用惰性删除 + 定期删除双策略组合:
| 策略 | 机制 | 优点 | 缺点 |
|---|---|---|---|
| 惰性删除 | 访问key时才检查是否过期 | CPU友好,不额外消耗 | 过期key可能长期占用内存 |
| 定期删除 | 每隔一段时间随机检查并删除过期key | 平衡CPU和内存消耗 | 可能漏删部分过期key |
| 组合策略 | 惰性+定期同时工作 | 兼顾CPU和内存 | 仍有少量过期key残留 |
1.3 过期Key的生命周期
## Key过期流程
1. 设置TTL(Time To Live)
↓
2. Key进入过期字典(expires dict)
↓
3. 定期扫描(每100ms抽查部分key)
├── 发现过期 → 删除
└── 未发现 → 继续保留
4. 客户端访问Key
├── 已过期 → 惰性删除,返回nil
└── 未过期 → 返回数据
5. 内存不足时触发淘汰策略
二、CentOS上Redis安装与配置
2.1 安装Redis
# 方法一:yum安装(CentOS 7)
sudo yum install -y epel-release
sudo yum install -y redis
# 方法二:yum安装(CentOS 8/Stream)
sudo dnf install -y redis
# 方法三:源码编译安装(推荐,可获取最新版)
cd /opt
sudo wget https://download.redis.io/redis-stable.tar.gz
sudo tar -xzvf redis-stable.tar.gz
cd redis-stable
sudo make
sudo make install
2.2 启动Redis
# 使用systemd启动
sudo systemctl start redis
sudo systemctl enable redis
# 验证运行状态
sudo systemctl status redis
redis-cli ping
# 返回PONG表示正常
2.3 Redis配置文件位置
# yum安装的配置文件
sudo nano /etc/redis.conf
# 源码安装的配置文件
sudo nano /opt/redis-stable/redis.conf
三、TTL设置方法详解
3.1 命令行设置过期时间
# 连接Redis
redis-cli
# ===== 过期时间设置命令 =====
# 1. EXPIRE:设置秒级过期
SET user:1001 "张三"
EXPIRE user:1001 3600 # 3600秒(1小时)后过期
# 2. PEXPIRE:设置毫秒级过期
PEXPIRE user:1001 3600000 # 3600000毫秒(1小时)后过期
# 3. EXPIREAT:设置UNIX时间戳过期
EXPIREAT user:1001 1735689600 # 到指定时间戳过期
# 4. PEXPIREAT:设置毫秒级时间戳过期
PEXPIREAT user:1001 1735689600000
# 5. SET命令直接带过期(推荐)
SET session:abc123 "userdata" EX 1800 # 30分钟过期
SET token:xyz789 "authdata" PX 7200000 # 2小时过期(毫秒)
SET cache:product:100 "data" EXAT 1735689600 # 到指定时间戳过期
# 6. SETEX:设置值+秒级过期(旧语法)
SETEX cache:hot 300 "热门数据" # 5分钟过期
3.2 查看剩余过期时间
# TTL:查看秒级剩余时间
TTL user:1001
# 返回值说明:
# -1:key存在但没有设置过期时间
# -2:key不存在
# >0:剩余秒数
# PTTL:查看毫秒级剩余时间
PTTL user:1001
# 批量查看TTL
redis-cli --scan --pattern "session:*" | xargs -I {} redis-cli TTL {}
3.3 取消过期时间
# PERSIST:移除过期时间,key变为永久
PERSIST user:1001
# 重新SET也会覆盖过期时间
SET user:1001 "李四" # 变为永不过期
四、定期删除参数配置
4.1 核心配置参数
# 编辑Redis配置文件
sudo nano /etc/redis.conf
# ===== 定期删除相关配置 =====
# 每秒执行定期删除的频率(Hz)
# 值越大,扫描越频繁,CPU消耗越多,但过期key清理越及时
# 默认值:10(每秒执行10次)
hz 10
# 动态调整Hz(开启自适应)
# Redis会根据已连接客户端数量自动调整hz值
# 默认值:yes
dynamic-hz yes
4.2 Hz参数调优
## Hz参数选择指南
### hz = 10(默认)
- 适用场景:通用场景
- 扫描频率:每100ms一次
- CPU消耗:低
- 过期key清理速度:中等
### hz = 50~100
- 适用场景:大量短期key(如验证码、会话)
- 扫描频率:每10~20ms一次
- CPU消耗:中等
- 过期key清理速度:快
### hz = 1~5
- 适用场景:内存充足、key过期不敏感
- 扫描频率:每200ms~1s一次
- CPU消耗:极低
- 过期key清理速度:慢
### 调优公式
hz ≈ 预期每秒过期key数 ÷ 20 + 10
4.3 定期删除内部机制
## Redis定期删除执行流程
1. 每隔 1000/hz 毫秒执行一次(默认100ms)
2. 从过期字典中随机抽取20个key
3. 检查每个key是否过期
4. 删除所有已过期的key
5. 如果过期key占比 > 25%,重复步骤2-5
6. 单次执行时间不超过 1000/hz 毫秒的25%
7. 总共遍历16个数据库(db0~db15)
关键限制:
- 每次最多随机抽20个key
- 最多连续执行16次(防止阻塞)
- 超时自动退出(保证响应速度)
五、内存淘汰策略配置
当过期策略无法及时清理内存时,Redis会触发内存淘汰策略。
5.1 八种淘汰策略
| 策略 | 说明 | 适用场景 |
|---|---|---|
| noeviction | 不淘汰,写入报错 | 数据不能丢失 |
| allkeys-lru | 所有key中淘汰最久未使用的 | 通用缓存 |
| allkeys-lfu | 所有key中淘汰使用频率最低的 | 热点缓存 |
| allkeys-random | 所有key中随机淘汰 | 无访问热点 |
| volatile-lru | 过期key中淘汰最久未使用的 | 混合持久化+缓存 |
| volatile-lfu | 过期key中淘汰使用频率最低的 | 混合场景 |
| volatile-random | 过期key中随机淘汰 | 过期key均匀访问 |
| volatile-ttl | 过期key中淘汰TTL最短的 | 有明确时效需求 |
5.2 配置淘汰策略
# redis.conf
# 设置最大内存限制
maxmemory 2gb
# 设置淘汰策略
maxmemory-policy allkeys-lru
# 淘汰采样数量(越大越精确,但越慢)
maxmemory-samples 5
5.3 策略选择决策树
## 如何选择淘汰策略
是否所有key都可以淘汰?
├── 是 → 是否有访问热点?
│ ├── 是 → allkeys-lru(最常用)
│ │ 或 allkeys-lfu(更精确)
│ └── 否 → allkeys-random
└── 否 → 是否有设置TTL的key?
├── 是 → 是否关心TTL短的先淘汰?
│ ├── 是 → volatile-ttl
│ └── 否 → 是否有访问热点?
│ ├── 是 → volatile-lru
│ │ 或 volatile-lfu
│ └── 否 → volatile-random
└── 否 → noeviction(默认)
5.4 运行时动态调整
# 查看当前淘汰策略
redis-cli CONFIG GET maxmemory-policy
# 动态修改淘汰策略(无需重启)
redis-cli CONFIG SET maxmemory-policy allkeys-lru
# 查看当前内存使用
redis-cli INFO memory | grep used_memory_human
# 查看淘汰统计
redis-cli INFO stats | grep evicted
六、生产环境最佳实践
6.1 过期策略配置模板
# ===== 生产环境Redis过期策略配置模板 =====
# 最大内存(建议设为系统内存的70-80%)
maxmemory 4gb
# 淘汰策略(推荐allkeys-lru)
maxmemory-policy allkeys-lru
# 采样数量
maxmemory-samples 10
# 定期删除频率
hz 20
# 开启动态Hz
dynamic-hz yes
# 惰性删除(默认开启)
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
replica-lazy-flush no
# 异步删除(大key优化)
lazyfree-lazy-eviction yes
lazyfree-lazy-expire yes
lazyfree-lazy-server-del yes
6.2 不同业务场景配置建议
## 业务场景配置对照表
### 会话缓存(Session Cache)
- TTL:30分钟~2小时
- 淘汰策略:allkeys-lru
- hz:20
- 示例:SET session:token123 "data" EX 1800
### 验证码缓存
- TTL:5~15分钟
- 淘汰策略:volatile-ttl
- hz:50
- 示例:SET sms:code:13800138000 "123456" EX 300
### 热点数据缓存
- TTL:1~24小时
- 淘汰策略:allkeys-lfu
- hz:10
- 示例:SET cache:product:100 "data" EX 3600
### 排行榜
- TTL:不设或24小时刷新
- 淘汰策略:allkeys-lru
- hz:10
- 示例:ZADD rank:score 100 "user1"
### 限流计数器
- TTL:1秒~1分钟
- 淘汰策略:volatile-ttl
- hz:100
- 示例:SET rate:api:192.168.1.1 1 EX 1
6.3 大Key过期优化
# 问题:大key过期时会导致主线程阻塞
# 解决方案:使用异步删除
# 1. 开启异步删除配置
CONFIG SET lazyfree-lazy-eviction yes
CONFIG SET lazyfree-lazy-expire yes
# 2. 使用UNLINK替代DEL(异步删除)
UNLINK bigkey:hash:10000 # 异步删除,不阻塞
# 3. 大key的过期处理方案
# 方案A:将大key拆分为小key
HSET user:1000:profile name "张三"
HSET user:1000:settings theme "dark"
# 分别设置过期
EXPIRE user:1000:profile 3600
EXPIRE user:1000:settings 7200
# 方案B:使用逻辑过期而非TTL
SET article:100:content "长文本内容"
HSET article:100:meta expire_at 1735689600
# 读取时检查逻辑过期时间
七、监控与调优
7.1 过期Key监控
# 查看过期key统计
redis-cli INFO stats | grep expire
# 查看内存使用详情
redis-cli INFO memory
# 实时监控命令
redis-cli MONITOR
# 查看慢日志
redis-cli SLOWLOG GET 10
7.2 自定义监控脚本
#!/bin/bash
# Redis过期策略监控脚本
REDIS_CLI="redis-cli"
ALERT_THRESHOLD=80 # 内存使用率告警阈值
# 获取内存使用率
MEMORY_USED=$($REDIS_CLI INFO memory | grep used_memory: | awk -F: '{print $2}' | tr -d '\r')
MEMORY_MAX=$($REDIS_CLI CONFIG GET maxmemory | tail -1)
if [ "$MEMORY_MAX" -gt 0 ]; then
USAGE_PERCENT=$((MEMORY_USED * 100 / MEMORY_MAX))
echo "Memory usage: ${USAGE_PERCENT}%"
if [ "$USAGE_PERCENT" -gt "$ALERT_THRESHOLD" ]; then
echo "WARNING: Memory usage exceeds ${ALERT_THRESHOLD}%!"
# 可以发送告警通知
fi
fi
# 查看淘汰统计
EVICTED=$($REDIS_CLI INFO stats | grep evicted_keys | awk -F: '{print $2}' | tr -d '\r')
echo "Evicted keys: $EVICTED"
# 查看过期key统计
EXPIRED=$($REDIS_CLI INFO stats | grep expired_keys | awk -F: '{print $2}' | tr -d '\r')
echo "Expired keys: $EXPIRED"
7.3 常见性能问题与解决
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 大量key同时过期 | 同一批次设置相同TTL | 在TTL上加随机偏移 |
| 内存持续增长 | 未设置过期或淘汰策略 | 配置maxmemory和淘汰策略 |
| 偶发性延迟 | 大key过期阻塞 | 开启异步删除或拆分大key |
| CPU占用高 | hz设置过高 | 降低hz值到合理范围 |
| 缓存雪崩 | 大量key同时失效 | 设置随机过期时间 |
八、总结
Redis过期策略配置要点:
- 理解双策略机制:惰性删除+定期删除协同工作
- 合理设置TTL:根据业务场景选择合适的过期时间
- 配置淘汰策略:推荐
allkeys-lru作为通用方案 - 调优hz参数:过期key越多,hz应设置越高
- 大key异步删除:开启
lazyfree避免阻塞 - 监控内存使用:设置告警,防止内存溢出
# 快速验证当前配置
redis-cli CONFIG GET maxmemory
redis-cli CONFIG GET maxmemory-policy
redis-cli CONFIG GET hz
注:本文基于Redis 7.x编写,具体配置可能因版本而异,请参考官方文档。