缓存怎么测试
查询怎么测试缓存时,发现的⾮常棒的⽂章。以下为原⽂:
什么是缓存?
缓存是我们在⽣活中经常听到⼀个词,如 怎么清理浏览器的缓存, ⼿机空间不够了,得删除缓存, 硬盘的缓存是不是越⼤越好等等的问题;
其实这些 缓存可以分成3种:
⼀种指硬件上的,像硬盘缓存和CPU缓存;⼀种客户端缓存;
⼀种是指服务端缓存;后两种更像是⼀种技术或者是服务;
硬件缓存:指的是⼀块芯⽚,可以被集成到硬盘或者是CPU上。它的作⽤就是充当硬盘(CPU)与外界接⼝(通常是内存)之间的暂存器,利⽤缓存可以减轻系统的负荷,同时提⾼数据的传输速率;
客户端缓存:某些应⽤,如浏览器,X宝,X信等,为了实现能够快速响应⽤户的请求,会把⽤户之前浏览的东西(如图⽚等)存在本地;在下次访问时,如果本地的缓存⾥有请求的内容,那么就直接展⽰出来,不⽤再次向服务器请求;
服务端缓存:它与客户端缓存⽬的相同,只不过是站在服务器这边考虑的;如果每次接到客户端请求都要连接⼀次数据库,当⽤户请求多的时候,负载过⼤;这时可以把⼀些经常被请求的数据存放在内存中,当有请求时直接返回,不⽤经过数据库,这样就可以减轻数据库的负担;⼩结
缓存是临时存放数据(使⽤频繁的数据)的地⽅,介于外部请求和真实数据之间;为什么要⽤缓存
从⼀个⽤户的⾓度来看,体验最好的肯定是不管什么情况下,都能成功访问这个页⾯,并且打开的速度很快,也就是保证正常⼯作的前提下时间尽可能短;
如果没有缓存,我们的体验可能是这样的:
⽤户请求⼀个数据,这个数据得从数据库中去取,随着⽤户越来越多和数据量越来越⼤,每次⽤户请求的时间就会越来越长,⽽且数据库⽆时不刻都在⼯作;
这样⽤户和数据库都很痛苦,时间⼀长,就有可能发⽣下⾯两件事情:1)⽤户很烦,抱怨页⾯加载太慢或者打不开,最后放弃了这个应⽤;2)数据库满负荷⼯作,偶尔崩溃(导致页⾯错误);
分析原因:由于数据库的连接数和连接时长是有的,但请求过多,超出了数据库能承受的范围,导致数据库崩溃;那为什么不把⼀部分数据放在别的地⽅,这样有⽤户请求这些数据时,就不⽤从数据库中取了?
服务器缓存
⼯作原理
当客户端向服务器请求⼀个资源时,服务器⾸先在缓存中找,如果在缓存中,那么直接返回,不需要连接数据库;如果请求的资源不在缓存中,这时再去数据库中找,找到后返回给客户端,并将这个资源加⼊缓存中;
这样下次请求相同资源时,就不需要连接数据库了。⽽且如果把缓存放在内存中,因为对内存的操作要⽐对数据库操作快得多,这样请求时间也会缩短;
所以,通过使⽤缓存,就可以保证满⾜⽤户的需求,在正常⼯作的前提下响应时间尽可能短;特别需要注意缓存失效的场景,如:
数据库的数据已经更新了,那对应的缓存数据也要更新;缓存超过失效时间,需要重新发起请求来更新缓存;
缓存满了,⽐如缓存满了,重新发起请求,新的资源重新加⼊缓存,⼀般做法是把缓存⾥最旧的资源剔除,加⼊新的资源;
前端缓存
类型
缓存分为两类:强制缓存和协商缓存,定义如下:
强制缓存:客户端直接从缓存中读取数据,不与服务器作交互;
协商缓存:客户端发送特定的报⽂到服务器,服务器根据接收到的报⽂判断资源是否有更新,有则返回200和最新的资源⽂件,⽆则返回304使客户端从缓存中读取数据;缓存由什么决定?
缓存由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的缓存;解决热点数据集中失效问题
在设置缓存的时候,⼀般会给缓存设置⼀个失效时间,过了这个时间,缓存就失效了;
对于⼀些热点的数据来说,当缓存失效以后会存在⼤量的请求过来,然后打到数据库去,从⽽可能导致数据库崩溃的情况;解决办法
设置不同的失效时间;
采⽤缓存击穿的解决办法,加锁;
永不失效,就是采⽤定时任务对快要失效的缓存进⾏更新缓存和失效时间;
缓存的测试点
功能:
缓存是否可以正确被创建,包括位置、名字和内容;
缓存是否被清除,包括主动清楚以及被第三⽅发起的清除,清除后是否正常⼯作及清除失效的情况;
系统运⾏过程中,redis缓存数据⽣效、缓存的数据读取正确、数据写⼊落地正确,数据有效期设置合理;缓存与数据库的数据⼀致性检测;
DB事务性导致回滚,缓存是否回滚,有没有产⽣脏数据;缓存是否有⼤⼩,达到⼤⼩临界值如何处理;缓存时突然被中断,如何处理;缓存失效后,是否能正常表现;⾃动化:
⾃动化⽤例中断⾔部分设计缓存层断⾔并且⾃动化框架本⾝对于断层层次可配置;性能及稳定性:
关注业务本⾝应⽤场景及缓存结构,是否使⽤缓存;预防缓存穿透、缓存雪崩、缓存击穿引发的系统风险;扩容:
关注扩容⽅案设计、⽼数据备份策略、回滚⽅案;关注扩容后分⽚策略的变化;
扩容后热点数据失效率或命中率以及对后端DB带来的压⼒;环境:
⽆⽹络&有数据:
缓存⼤⼩未超过,缓存时间有效期内,显⽰缓存数据加载;
缓存⼤⼩超过,本地缓存数据删除,显⽰⽆⽹提⽰,⽆数据加载;缓存时间过期,本地缓存数据删除,显⽰⽆⽹提⽰,⽆数据加载;⽆⽹络&⽆数据:
显⽰⽆数据加载;有⽹络&有数据:
缓存⼤⼩未超过,缓存时间有校内,显⽰缓存数据加载;缓存⼤⼩超过了,本地缓存数据删除,直接从线上拉取数据;缓存时间过期,本地缓存数据删除,直接从线上拉取数据;有⽹络&⽆数据:
直接从线上拉取数据存到本地;缓存存储:
客户端安装后,有⽹络,开始存储数据到本地;覆盖安装,缓存数据依然存储在本地;
清除数据、卸载、重装,内存和本地缓存数据清零;异常情况:
由于⽹络原因缓存失败,则⽆法读取缓存数据;
由于服务器原因导致缓存失败,则⽆法取缓存数据;
终端本地的数据接近满值,内存被占⽤,⽆法读取缓存数据;设置的缓存⽂件夹和数据⽂件不可读写;缓存的刷新机制是否⼿动操作;