Redis + Caffeine 多级缓存架构与分布式锁实战

Redis + Caffeine 多级缓存架构与分布式锁实战

Ethan
2025-06-05 发布 / 正在检测是否收录...

缓存是高并发系统的基石。单靠 Redis 已经不足以应对极致性能需求——本地缓存 + 分布式缓存的多级架构才是最优解。本文深入 Redis 核心机制、Caffeine 本地缓存、多级缓存设计和分布式锁实战。

Redis 核心数据结构与使用场景

数据结构底层实现典型场景
StringSDS缓存对象、计数器、分布式锁
Hashziplist / hashtable存储对象属性
Listquicklist消息队列、最新列表
Setinset / hashtable标签、共同好友
ZSetziplist / skiplist排行榜、延迟队列
Streamradix tree + listpack消息队列(支持消费组)

缓存穿透、击穿、雪崩:三板斧

1. 缓存穿透:查不存在的数据

// 布隆过滤器
BF.RESERVE userFilter 0.01 1000000
BF.ADD userFilter "user:999999"
// 查询前先判断布隆过滤器:不存在则直接拒绝

// 缓存空值
String value = redis.get(key);
if (value == null) {
    value = db.query(key);
    if (value == null) {
        redis.setex(key, 60, "NULL");   // 缓存空值 60 秒
        return null;
    }
    redis.set(key, value, 300);
}

2. 缓存击穿:热点 Key 过期

public String getWithMutex(String key) {
    String value = redis.get(key);
    if (value != null) return value;
    String lockKey = "lock:" + key;
    if (redis.setnx(lockKey, "1")) {
        redis.expire(lockKey, 10);
        try {
            value = db.query(key);
            redis.set(key, value, 300);
        } finally {
            redis.del(lockKey);
        }
        return value;
    } else {
        Thread.sleep(50);
        return getWithMutex(key);  // 递归重试
    }
}

3. 缓存雪崩:大量 Key 同时过期

// TTL 加随机偏移
int ttl = 300 + ThreadLocalRandom.current().nextInt(60);  // 300~360秒
redis.setex(key, ttl, value);

// 多级缓存兜底
public Object get(String key) {
    Object val = caffeine.get(key);          // L1: 本地缓存
    if (val != null) return val;
    val = redis.get(key);                    // L2: Redis
    if (val != null) {
        caffeine.put(key, val);              // 回填 L1
        return val;
    }
    val = db.query(key);                     // L3: 数据库
    redis.set(key, val, ttl + random(60));   // 回填 L2
    caffeine.put(key, val);                  // 回填 L1
    return val;
}

Caffeine 本地缓存配置

Cache<String, Object> cache = Caffeine.newBuilder()
    .maximumSize(10000)           // 最大条目数
    .expireAfterWrite(5, TimeUnit.MINUTES)
    .expireAfterAccess(3, TimeUnit.MINUTES)
    .recordStats()                // 开启统计(命中率监控)
    .build();

Redis 分布式锁:Redisson 实战

@Autowired private RedissonClient redisson;

public void processOrder(String orderId) {
    RLock lock = redisson.getLock("order:" + orderId);
    try {
        // 尝试加锁,最多等待 10 秒,锁 30 秒后自动释放
        if (lock.tryLock(10, 30, TimeUnit.SECONDS)) {
            // 业务逻辑
            orderService.process(orderId);
        }
    } finally {
        if (lock.isHeldByCurrentThread()) {
            lock.unlock();
        }
    }
}

// Redisson 的 WatchDog 机制:自动续期
// 如果业务还没执行完,WatchDog 每隔 10 秒自动续期到 30 秒

Redis 哨兵集群搭建

# sentinel.conf
sentinel monitor mymaster 192.168.1.10 6379 2  # 2 个哨兵同意才判定下线
sentinel down-after-milliseconds mymaster 5000   # 5 秒无响应判定主观下线
sentinel failover-timeout mymaster 60000         # 故障转移超时 60 秒
sentinel parallel-syncs mymaster 1               # 一次只同步一台新主库

总结

多级缓存架构的核心思想是"近处快,远处稳"。Caffeine 提供微秒级响应但空间有限,Redis 提供毫秒级响应且可共享,数据库是最后的兜底。分布式锁的关键在于原子性(SETNX)、防死锁(过期时间)、防误删(Lua 脚本校验值)和可重入(Redisson WatchDog)。

© 版权声明
THE END
喜欢就支持一下吧
点赞 1 分享 收藏

评论 (0)

取消

Warning: file_put_contents(/var/www/html/usr/cache/pagecache/38/38aaa421c8ba88f8151be540c6ea1edd.cache): failed to open stream: No such file or directory in /var/www/html/usr/plugins/PageCache/Plugin.php on line 188