1. 首页 > Redis教程 > 正文

Redis教程FG031-Redis缓存雪崩击穿穿透防范实战

本文档风哥主要介绍Redis缓存雪崩、击穿和穿透的防范实战,包括基础概念、防范策略、高可用性设计、监控与告警、实施方案、代码实现、测试与验证以及实战案例等内容,风哥教程参考Redis官方文档等内容编写,适合DBA人员和开发人员在生产环境中使用。

Part01-基础概念与理论知识

1.1 缓存雪崩

缓存雪崩是指在短时间内,大量缓存同时过期,导致所有请求都直接访问数据库,造成数据库压力骤增,甚至宕机的情况。

  • 原因:大量缓存同时过期,或Redis实例宕机
  • 影响:数据库压力骤增,可能导致数据库宕机
  • 防范:设置随机过期时间,使用多级缓存,确保Redis高可用

1.2 缓存击穿

缓存击穿是指一个热点Key过期,导致大量请求同时访问这个Key,直接访问数据库,造成数据库压力骤增的情况。

  • 原因:热点Key过期,或热点Key不存在
  • 影响:数据库压力骤增,可能导致数据库宕机
  • 防范:设置热点Key永不过期,使用互斥锁,预热热点数据

1.3 缓存穿透

缓存穿透是指请求一个不存在的数据,缓存和数据库都没有,导致每次请求都直接访问数据库,造成数据库压力骤增的情况。

  • 原因:请求不存在的数据,或恶意攻击
  • 影响:数据库压力骤增,可能导致数据库宕机
  • 防范:使用布隆过滤器,缓存空值,限流

更多视频教程www.fgedu.net.cn

Part02-生产环境规划与建议

2.1 防范策略

防范策略:

  • 缓存雪崩防范:
    • 设置随机过期时间,避免大量缓存同时过期
    • 使用多级缓存,如本地缓存 + Redis
    • 确保Redis高可用,如使用哨兵或集群模式
    • 缓存预热,提前加载热点数据
  • 缓存击穿防范:
    • 设置热点Key永不过期
    • 使用互斥锁,防止并发请求同时访问数据库
    • 预热热点数据
    • 使用读写分离,分散数据库压力
  • 缓存穿透防范:
    • 使用布隆过滤器,过滤不存在的数据
    • 缓存空值,避免重复访问数据库
    • 限流,防止恶意攻击
    • 参数校验,过滤非法请求

2.2 高可用性设计

# 高可用性设计

## 1. Redis高可用方案
– 主从复制:提供数据备份和读写分离
– 哨兵模式:自动故障转移
– 集群模式:数据分片和高可用

## 2. 多级缓存设计
– 本地缓存:如Guava Cache、Caffeine
– 分布式缓存:如Redis
– CDN缓存:静态资源缓存

## 3. 数据库高可用
– 主从复制:提供数据备份和读写分离
– 集群模式:如MySQL Cluster、PostgreSQL Cluster
– 读写分离:分散数据库压力

## 4. 服务高可用
– 负载均衡:如Nginx、HAProxy
– 服务集群:多实例部署
– 熔断降级:如Hystrix、Sentinel

2.3 监控与告警

# 监控与告警

## 1. Redis监控
– 内存使用:info memory
– 命令执行:info commandstats
– 慢查询:slowlog get
– 集群状态:cluster info

## 2. 数据库监控
– 连接数:show global status like ‘Threads_connected’
– 查询性能:show global status like ‘Queries’
– 锁等待:show global status like ‘Innodb_row_lock_waits’

## 3. 应用监控
– QPS:每秒查询数
– 响应时间:平均响应时间
– 错误率:请求错误率
– 缓存命中率:缓存命中次数 / 总请求次数

## 4. 告警机制
– 内存使用过高:超过80%
– 命令执行延迟:超过100ms
– 数据库连接数:超过最大值的80%
– 缓存命中率:低于90%

学习交流加群风哥QQ113257174

Part03-生产环境项目实施方案

3.1 实施方案

# 实施方案

## 1. 缓存雪崩防范
– 设置随机过期时间:在基础过期时间上增加随机值
– 实现多级缓存:本地缓存 + Redis
– 部署Redis高可用:哨兵或集群模式
– 缓存预热:系统启动时加载热点数据

## 2. 缓存击穿防范
– 热点Key永不过期:设置较长的过期时间或定期更新
– 实现互斥锁:使用Redis的setnx命令
– 预热热点数据:系统启动时加载热点数据
– 读写分离:主节点写,从节点读

## 3. 缓存穿透防范
– 实现布隆过滤器:过滤不存在的数据
– 缓存空值:对不存在的数据缓存空值,设置较短的过期时间
– 限流:对请求进行限流,防止恶意攻击
– 参数校验:过滤非法请求

## 4. 监控与告警
– 配置Prometheus监控Redis和数据库
– 配置Grafana面板,可视化监控数据
– 设置告警规则,及时发现问题
– 定期分析监控数据,优化缓存策略

3.2 代码实现

# 代码实现

## 1. 缓存雪崩防范
// 设置随机过期时间
public void setWithRandomExpire(String key, String value, int baseExpire) {
int randomExpire = baseExpire + new Random().nextInt(300); // 增加0-300秒的随机时间
redisTemplate.opsForValue().set(key, value, randomExpire, TimeUnit.SECONDS);
}

## 2. 缓存击穿防范
// 使用互斥锁
public String getWithLock(String key) {
String value = redisTemplate.opsForValue().get(key);
if (value == null) {
String lockKey = “lock:” + key;
Boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, “1”, 5, TimeUnit.SECONDS);
if (locked != null && locked) {
try {
// 从数据库获取数据
value = getDataFromDB(key);
if (value != null) {
redisTemplate.opsForValue().set(key, value, 3600, TimeUnit.SECONDS);
}
} finally {
redisTemplate.delete(lockKey);
}
} else {
// 等待一段时间后重试
Thread.sleep(100);
return getWithLock(key);
}
}
return value;
}

## 3. 缓存穿透防范
// 使用布隆过滤器
private BloomFilter bloomFilter = BloomFilter.create(Funnels.stringFunnel(Charset.defaultCharset()), 1000000, 0.01);

public String getWithBloomFilter(String key) {
if (!bloomFilter.mightContain(key)) {
return null; // 不存在的数据,直接返回
}
String value = redisTemplate.opsForValue().get(key);
if (value == null) {
value = getDataFromDB(key);
if (value != null) {
redisTemplate.opsForValue().set(key, value, 3600, TimeUnit.SECONDS);
} else {
// 缓存空值,设置较短的过期时间
redisTemplate.opsForValue().set(key, “”, 60, TimeUnit.SECONDS);
}
}
return value;
}

3.3 测试与验证

# 测试与验证

## 1. 缓存雪崩测试
– 模拟大量缓存同时过期的情况
– 观察系统响应时间和数据库压力
– 验证多级缓存和随机过期时间的效果

## 2. 缓存击穿测试
– 模拟热点Key过期的情况
– 观察系统响应时间和数据库压力
– 验证互斥锁和热点Key永不过期的效果

## 3. 缓存穿透测试
– 模拟请求不存在的数据的情况
– 观察系统响应时间和数据库压力
– 验证布隆过滤器和缓存空值的效果

## 4. 性能测试
– 使用JMeter进行性能测试
– 测试不同场景下的系统性能
– 优化缓存策略,提高系统性能

风哥提示:Redis接口限流是保护系统的重要机制,合理的限流策略可以防止系统过载,确保系统的稳定性和可用性。在实际应用中,需要根据具体业务场景和数据特点,选择合适的限流算法和策略。

Part04-生产案例与实战讲解

4.1 缓存雪崩防范

# 缓存雪崩防范

## 1. 场景描述
– 电商系统,大量商品缓存同时过期
– 系统启动时,缓存未加载

## 2. 解决方案
– 设置随机过期时间
– 实现多级缓存
– 部署Redis高可用
– 缓存预热

## 3. 实战操作
# 设置随机过期时间
$ /redis/app/bin/redis-cli -h 192.168.1.100 -p 6379 -a fgedu@2026 set product:2001:info “{\”id\”:\”2001\”,\”name\”:\”iPhone 14\”,\”price\”:\”6999\”}” EX 3600
# 实际应用中,在代码中设置随机过期时间

# 实现多级缓存(使用Caffeine)
// Java代码
Cache localCache = Caffeine.newBuilder()
.expireAfterWrite(10, TimeUnit.MINUTES)
.maximumSize(1000)
.build();

// 获取数据
public String getProductInfo(String productId) {
String key = “product:” + productId + “:info”;
// 先从本地缓存获取
String value = localCache.getIfPresent(key);
if (value == null) {
// 从Redis获取
value = redisTemplate.opsForValue().get(key);
if (value != null) {
localCache.put(key, value);
} else {
// 从数据库获取
value = getDataFromDB(productId);
if (value != null) {
// 设置随机过期时间
int expire = 3600 + new Random().nextInt(300);
redisTemplate.opsForValue().set(key, value, expire, TimeUnit.SECONDS);
localCache.put(key, value);
}
}
}
return value;
}

## 4. 测试
$ ab -n 10000 -c 100 http://localhost:8080/product/info/2001

# 输出示例
Concurrency Level: 100
Time taken for tests: 1.234 seconds
Complete requests: 10000
Failed requests: 0
Total transferred: 1234567 bytes
HTML transferred: 123456 bytes
Requests per second: 8103.57 [#/sec] (mean)
Time per request: 12.345 [ms] (mean)
Time per request: 0.123 [ms] (mean, across all concurrent requests)
Transfer rate: 987.65 [Kbytes/sec] received

Connection Times (ms):
min mean[+/-sd] median max
Connect: 0 0 0.1 0 1
Processing: 5 12 2.3 12 20
Waiting: 5 12 2.3 12 20
Total: 5 12 2.3 12 21

4.2 缓存击穿防范

# 缓存击穿防范

## 1. 场景描述
– 热点商品,访问频率高
– 商品缓存过期

## 2. 解决方案
– 设置热点Key永不过期
– 使用互斥锁
– 预热热点数据

## 3. 实战操作
# 设置热点Key永不过期
$ /redis/app/bin/redis-cli -h 192.168.1.100 -p 6379 -a fgedu@2026 set product:hot:2001 “{\”id\”:\”2001\”,\”name\”:\”iPhone 14\”,\”price\”:\”6999\”}”

# 使用互斥锁获取热点数据
// Java代码
public String getHotProductInfo(String productId) {
String key = “product:hot:” + productId;
String value = redisTemplate.opsForValue().get(key);
if (value == null) {
String lockKey = “lock:product:hot:” + productId;
Boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, “1”, 5, TimeUnit.SECONDS);
if (locked != null && locked) {
try {
// 从数据库获取数据
value = getDataFromDB(productId);
if (value != null) {
// 设置永不过期(或较长的过期时间)
redisTemplate.opsForValue().set(key, value);
}
} finally {
redisTemplate.delete(lockKey);
}
} else {
// 等待一段时间后重试
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return getHotProductInfo(productId);
}
}
return value;
}

# 预热热点数据
// 系统启动时预热热点数据
@PostConstruct
public void warmupHotProducts() {
List hotProductIds = Arrays.asList(“2001”, “2002”, “2003”);
for (String productId : hotProductIds) {
String value = getDataFromDB(productId);
if (value != null) {
String key = “product:hot:” + productId;
redisTemplate.opsForValue().set(key, value);
}
}
}

## 4. 测试
$ ab -n 10000 -c 100 http://localhost:8080/product/hot/2001

# 输出示例
Concurrency Level: 100
Time taken for tests: 0.876 seconds
Complete requests: 10000
Failed requests: 0
Total transferred: 1234567 bytes
HTML transferred: 123456 bytes
Requests per second: 11415.53 [#/sec] (mean)
Time per request: 8.760 [ms] (mean)
Time per request: 0.088 [ms] (mean, across all concurrent requests)
Transfer rate: 1376.45 [Kbytes/sec] received

Connection Times (ms):
min mean[+/-sd] median max
Connect: 0 0 0.1 0 1
Processing: 3 8 1.5 8 15
Waiting: 3 8 1.5 8 15
Total: 3 8 1.5 8 16

4.3 缓存穿透防范

# 缓存穿透防范

## 1. 场景描述
– 恶意请求不存在的商品ID
– 系统遭受大量无效请求

## 2. 解决方案
– 使用布隆过滤器
– 缓存空值
– 限流

## 3. 实战操作
# 使用布隆过滤器
// 初始化布隆过滤器
private BloomFilter bloomFilter = BloomFilter.create(Funnels.stringFunnel(Charset.defaultCharset()), 1000000, 0.01);

// 加载商品ID到布隆过滤器
@PostConstruct
public void initBloomFilter() {
List productIds = getProductIdsFromDB();
for (String productId : productIds) {
bloomFilter.put(productId);
}
}

// 使用布隆过滤器获取数据
public String getProductInfoWithBloomFilter(String productId) {
if (!bloomFilter.mightContain(productId)) {
return null; // 不存在的数据,直接返回
}
String key = “product:” + productId + “:info”;
String value = redisTemplate.opsForValue().get(key);
if (value == null) {
// 从数据库获取数据
value = getDataFromDB(productId);
if (value != null) {
redisTemplate.opsForValue().set(key, value, 3600, TimeUnit.SECONDS);
} else {
// 缓存空值,设置较短的过期时间
redisTemplate.opsForValue().set(key, “”, 60, TimeUnit.SECONDS);
}
}
return value;
}

# 限流
// 使用Redis实现限流
public boolean isAllowed(String key, int limit, int window) {
String limitKey = “limit:” + key;
Long current = redisTemplate.opsForValue().increment(limitKey);
if (current == 1) {
redisTemplate.expire(limitKey, window, TimeUnit.SECONDS);
}
return current <= limit; } // 在请求处理前进行限流 public String handleRequest(String productId) { if (!isAllowed("product:" + productId, 100, 60)) { return "Too many requests"; } return getProductInfoWithBloomFilter(productId); } ## 4. 测试 $ ab -n 10000 -c 100 http://localhost:8080/product/info/999999 # 输出示例 Concurrency Level: 100 Time taken for tests: 0.567 seconds Complete requests: 10000 Failed requests: 0 Total transferred: 1234567 bytes HTML transferred: 123456 bytes Requests per second: 17636.68 [#/sec] (mean) Time per request: 5.670 [ms] (mean) Time per request: 0.057 [ms] (mean, across all concurrent requests) Transfer rate: 2134.56 [Kbytes/sec] received Connection Times (ms): min mean[+/-sd] median max Connect: 0 0 0.1 0 1 Processing: 2 5 1.0 5 10 Waiting: 2 5 1.0 5 10 Total: 2 5 1.0 5 11

更多学习教程公众号风哥教程itpux_com

Part05-风哥经验总结与分享

5.1 最佳实践

Redis缓存雪崩击穿穿透防范实战最佳实践:

  • 综合防范:结合多种防范策略,提高系统的稳定性,学习交流加群风哥微信: itpux-com
  • 热点数据处理:对热点数据进行特殊处理,如永不过期、预热等
  • 多级缓存:使用本地缓存 + Redis,减轻Redis的压力
  • 高可用设计:确保Redis和数据库的高可用性
  • 监控与告警:建立完善的监控和告警机制,及时发现问题
  • 性能测试:定期进行性能测试,优化缓存策略
  • 安全防护:防止恶意攻击,如限流、参数校验等
  • 持续优化:根据实际情况,持续优化缓存策略

5.2 常见问题

常见问题及解决:

  • 缓存雪崩:设置随机过期时间,使用多级缓存,确保Redis高可用
  • 缓存击穿:设置热点Key永不过期,使用互斥锁,预热热点数据
  • 缓存穿透:使用布隆过滤器,缓存空值,限流
  • 性能下降:优化缓存策略,使用多级缓存,合理设置过期时间
  • 内存使用过高:合理设置缓存大小,定期清理过期数据
  • 监控不到位:配置完善的监控系统,及时发现问题

5.3 优化技巧

风哥提示:Redis缓存雪崩、击穿和穿透是缓存使用中的常见问题,合理的防范策略可以提高系统的稳定性和性能。在实际应用中,需要根据具体业务场景和数据特点,选择合适的防范策略。

# 优化技巧

## 1. 缓存策略优化
– 根据数据特点选择合适的缓存策略
– 合理设置过期时间,避免大量缓存同时过期
– 对热点数据进行特殊处理,如永不过期、预热等
– 使用多级缓存,减轻Redis的压力

## 2. 高可用性优化
– 部署Redis高可用方案,如哨兵或集群模式
– 确保数据库的高可用性,如主从复制、集群等
– 实现服务的高可用,如负载均衡、服务集群等

## 3. 性能优化
– 优化Redis配置,提高性能
– 优化网络配置,减少网络延迟
– 优化应用代码,减少Redis的访问次数
– 合理使用Redis的高级数据结构

## 4. 安全防护
– 防止恶意攻击,如限流、参数校验等
– 使用布隆过滤器,过滤不存在的数据
– 缓存空值,避免重复访问数据库

## 5. 监控与告警
– 配置完善的监控系统,及时发现问题
– 设置合理的告警规则,及时处理问题
– 定期分析监控数据,优化缓存策略

通过本文档的学习,您应该掌握了Redis缓存雪崩、击穿和穿透的防范实战,能够在生产环境中实施有效的防范策略,提高系统的稳定性和性能。在实际应用中,需要根据具体业务场景和数据特点,选择合适的防范策略,确保系统的高效运行。

风哥提示:Redis缓存雪崩、击穿和穿透是缓存使用中的常见问题,合理的防范策略可以提高系统的稳定性和性能。在实际应用中,需要根据具体业务场景和数据特点,选择合适的防范策略。

from Redis视频:www.itpux.com

本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html

联系我们

在线咨询:点击这里给我发消息

微信号:itpux-com

工作日:9:30-18:30,节假日休息