分布式缓存实战:Redis与多级缓存架构的完整指南

分布式缓存实战:Redis与多级缓存架构的完整指南

大家好,我是迪哥。缓存是提升系统性能的关键组件,从本地缓存到分布式缓存,从 Redis 到多级缓存架构,我们经历了多次优化。今天就聊聊分布式缓存的最佳实践。

多级缓存架构

复制代码
┌─────────────────────────────────────────────────────────────┐
│                      多级缓存架构                            │
├─────────────────────────────────────────────────────────────┤
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐    │
│  │  本地缓存    │  │   Redis      │  │   数据库     │    │
│  │  Caffeine   │  │   分布式缓存  │  │   MySQL     │    │
│  └──────┬───────┘  └──────┬───────┘  └──────┬───────┘    │
│         │                 │                 │              │
│         ▼                 ▼                 ▼              │
│  ┌─────────────────────────────────────────────────────┐   │
│  │                   应用层                            │   │
│  └─────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────┘

本地缓存:Caffeine

配置示例

java 复制代码
@Configuration
public class CaffeineConfig {
    
    @Bean
    public Cache<String, Object> localCache() {
        return Caffeine.newBuilder()
            .initialCapacity(1000)
            .maximumSize(10000)
            .expireAfterWrite(10, TimeUnit.MINUTES)
            .expireAfterAccess(5, TimeUnit.MINUTES)
            .recordStats()
            .build();
    }
}

使用示例

java 复制代码
@Service
public class UserService {
    @Autowired
    private Cache<String, User> localCache;
    
    @Autowired
    private StringRedisTemplate redisTemplate;
    
    @Autowired
    private UserMapper userMapper;
    
    public User getUser(Long userId) {
        String key = "user:" + userId;
        
        // 1. 先查本地缓存
        User user = localCache.getIfPresent(key);
        if (user != null) {
            return user;
        }
        
        // 2. 再查 Redis
        String json = redisTemplate.opsForValue().get(key);
        if (json != null) {
            user = JSON.parseObject(json, User.class);
            localCache.put(key, user);
            return user;
        }
        
        // 3. 最后查数据库
        user = userMapper.selectById(userId);
        if (user != null) {
            redisTemplate.opsForValue().set(key, JSON.toJSONString(user), 30, TimeUnit.MINUTES);
            localCache.put(key, user);
        }
        
        return user;
    }
}

Redis 缓存优化

缓存策略

java 复制代码
public enum CacheStrategy {
    READ_THROUGH,    // 读穿透
    WRITE_THROUGH,   // 写穿透
    WRITE_BEHIND,    // 写回
    CACHE_ASIDE;     // 旁路缓存(最常用)
}

缓存更新模式

java 复制代码
@Service
public class CacheService {
    @Autowired
    private StringRedisTemplate redisTemplate;
    
    // 模式1:先更新数据库,再删除缓存
    public void updateUser1(User user) {
        userMapper.updateById(user);
        redisTemplate.delete("user:" + user.getId());
    }
    
    // 模式2:先删除缓存,再更新数据库
    public void updateUser2(User user) {
        redisTemplate.delete("user:" + user.getId());
        userMapper.updateById(user);
    }
    
    // 模式3:延迟双删(解决并发问题)
    @Async
    public void updateUser3(User user) {
        redisTemplate.delete("user:" + user.getId());
        userMapper.updateById(user);
        
        // 延迟一段时间后再次删除
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        redisTemplate.delete("user:" + user.getId());
    }
}

缓存问题解决

问题 1:缓存穿透

java 复制代码
// 使用布隆过滤器
@Component
public class BloomFilterService {
    private final BloomFilter<Long> userFilter;
    
    public BloomFilterService() {
        userFilter = BloomFilter.create(
            Funnels.longFunnel(),
            1000000,  // 预计元素数量
            0.01      // 误判率
        );
        
        // 初始化过滤器
        List<Long> userIds = userMapper.selectAllIds();
        userIds.forEach(userFilter::put);
    }
    
    public boolean mightContain(Long userId) {
        return userFilter.mightContain(userId);
    }
}

问题 2:缓存击穿

java 复制代码
@Service
public class ProductService {
    @Autowired
    private StringRedisTemplate redisTemplate;
    
    private final Map<String, Object> locks = new ConcurrentHashMap<>();
    
    public Product getProduct(Long productId) {
        String key = "product:" + productId;
        
        // 先查缓存
        String json = redisTemplate.opsForValue().get(key);
        if (json != null) {
            return JSON.parseObject(json, Product.class);
        }
        
        // 加锁,防止缓存击穿
        synchronized (locks.computeIfAbsent(key, k -> new Object())) {
            try {
                // 双重检查
                json = redisTemplate.opsForValue().get(key);
                if (json != null) {
                    return JSON.parseObject(json, Product.class);
                }
                
                // 查数据库
                Product product = productMapper.selectById(productId);
                if (product != null) {
                    redisTemplate.opsForValue().set(key, JSON.toJSONString(product), 5, TimeUnit.MINUTES);
                }
                return product;
            } finally {
                locks.remove(key);
            }
        }
    }
}

问题 3:缓存雪崩

java 复制代码
// 解决方案:设置随机过期时间
public void setCacheWithRandomTTL(String key, Object value) {
    int ttl = 30 + ThreadLocalRandom.current().nextInt(30); // 30-60分钟
    redisTemplate.opsForValue().set(key, JSON.toJSONString(value), ttl, TimeUnit.MINUTES);
}

最佳实践清单

维度 最佳实践
多级缓存 本地缓存 + Redis + 数据库
缓存策略 旁路缓存模式
更新模式 先更新数据库,再删除缓存
并发问题 延迟双删 + 分布式锁
监控 监控缓存命中率、热点Key

说到缓存,我家那只叫 Docker 的哈士奇最近学会了"缓存策略"------把喜欢的玩具藏在沙发底下(本地缓存),饿了才去狗粮碗(数据库)找吃的,这缓存命中率比我们的 Redis 还高 😂

我是迪哥,我们下期再见!

相关推荐
·薯条大王8 小时前
经济实惠玩云服务器|一台云服务器多人共用,子账号配置教程
java·linux·运维·服务器·汇编·c++·python
ZJH__GO11 小时前
网络编程v4pro--实现聊天室文件传输功能
java·服务器·网络·计算机网络
程序员黑豆11 小时前
Windows 系统 Java 环境变量配置全攻略:解决“不是内部或外部命令”
java·前端·ai编程
命运之光11 小时前
【C语言完整代码】就诊信息管理系统
java·c语言·开发语言
凤山老林11 小时前
Spring Boot @Async 线上实战:从默认配置到生产级线程池治理
java·spring boot·后端
marvelyu12 小时前
每天10分钟学会OceanBase系列(Day 20):跨机房容灾实战——构建多数据中心高可用架构
java·大数据·数据库
AI人工智能+电脑小能手13 小时前
大白话说Java设计模式-04-工厂方法模式(业务实战篇)
java·设计模式·工厂方法模式·架构设计·代码解耦
BUG指挥官13 小时前
Sa-Token和Spring Security对比
java·后端·spring
小当家.10513 小时前
深入理解 ReAct Agent:从原理到 Java 实战
java·react.js·agent·react·架构设计·agent设计
geminigoth14 小时前
Spring AI Alibaba 入门开发一(备份)
java·人工智能·spring