← 返回首页

缓存架构设计

📂 architecture ⏱ 2 min 243 words

缓存架构设计

多级缓存架构

多级缓存采用本地缓存 + 分布式缓存 + 数据库的分层策略,逐层过滤请求,减轻后端压力。

请求 → 本地缓存(L1) → Redis(L2) → 数据库(L3)
@Service
public class MultiLevelCacheService {

    private final Cache<String, Object> localCache;
    private final RedisTemplate<String, Object> redisTemplate;
    private final DataSource dataSource;

    public Object get(String key) {
        // L1: 本地缓存
        Object value = localCache.getIfPresent(key);
        if (value != null) return value;

        // L2: Redis分布式缓存
        value = redisTemplate.opsForValue().get(key);
        if (value != null) {
            localCache.put(key, value);
            return value;
        }

        // L3: 数据库回源
        value = dataSource.query(key);
        if (value != null) {
            redisTemplate.opsForValue().set(key, value, 30, TimeUnit.MINUTES);
            localCache.put(key, value);
        }
        return value;
    }
}

缓存穿透

缓存穿透指查询不存在的数据,每次都穿透到数据库。解决方案包括布隆过滤器和缓存空值。

@Component
public class BloomFilterCache {

    private final BloomFilter<String> bloomFilter = BloomFilter.create(
        Funnels.stringFunnel(StandardCharsets.UTF_8),
        1_000_000, 0.01
    );

    public Object get(String key) {
        if (!bloomFilter.mightContain(key)) {
            return null; // 布隆过滤器拦截
        }
        Object value = cache.get(key);
        if (value == null) {
            value = database.query(key);
            if (value == null) {
                cache.put(key, NULL_PLACEHOLDER, 5, TimeUnit.MINUTES);
            }
        }
        return value;
    }
}

缓存击穿

缓存击穿是热点Key过期瞬间大量请求直达数据库。通过互斥锁或永不过期+异步刷新解决。

public Object getWithMutex(String key) {
    Object value = cache.get(key);
    if (value != null) return value;

    String lockKey = "lock:" + key;
    if (redis.setIfAbsent(lockKey, "1", 10, TimeUnit.SECONDS)) {
        try {
            value = database.query(key);
            cache.put(key, value, 30, TimeUnit.MINUTES);
        } finally {
            redis.delete(lockKey);
        }
    } else {
        Thread.sleep(50);
        return getWithMutex(key);
    }
    return value;
}

缓存雪崩

缓存雪崩是大量Key同时过期或Redis宕机导致请求涌入数据库。采用随机过期时间和集群高可用策略。

public void setWithRandomTTL(String key, Object value, int baseTTL) {
    int randomTTL = baseTTL + ThreadLocalRandom.current().nextInt(300);
    redisTemplate.opsForValue().set(key, value, randomTTL, TimeUnit.SECONDS);
}

@Bean
public RedissonClient redissonClient() {
    Config config = new Config();
    config.useSentinelServers()
        .setMasterName("mymaster")
        .addSentinelAddress("redis1:26379", "redis2:26379", "redis3:26379");
    return Redisson.create(config);
}