Redis--高并发问题:缓存穿透、缓存击穿、缓存雪崩与数据库缓存双写不一致

📅 2026/7/24 13:04:44 👁️ 阅读次数 📝 编程学习
Redis--高并发问题:缓存穿透、缓存击穿、缓存雪崩与数据库缓存双写不一致

Redis的高并发问题

Redis做缓存虽然减轻了DBMS的压力,但在高并发情况下也可能会出现问题。

缓存穿透

当请求的数据既不在缓存也不在数据库(比如查询民族是阿凡达的人口总数),就会导致每个查询都会“穿透”缓存“直抵数据库”,这种情况称为缓存穿透。

缓存穿透不仅增加了响应时间,而且还会引发对DBMS的高并发查询,这很可能导致DBMS的崩溃。

缓存穿透的原因有两个:

  • 数据库种没有相应的查询结果
  • 查询结果为空时不进行缓存。

那么解决方案也有两个:

  • 对非法请求进行限制
  • 对结果为空的查询给出默认值

缓存击穿

对于某个缓存,在高并发情况下访问量巨大,当缓存过期时,出现大量访问要到数据库中进行查询,导致DBMS崩溃,这种情况称为缓存击穿,该缓存数据称为热点数据。

其解决方案是使用“双重检测锁”机制。

// 双重检测锁就是先判断、再加锁、再判断,把性能和安全兼顾。public static Singleton getInstance() {// 第一次检测:不为空直接返回,不加锁(性能优化)if (instance == null) {synchronized (Singleton.class) {// 第二次检测:防止多个线程同时进入外层判断if (instance == null) {instance = new Singleton();}}}return instance;}

缓存雪崩

由于缓存中的数据,很多是有过期时间的。若大量缓存在同一很短时间内全部过期,那么在高并发场景下可能会对DBMS的高并发发起查询。这会导致DBMS崩溃,这种情况称为缓存雪崩。

缓存雪崩没有很直接的解决方案,最好的方案就是预防,就是提前规划好过期时间。

要么让缓存永久有效,当DB数据发生变化时清楚缓存。

如果DBMS是分布式部署,就将热点数据均匀分步在不同的数据库节点,将可能到来的访问分散开。

数据库缓存双写不一致

以下两种场景下均可能发生此问题:

  • “修改DB更新缓存”场景

    对于具有缓存warmup功能的系统,数据变更会更新缓存(不是删除缓存)。

    在高并发写请求的场景下数据库与缓存中数据不一致。

无标题

  • “修改DB删除缓存”场景

    没有缓存warmup功能的,对数据库执行写操作后,会删除缓存。

无标2题

上面这个图画的不好。

解决方案:延迟双删

延迟双删专门针对“修改DB删除缓存”场景的解决方案,此方案不能彻底解决数据不一致的问题,只会降低发生问题的概率。

延迟双删:写操作完成后立即执行删除缓存操作,然后停止一段时间(一般几秒钟)后再删除一次。

两次删除中间的间隔时长要大于一次缓存写操作的时长。

无3标题

解决方案:队列

将请求写入一个队列,一个请求处理完再出来下一个请求。

但是这样会使系统失去并发性,降低性能。

解决方案:分布式锁

通过对数据加锁来协调对其得到操作即可。这样不会影响并发,最终使数据库与缓存的数据达成一致性。