结论与实战教程:使用随机过期时间避免缓存雪崩,结合 Canal 实现数据一致性。设置键过期:SET key value EX 3600 * (1 + random(0,0.1));缓存雪崩解决方案:1. 预热缓存;2. 随机TTL;3. 互斥锁;数据一致性:双写一致性用 Canal 订阅 binlog 更新 Redis;代码示例:StringRedisTemplate.opsForValue().set(key, value, 3600 + (int)(Math.random()*300), TimeUnit.SECONDS); 这样解决雪崩和一致性问题。
来源1
缓存雪崩是指由于缓存中数据大批量到 期而导致后端数据库的请求量过大,从而导致数据库宕机。在 Redis 中,我们可以通过设置不同的过期时间来避免缓存雪崩。代码示例:public void set(String key, String value, long seconds) { redisTemplate.opsForValue().set(key, value, seconds + new Random().nextInt(300), TimeUnit.SECONDS); }
来源2
数据一致性问题:缓存与数据库双写模式容易不一致。解决方案:1. 先删缓存再更新数据库(不推荐);2. 先更新数据库再删缓存;3. 使用 Canal 监听 binlog 异步更新缓存。Canal 配置后,消费 binlog 事件:if (eventType == EventType.UPDATE) { redisTemplate.delete(oldKey); redisTemplate.opsForValue().set(newKey, newValue); }
来源3
Redis 过期策略有三种:定时删除、惰性删除、定期删除。实战中结合使用,避免内存泄漏。针对雪崩,加随机偏移: expireTime = baseExpire + random(0, expireWindow); 这样分散过期峰值。
来源4
解决缓存雪崩的完整方案:1. 给缓存设置不同 TTL,加入随机值;2. 缓存预热,启动时加载热点数据;3. 使用 Sentinel 高可用;4. 限流降级。代码:@Cacheable(value = "user", key = "#id", unless = "#result == null") public User getUser(Long id) { return userMapper.selectById(id); }
来源5
最终一致性方案:Update DB -> MQ -> Update Cache。使用 RocketMQ 确保消息不丢,消费者更新 Redis:@RocketMQMessageListener(topic = "cache-update") public void handle(String key) { redisTemplate.delete(key); }
来源6
FAQ:
Q: 缓存雪崩怎么彻底避免?
A: 随机 TTL + 预热 + 热点数据永不过期。
Q: 数据不一致怎么处理?
A: Canal + 异步更新,或延迟双删。
Q: Redis 内存不足怎么办?
A: 配置 maxmemory-policy allkeys-lru。
Q: 分布式锁怎么实现防雪崩?
A: setnx + lua 脚本原子操作。