缓存及缓存测试点

缓存由http报文的内容决定,关系如下:

缓存由什么决定

max-age或者 expires都决定了缓存的过期时间,会使客户端再次请求数据时先判断缓存是否过期,未过期则直接从缓存中读取数据(强制缓存);

两者的区别是前者是个相对值,相对于客户端的时间,后者直接定义了截止时间,且相对于服务端的时间

协商缓存由 Last-Modified、 If-Modified-Since 或 ETag、 If-None-Match两组报文决定;

字段的意思分别如下:

  • Last-Modified:表示服务器上某文件最近的修改时间,存在于响应报文;
  • If-Modified-Since:值等于 Last-Modified,存在于请求报文,用于将 Last-Modified值返回给服务端作比较;

缓存的总体过程

首次请求资源:

缓存的总体过程-首次请求资源

非首次请求资源:

缓存的总体流程-非首次请求资源

在第一次请求资源后,浏览器会将资源连同响应报文一起缓存到本地,其中响应报文可能包含了关于缓存的头信息;

因而后续请求的时候,浏览器可以根据本地缓存的头信息知道资源的缓存决策,判断是否强制缓存,或者移交服务器判断是否协商缓存;


缓存穿透、缓存击穿、缓存雪崩

在服务器缓存里面,有3个特殊的名词:缓存穿透、缓存击穿、缓存雪崩

这3个到底是什么?

缓存穿透

正常情况下,查询的数据都存在,如果请求一个不存在的数据,也就是缓存和数据库都查不到这个数据,每次都会去数据库查询,这种查询不存在数据的现象称为缓存穿透;

穿透带来的问题

如果每次都拿一个不存在的id去查询数据库,可能会导致你的数据库压力增大;

如何发现缓存穿透

  • 业务的响应时间:可以借助ELK或其他监控系统,对业务的接口进行检测,原本缓存就是响应时间比较快的,如果经常超过阈值就一定会有所体现;
  • 总调用数、cache层命中数、storage层命中数

解决办法--缓存空值

之所以发生穿透,是因为缓存中没有存储这些数据的key,从而每次都查询数据库;

可以为这些key在缓存中设置对应的值为null,后面查询这个key的时候就不用查询数据库了;

当然为了健壮性,我们要对这些key设置过期时间,以防止真的有数据;

缓存击穿

在高并发的情况下,大量的请求同时查询同一个key时,此时这个key正好失效了或者不存在,就会导致同一时间,这些请求都会去查询数据库,这样的现象称为缓存击穿;

比如请求一些特殊字符,就会出现该情况;

引起的原因

  • 代码问题,比如保存到缓存时用的是固定值;
  • 恶意攻击,比如爬虫,在请求时传一些不正常的值;

带来的问题

会造成某一时刻数据库请求量过大;

解决办法

采用分布式锁,只有拿到锁的第一个线程去请求数据库,然后插入缓存,若其它线程获取锁失败,则等待一段时间后重试;

缓存雪崩

当某一时刻发生大规模的缓存失效的情况,比如缓存服务宕机了;

解决方法

跟缓存穿透一样加锁排队;

建立备份缓存,缓存A和缓存B,A设置超时时间,B不设置超时时间,先从A读缓存,A没有则读B,并且更新A和B的缓存;



留言