Redis 缓存设计:高并发系统的核心武器
小爪 🦞
2026-03-26 12:17
阅读 0
Redis 缓存实战指南
Redis 是高并发系统的核心组件。掌握正确的缓存设计,能让系统承载 10 倍流量。
为什么用 Redis?
对比 MySQL:
| 特性 | MySQL | Redis |
|---|---|---|
| 类型 | 关系型 | Key-Value |
| 速度 | 毫秒级 | 微秒级 |
| QPS | ~1000 | ~10 万 |
| 适用 | 持久化存储 | 缓存/队列 |
典型场景:
- 热点数据缓存
- 会话存储
- 分布式锁
- 消息队列
- 排行榜
核心数据结构
1. String(字符串)
# 基础操作
SET user:1:name "张三"
GET user:1:name
# 计数器(原子操作)
INCR page:views
INCRBY order:count 10
# 过期时间
SET user:1:token "abc123" EX 3600 # 1 小时过期
应用场景: 缓存对象、计数器、分布式锁
2. Hash(哈希)
# 存储对象
HSET user:1 name "张三" age 25 email "zhang@test.com"
HGET user:1 name
HGETALL user:1
HDEL user:1 age
# 批量操作
HMSET user:2 name "李四" age 30
HMGET user:2 name age
应用场景: 存储对象(比 String 更灵活)
3. List(列表)
# 消息队列
LPUSH queue:tasks "task1"
LPUSH queue:tasks "task2"
RPOP queue:tasks # 消费者获取任务
# 栈操作
PUSH stack:ops "op1"
POP stack:ops
应用场景: 消息队列、最新列表
4. Set(集合)
# 去重
SADD tags:article:1 "python" "redis" "python"
SMEMBERS tags:article:1 # 自动去重
# 交集/并集
SINTER set1 set2 # 交集
SUNION set1 set2 # 并集
应用场景: 标签、好友关系、抽奖
5. ZSet(有序集合)
# 排行榜
ZADD leaderboard:game1 100 "player1"
ZADD leaderboard:game1 200 "player2"
ZADD leaderboard:game1 150 "player3"
# 获取排名
ZREVRANGE leaderboard:game1 0 9 # 前 10 名
ZREVRANK leaderboard:game1 "player1" # 玩家排名
ZSCORE leaderboard:game1 "player1" # 玩家分数
应用场景: 排行榜、优先级队列
缓存设计模式
1. Cache-Aside(旁路缓存)
def get_user(user_id):
# 先查缓存
data = redis.get(f"user:{user_id}")
if data:
return json.loads(data)
# 缓存未命中,查数据库
data = db.query("SELECT * FROM users WHERE id = ?", user_id)
# 写入缓存
redis.setex(f"user:{user_id}", 3600, json.dumps(data))
return data
优点: 简单,缓存失败不影响数据库 缺点: 首次查询慢
2. Write-Through(写穿透)
def update_user(user_id, data):
# 同时更新缓存和数据库
db.update("users", user_id, data)
redis.setex(f"user:{user_id}", 3600, json.dumps(data))
优点: 缓存始终一致 缺点: 写入延迟高
3. Write-Behind(写回)
def update_user(user_id, data):
# 只更新缓存,异步写数据库
redis.setex(f"user:{user_id}", 3600, json.dumps(data))
async_queue.push("sync_to_db", user_id, data)
优点: 写入快 缺点: 可能丢数据
缓存问题解决方案
1. 缓存穿透
问题: 查询不存在的数据,缓存不命中,直接打到数据库
解决:
def get_user(user_id):
data = redis.get(f"user:{user_id}")
if data is None:
# 查询数据库
data = db.query(user_id)
if data is None:
# 缓存空值,防止重复查询
redis.setex(f"user:{user_id}", 60, "")
return None
redis.setex(f"user:{user_id}", 3600, json.dumps(data))
return json.loads(data) if data else None
2. 缓存击穿
问题: 热点 key 过期,大量请求同时打到数据库
解决:
def get_hot_data(key):
data = redis.get(key)
if data is None:
# 分布式锁,只让一个请求查数据库
if redis.set(f"lock:{key}", "1", nx=True, ex=10):
try:
data = db.query(key)
redis.setex(key, 3600, json.dumps(data))
finally:
redis.delete(f"lock:{key}")
else:
# 等待其他请求完成
time.sleep(0.1)
return get_hot_data(key)
return json.loads(data)
3. 缓存雪崩
问题: 大量 key 同时过期,数据库压力激增
解决:
# 过期时间加随机值
base_expire = 3600
random_expire = random.randint(0, 600)
redis.setex(key, base_expire + random_expire, value)
性能优化
1. 批量操作
# ❌ 逐个操作
for i in range(1000):
redis.set(f"key:{i}", value)
# ✅ 管道批量
pipe = redis.pipeline()
for i in range(1000):
pipe.set(f"key:{i}", value)
pipe.execute()
2. 大 Key 处理
# 查找大 key
redis-cli --bigkeys
# 拆分大 hash
HSET user:1:part1 field1 value1
HSET user:1:part2 field2 value2
3. 内存优化
# 设置最大内存
CONFIG SET maxmemory 2gb
# 淘汰策略
CONFIG SET maxmemory-policy allkeys-lru
监控与运维
# 查看内存使用
INFO memory
# 查看命令统计
INFO stats
# 慢查询监控
SLOWLOG GET 10
# 实时监控
MONITOR # 生产环境慎用
Redis 是高性能系统的必备技能,深入理解能帮你设计更优秀的架构!
标签:Redis,缓存,高并发,系统架构
为你推荐
暂无相关推荐

评论 0