JAVA全系列 教程
3762个小节阅读:7093k
目录
C语言快速入门
JAVA全系列 教程
面向对象的程序设计语言
Python全系列 教程
Python3.x版本,未来主流的版本
人工智能 教程
顺势而为,AI创新未来
大厂算法 教程
算法,程序员自我提升必经之路
C++ 教程
一门通用计算机编程语言
微服务 教程
目前业界流行的框架组合
web前端全系列 教程
通向WEB技术世界的钥匙
大数据全系列 教程
站在云端操控万千数据
AIGC全能工具班
A A
White Night
在我们的项目中,由于秒杀商品的缓存没有设置过期时间,所以雪崩的产生一定是因为Redis服务异常。
当Redis服务异常后,所有请求都访问数据库,造成数据库压力过大。我们的解决思路就是,监控查询数据库秒杀商品的方法,如果该方法的流量突然增加,不会是某件商品从缓存丢失,一定是Redis服务异常,此时我们对服务进行限流降级处理。
修改查询秒杀商品详情方法,因为Setinel只能将生产者方法作为资源进行防护,所以将从数据库查询秒杀商品的方法独立出来。
xxxxxxxxxx
public interface SeckillService {
/**
* 从数据库根据商品id查询秒杀商品
*/
SeckillGoods findSecillGoodsByMySql(Long goodsId);
}
public class SeckillServiceImpl implements SeckillService {
@Override
public SeckillGoods findSeckillGoodsByRedis(Long goodsId) {
// 布隆过滤器判断商品是否存在,如果不存在,直接返回空
if (!bitMapBloomFilter.contains(goodsId.toString())){
System.out.println("布隆过滤器判断商品不存在!");
return null;
}
// 1. 从redis中查询秒杀商品
SeckillGoods seckillGoods = (SeckillGoods) redisTemplate.boundHashOps("seckillGoods").get(goodsId);
// 2. 如果查到商品,返回
if (seckillGoods != null) {
System.out.println("从redis中查询秒杀商品");
return seckillGoods;
}
return null;
}
@Override
public SeckillGoods findSecillGoodsByMySql(Long goodsId) {
// 4. 如果该商品不在秒杀状态,返回null
QueryWrapper<SeckillGoods> queryWrapper = new QueryWrapper();
queryWrapper.eq("goodsId", goodsId);
SeckillGoods seckillGoodsMysql = seckillGoodsMapper.selectOne(queryWrapper);
System.out.println("从mysql中查询秒杀商品");
Date now = new Date();
if (seckillGoodsMysql == null
|| now.after(seckillGoodsMysql.getEndTime())
|| now.before(seckillGoodsMysql.getStartTime())
|| seckillGoodsMysql.getStockCount() <= 0){
return null;
}
// 5. 如果该商品在秒杀状态,将商品保存到redis中,并返回该商品
addRedisSeckillGoods(seckillGoodsMysql);
return seckillGoodsMysql;
}
}
修改查询秒杀商品详情的控制器方法
xxxxxxxxxx
/**
* 用户查询秒杀商品详情
* @param id 商品id
* @return 查询结果
*/
@GetMapping("/findById")
public BaseResult<SeckillGoods> findById(Long id) {
// 从redis中查询秒杀商品详情
SeckillGoods seckillGoods = seckillService.findSeckillGoodsByRedis(id);
if (seckillGoods != null){
return BaseResult.ok(seckillGoods);
}else {
// 如果redis中查找不到,再从数据库查询秒杀商品详情
SeckillGoods secillGoodsByMySql = seckillService.findSecillGoodsByMySql(id);
return BaseResult.ok(secillGoodsByMySql);
}
}
给从数据库查询秒杀商品详情方法设置Setinel资源
xxxxxxxxxx
@SentinelResource("findSecillGoodsByMySql")
@Override
public SeckillGoods findSecillGoodsByMySql(Long goodsId) {
// 4. 如果该商品不在秒杀状态,返回null
QueryWrapper<SeckillGoods> queryWrapper = new QueryWrapper();
queryWrapper.eq("goodsId", goodsId);
SeckillGoods seckillGoodsMysql = seckillGoodsMapper.selectOne(queryWrapper);
System.out.println("从mysql中查询秒杀商品");
Date now = new Date();
if (seckillGoodsMysql == null
|| now.after(seckillGoodsMysql.getEndTime())
|| now.before(seckillGoodsMysql.getStartTime())
|| seckillGoodsMysql.getStockCount() <= 0){
return null;
}
// 5. 如果该商品在秒杀状态,将商品保存到redis中,并返回该商品
addRedisSeckillGoods(seckillGoodsMysql);
return seckillGoodsMysql;
}