写点什么

你管这破玩意叫缓存穿透?还是缓存击穿?

  • 2023-05-15
    湖南
  • 本文字数:3371 字

    阅读完需:约 11 分钟

一、缓存预热

Redis 缓存预热是指在服务器启动或应用程序启动之前,将一些数据先存储到 Redis 中,以提高 Redis 的性能和数据一致性。这可以减少服务器在启动或应用程序启动时的数据传输量和延迟,从而提高应用程序的性能和可靠性。

1、缓存预热常见步骤

(1)数据准备

在应用程序启动或服务器启动之前,准备一些数据,这些数据可以是静态数据、缓存数据或其他需要预热的数据。


(2)数据存储

将数据存储到 Redis 中,可以使用 Redis 的列表(List)数据类型或集合(Set)数据类型。


(3)数据预热

在服务器启动或应用程序启动之前,将数据存储到 Redis 中。可以使用 Redis 的客户端工具或命令行工具来执行此操作。


(4)数据清洗

在服务器启动或应用程序启动之后,可能会对存储在 Redis 中的数据进行清洗和处理。例如,可以删除过期的数据、修改错误的数据等。


需要注意的是,Redis 缓存预热可能会增加服务器的开销,因此应该在必要时进行。同时,为了减少预热的次数,可以考虑使用 Redis 的其他数据类型,如哈希表(Hash)或有序集合(Sorted Set)。此外,为了提高数据一致性和性能,可以使用 Redis 的持久化功能,将数据存储到 Redis 中,并在服务器重启后自动恢复数据。

2、代码实现

@Component@Slf4jpublic class BloomFilterInit{    @Resource    private RedisTemplate redisTemplate;
//初始化白名单数据 @PostConstruct public void init() { //1 白名单客户加载到布隆过滤器 String key = "customer:1"; //2 计算hashValue,由于存在计算出来负数的可能,我们取绝对值 int hashValue = Math.abs(key.hashCode()); //3 通过hashValue和2的32次方后取余,获得对应的下标坑位 long index = (long)(hashValue % Math.pow(2,32)); log.info(key+" 对应的坑位index:{}",index); //4 设置redis里面的bitmap对应类型白名单:whitelistCustomer的坑位,将该值设置为1 redisTemplate.opsForValue().setBit("whitelistCustomer",index,true);
}}
复制代码

二、缓存雪崩

Redis 缓存雪崩是指在缓存系统中,由于某些原因,缓存的数据突然大量地被删除或修改,导致缓存系统的性能下降,甚至无法正常工作。

1、什么情况会发生缓存雪崩?

(1)误删除

由于误操作或故障,缓存系统可能会误删除一些正常的数据。这种情况通常会在数据库中发生。


(2)误修改

由于误操作或故障,缓存系统可能会误修改一些正常的数据。这种情况通常会在数据库中发生。


(3)负载波动

缓存系统通常会承受一定的负载波动,例如,在高峰期间,数据量可能会大幅增加,从而导致缓存系统的性能下降。


(4)数据变化频繁

如果缓存系统中的数据变化频繁,例如,每秒钟都会有大量的数据插入或删除,那么缓存系统可能会因为响应过慢而导致雪崩。

2、Redis 缓存集群实现高可用

(1)主从 + 哨兵

(2)Redis 集群

(3)开启 Redis 持久化机制 aof/rdb,尽快恢复缓存集群。

3、如何避免 Redis 缓存雪崩?

(1)数据备份

定期备份数据,以防止误删除或误修改。


(2)数据同步

定期同步数据,以防止数据不一致。


(3)负载均衡

使用负载均衡器将请求分配到多个 Redis 实例上,以减轻单个实例的负载。


(4)数据优化

优化数据库结构,减少数据变化频繁的情况。


(5)监控与告警

监控 Redis 实例的性能指标,及时发现缓存系统的异常,并发出告警。

三、缓存穿透

Redis 缓存穿透是指在 Redis 缓存系统中,由于某些原因,缓存的数据无法被正常访问或处理,导致缓存失去了它的作用。

1、什么情况会发生缓存穿透?

(1)数据量过大

当缓存中存储的数据量过大时,缓存的数据量可能会超过 Redis 的数据存储限制,从而导致缓存失去了它的作用。


(2)数据更新频繁

当缓存中存储的数据更新频繁时,缓存的数据可能会出现异步的变化,导致缓存无法被正常访问。


(3)数据过期

当缓存中存储的数据过期时,缓存的数据可能会失去它的作用,因为 Redis 会在一定时间后自动将过期的数据删除。


(4)数据权限限制

当缓存中存储的数据受到权限限制时,只有拥有足够权限的用户才能访问和处理这些数据,从而导致缓存失去了它的作用。


(5)Redis 性能瓶颈

当 Redis 服务器的性能达到极限时,Redis 缓存可能会因为响应过慢而导致穿透。

2、如何避免 Redis 缓存穿透?

(1)设置合理的缓存大小

根据实际需求设置合理的缓存大小,以避免缓存穿透。


(2)优化数据结构

根据实际需求优化数据结构,以减少数据的大小和更新频率。


(3)设置合理的过期时间

设置合理的过期时间,以避免缓存失去它的作用。


(4)增加 Redis 的并发处理能力

通过增加 Redis 的并发处理能力,以提高缓存的处理能力和响应速度。


(5)优化 Redis 服务器的硬件和软件配置

通过优化 Redis 服务器的硬件和软件配置,以提高 Redis 的性能和处理能力。

四、通过空对象缓存解决缓存穿透

如果发生了缓存穿透,可以针对要查询的数据,在 Redis 中插入一条数据,添加一个约定好的默认值,比如 defaultNull。


比如你想通过某个 id 查询某某订单,Redis 中没有,MySQL 中也没有,此时,就可以在 Redis 中插入一条,存为 defaultNull,下次再查询就有了,因为是提前约定好的,前端也明白是啥意思,一切 OK,岁月静好。

这种方式只能解决 key 相同的情况,如果 key 都不同,则完蛋。

五、Google 布隆过滤器 Guava 解决缓存穿透

1、引入 pom

<!--guava Google 开源的 Guava 中自带的布隆过滤器--><dependency>    <groupId>com.google.guava</groupId>    <artifactId>guava</artifactId>    <version>23.0</version></dependency>
复制代码

2、创建布隆过滤器

BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), 100);
复制代码

布隆过滤器中添加元素

bloomFilter.mightContain(1)
复制代码

判断布隆过滤器中是否存在

bloomFilter.mightContain(1)
复制代码

3、fpp 误判率

@Service@Slf4jpublic class GuavaBloomFilterService {    public static final int SIZE = 1000000;
//误判率 public static double fpp = 0.01;
//创建guava布隆过滤器 private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), SIZE, fpp); public void guavaBloomFilter() { for (int i = 1; i <= SIZE; i++) { bloomFilter.put(i); } ArrayList<Integer> list = new ArrayList<>(10000);
for (int i = SIZE + 1; i <= SIZE + (10000); i++) { if (bloomFilter.mightContain(i)) { log.info("被误判了:{}", i); list.add(i); } } log.info("误判总数量:{}", list.size()); }}
复制代码

六、Redis 缓存击穿

Redis 缓存击穿是指在 Redis 缓存系统中,由于某些原因,缓存的数据无法被正常访问或处理,导致缓存失去了它的作用。

1、什么情况会发生缓存击穿?

根本原因:热点 Key 失效


(1)数据量过大

当缓存中存储的数据量过大时,缓存的数据量可能会超过 Redis 的数据存储限制,从而导致缓存失去了它的作用。


(2)数据更新频繁

当缓存中存储的数据更新频繁时,缓存的数据可能会出现异步的变化,导致缓存无法被正常访问。


(3)数据过期

当缓存中存储的数据过期时,缓存的数据可能会失去它的作用,因为 Redis 会在一定时间后自动将过期的数据删除。


(4)数据权限限制

当缓存中存储的数据受到权限限制时,只有拥有足够权限的用户才能访问和处理这些数据,从而导致缓存失去了它的作用。


(5)Redis 性能瓶颈

当 Redis 服务器的性能达到极限时,Redis 缓存可能会因为响应过慢而导致击穿。

2、如何避免 Redis 缓存击穿?

(1)设置合理的缓存大小

根据实际需求设置合理的缓存大小,以避免缓存穿透。


(2)优化数据结构

根据实际需求优化数据结构,以减少数据的大小和更新频率。


(3)设置合理的过期时间

设置合理的过期时间,以避免缓存失去它的作用。


(4)增加 Redis 的并发处理能力

通过增加 Redis 的并发处理能力,以提高缓存的处理能力和响应速度。


(5)优化 Redis 服务器的硬件和软件配置

通过优化 Redis 服务器的硬件和软件配置,以提高 Redis 的性能和处理能力。

七、Redis 缓存击穿解决方案

1、互斥更新

通过双检加锁机制。

2、差异失效时间

先更新从缓存 B,再更新主缓存 A,而且让从缓存 B 的缓存失效时间长于 A,保证 A 失效时,B 还在。


作者:哪吒编程

链接:https://juejin.cn/post/7233052510553636901

来源:稀土掘金

用户头像

还未添加个人签名 2021-07-28 加入

公众号:该用户快成仙了

评论

发布
暂无评论
你管这破玩意叫缓存穿透?还是缓存击穿?_Java_做梦都在改BUG_InfoQ写作社区