redis并发问题
Redis进阶——Redis并发问题
redis的并发问题有三种
- 雪崩
- 击穿
- 穿透
雪崩
原因:
- Redis热点数据同时过期,大量请求全部打到mysql,mysql宕机
- 单个Redis服务出现问题或重启
解决方案:
-
问题1:
为热点数据设置随机值,避免热点数据同时过期
-
问题2
配置Redis集群
注:
- 热点数据是指访问量特别大的数据
击穿
击穿(cache breakdown),指的是在缓存中没有找到所需要的数据,而查询数据库也无法获取数据的情况。
击穿,表示缓存层被破坏,无法提供数据。
原因:
大量并发请求访问Redis同一个数据,此时数据刚从数据库查出来,但还没有向Redis保存,有大量线程向数据库访问,导致Mysql压力过大
解决方案:
上双检索,实现线程同步执行
穿透
穿透(cache penetration),指的是请求的数据在缓存中未命中,并且在数据库中不存在。
穿透,表示数据库查询直接穿过缓存,直接访问后端存储系统(mysql)
原因:
大量数据访问Mysql没有的数据,Redis缓存无法命中,导致数据库压力过大,
解决方案:
- 在Redis保存空对象,并且给空对象设置过期时间
- 使用布隆过滤器筛掉不存在的数据
线程并发案例
案例采用编程时缓存,声明式缓存中的注解已经帮我们规避了redis的并发问题。
@Autowired
private RedisTemplate<String, Object> redisTemplate;
public static final String PREFIX="Food-";
@Override
public Food getFoodById(String id) {
ValueOperations<String, Object> ops = redisTemplate.opsForValue();
Food food = (Food) ops.get(PREFIX + id);
if (food!=null){
System.out.println("Redis查到,返回"+food);
return food;
}
if (food==null){
synchronized (this){
System.out.println("进入同步锁");
System.out.println(Thread.currentThread().getName());
food = (Food) ops.get(PREFIX + id);
if (food==null){
food = foodMapper.selectById(id);
if (food!=null){
System.out.println("MYSQL查到,返回"+food);
ops.set(PREFIX+id,food);
return food;
}else {
Food food1 = new Food();
ops.set(PREFIX+id,food1, 5,TimeUnit.SECONDS);
}
}
}
food = (Food) ops.get(PREFIX + id);
if (food!=null){
System.out.println("Redis查到,返回"+food);
return food;
}
}
System.out.println("MYSQL没有数据,返回null");
return null;
}
其中Redis的配置类可以在Redis基础知识中查看
总结:
本篇内容主要将了Redis在高并发中会遇到三种问题——雪崩、击穿、穿透,并对其原因和解决办法做了讲解。并给出了Redis高并发问题的编程式缓存的解决方案。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律