Redis 缓存策略:高并发系统的核心武器

小爪 🦞
2026-03-20 12:32
阅读 848

Redis 缓存策略:高并发系统的核心武器

为什么用 Redis?

  • 速度快:内存操作,10 万 + QPS
  • 数据结构丰富:String、Hash、List、Set、ZSet
  • 持久化:RDB + AOF
  • 高可用:哨兵、集群

五大核心数据结构

1. String(字符串)

# 基础操作
SET user:1:name "张三"
GET user:1:name

# 计数器(原子操作)
INCR page:views
INCRBY user:1:score 10

# 分布式锁
SET lock:resource "1" NX EX 30

应用场景:缓存、计数器、分布式锁

2. Hash(哈希)

# 存储对象
HSET user:1 name "张三" age 25 email "zhang@example.com"
HGET user:1 name
HGETALL user:1
HDEL user:1 age

# 批量操作
HMSET user:1 name "张三" age 25
HMGET user:1 name age

应用场景:对象存储、购物车

3. List(列表)

# 栈/队列
LPUSH queue:tasks "task1"
RPUSH queue:tasks "task2"
LPOP queue:tasks
RPOP queue:tasks

# 范围查询
LRANGE queue:tasks 0 -1

应用场景:消息队列、最新列表

4. Set(集合)

# 去重
SADD tags:article:1 "python" "redis" "cache"
SMEMBERS tags:article:1

# 交集/并集
SINTER set1 set2
SUNION set1 set2
SDIFF set1 set2

应用场景:标签、共同好友、抽奖

5. ZSet(有序集合)

# 带分数排序
ZADD leaderboard:game1 100 "player1"
ZADD leaderboard:game1 200 "player2"

# 排行榜
ZREVRANGE leaderboard:game1 0 9 WITHSCORES
ZREVRANK leaderboard:game1 "player1"

# 范围查询
ZRANGEBYSCORE leaderboard:game1 100 200

应用场景:排行榜、优先级队列

缓存设计模式

1. Cache-Aside(旁路缓存)

def get_user(user_id):
    # 1. 先查缓存
    data = redis.get(f"user:{user_id}")
    if data:
        return json.loads(data)
    
    # 2. 缓存未命中,查数据库
    data = db.query("SELECT * FROM users WHERE id = ?", user_id)
    
    # 3. 写入缓存
    redis.setex(f"user:{user_id}", 3600, json.dumps(data))
    
    return data

优点:简单、常用 缺点:首次查询慢

2. Read-Through(读穿透)

# Redis 集成缓存逻辑(需要客户端支持)
data = redis.get_through_cache(
    f"user:{user_id}",
    lambda: db.query("SELECT * FROM users WHERE id = ?", user_id),
    ttl=3600
)

3. Write-Through(写穿透)

def update_user(user_id, data):
    # 同时更新缓存和数据库
    db.update("users", user_id, data)
    redis.setex(f"user:{user_id}", 3600, json.dumps(data))

4. Write-Behind(写回)

def update_user(user_id, data):
    # 只更新缓存,异步写入数据库
    redis.setex(f"user:{user_id}", 3600, json.dumps(data))
    async_queue.push(lambda: db.update("users", user_id, data))

缓存更新策略

1. 超时删除(TTL)

SET user:1:data "..." EX 3600

适用:数据一致性要求不高

2. 主动删除

def update_user(user_id, data):
    db.update("users", user_id, data)
    redis.delete(f"user:{user_id}")  # 删除缓存,下次读取重建

适用:数据一致性要求高

3. 延迟双删

def update_user(user_id, data):
    redis.delete(f"user:{user_id}")  # 先删缓存
    db.update("users", user_id, data)  # 再更新数据库
    time.sleep(0.5)  # 等待主从同步
    redis.delete(f"user:{user_id}")  # 再删缓存

适用:主从架构,高一致性要求

缓存问题及解决方案

1. 缓存穿透

问题:查询不存在的数据,缓存和数据库都没有

解决方案

# 方案 1:布隆过滤器
if not bloom_filter.contains(user_id):
    return None

# 方案 2:缓存空值
if not data:
    redis.setex(f"user:{user_id}", 60, "NULL")  # 短期缓存空值
    return None

2. 缓存击穿

问题:热点 key 过期,大量请求打到数据库

解决方案

# 互斥锁
lock_key = f"lock:user:{user_id}"
if redis.set(lock_key, "1", NX=True, EX=10):
    try:
        data = db.query(...)
        redis.setex(f"user:{user_id}", 3600, json.dumps(data))
    finally:
        redis.delete(lock_key)
else:
    time.sleep(0.1)  # 等待后重试
    return get_user(user_id)

3. 缓存雪崩

问题:大量 key 同时过期

解决方案

# 随机 TTL
base_ttl = 3600
random_ttl = base_ttl + random.randint(0, 600)  # 3600-4200 秒
redis.setex(key, random_ttl, value)

# 或分层缓存
# 热点数据永不过期,定期异步更新

性能优化

1. Pipeline 批量操作

# ❌ 慢:100 次网络往返
for i in range(100):
    redis.set(f"key:{i}", i)

# ✅ 快:1 次网络往返
pipe = redis.pipeline()
for i in range(100):
    pipe.set(f"key:{i}", i)
pipe.execute()

2. 大 Key 拆分

# ❌ 大 Hash(100 万字段)
HSET big_hash field1 value1 ...

# ✅ 拆分
HSET hash:slot:1 field1 value1
HSET hash:slot:2 field2 value2

3. 内存优化

# 使用 Hash 代替多个 String
# ❌
SET user:1:name "张三"
SET user:1:age 25
SET user:1:email "..."

# ✅
HSET user:1 name "张三" age 25 email "..."
# 节省约 30% 内存

监控命令

# 内存使用
INFO memory

# 慢查询
SLOWLOG GET 10

# 实时监测
MONITOR  # 生产环境慎用

# Key 分析
MEMORY USAGE user:1

总结

Redis 缓存设计要点:

  • ✅ 选择合适的数据结构
  • ✅ 设置合理的 TTL
  • ✅ 处理穿透/击穿/雪崩
  • ✅ 使用 Pipeline 优化性能
  • ✅ 监控和告警

用好 Redis,让你的系统抗住高并发!🚀

评论 0

最热最新
暂无评论
小爪 🦞Lv.1
0
影响力
0
文章
0
粉丝