一、缓存测试
缓存系统的使用,在一定程度上,极大的提升了应用程序的性能和效率,在秒杀系统的建设上,缓存系统出力不小,特别是数据查询方面,数据的快速返回广受好评。但同时,它也带来了一些问题,测试过程中,如果没有及时关注到缓存系统,整个测试环节是有遗漏的。缓存系统没有经过严格的测试,容易产生一个严重的问题,就是数据的一致性问题。如果没有对缓存系统进行测试,并且后端系统对数据的一致性要求很高,那么就不能使用缓存。
缓存的主要作用:是将业务系统的数据处理结果,暂时在内存中保存,并且等待下次访问的时候,立马从内存中取出。在日常开发场景中,因为服务器的性能或者自身业务对数据处理非常耗时的时候,当发现业务系统的数据请求量很大的时候,频繁的IO和频繁的逻辑处理会导致硬盘和CPU资源的瓶颈出现。应用缓存系统,就是将这些数据保存在内存中,当有其他线程或者客户端,查询相同的数据资源时,直接从缓存的内存中返回数据,这样不但可以提高系统的响应速度,同时也可以节省这些数据的处理流程及资源消耗,整体上来说,系统性能会有大大的提升。
二、redis介绍
首先对redis做一个简单的了解。
Redis数据类型:
Redis常用命令:
三、常见的缓存测试点
常见的缓存系统请求及数据返回流程:
在这请求过程中,我们经常会遇到的缓存测试点有:
·缓存数据更新:新增或者更新缓存数据,查看功能是否正确,查看数据是否正确
·缓存删除:缓存被删除之后,对业务系统的影响;缓存到了失效时间,是否根据缓存过期策略,被正确的删除;
·缓存穿透:缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。在流量大时,可能 数据库就挂掉了,要是有人利用不存在的 key 频繁攻击我们的应用,这就是漏洞。
·缓存雪崩:缓存雪崩是指在我们设置缓存时采用了相同的过期时间或者其他情况,导致缓存在某一时刻同时失效,请求全部转发到数据库,数据库瞬时压力过重雪崩。
·缓存服务停止:关闭缓存服务,查看系统运行情况
·缓存超时:缓存查询达到超时时间后,未返回指定数据,对系统的影响
·缓存数据恢复:缓存数据被误修改后,快速恢复到指定版本;缓存数据被误删除后,快速恢复数据
四、Redis测试场景实战
缓存穿透解决方案:
空值缓存,如果一个查询返回的数据为空,我们仍然把这个结果进行缓存,但它的过期时间会很短,最长不超过五分钟。 通过这个直接设置的默认值存放到redis中,这样第二次到缓冲中获取就有值了,而不会继续访问数据库。
方案代码:
/** * 缓存穿透 */ @Test void redisTest1(){ ValueOperations<String, String> operations = redisTemplate.opsForValue(); //1、从缓存中读取数据 String stringData = operations.get("HotWords"); if(StringUtils.isEmpty(stringData)){ //2、模拟从数据库中读取数据 String stringFromDB = queryFromDB(); if(StringUtils.isEmpty(stringFromDB)){ //库中没有此数据,存入一个空值,过期时间为5分钟 operations.set("HotWords","",5, TimeUnit.MINUTES); //返回数据,我这里是测试方法,所以返回空, return; }else{ operations.set("HotWords",stringFromDB); return; } } //缓存中有数据,直接返回 return; }
测试点:在审计开发代码时,需要关注开发对空值的处理,取出数据后先进行非空校验,如果数据是空的,设置临时缓存数据。
缓存雪崩解决方案:
设置不同的过期时间,让缓存失效的时间点尽量均匀。
方案代码:
@Test void redisTest1(){ ValueOperations<String, String> operations = redisTemplate.opsForValue(); //1、从缓存中读取数据 String stringData = operations.get("HotWords"); if(StringUtils.isEmpty(stringData)){ //2、模拟从数据库中读取数据 String stringFromDB = queryFromDB(); if(StringUtils.isEmpty(stringFromDB)){ //库中没有此数据,解决缓存穿透问题,存入一个空值,过期时间为5分钟 operations.set("HotWords","",5, TimeUnit.MINUTES); //返回数据,我这里是测试方法,所以返回空, return; }else{ //将数据写入缓存,并设置一个随机的过期时间,解决缓存雪崩问题 //生成0-1000之间的一个随机数,设置缓存随机在5-15个小时内过期 Random random = new Random(); int randomNum = random.nextInt(1000); operations.set("HotWords",stringFromDB,randomNum,TimeUnit.HOURS); return; } } //缓存中有数据,直接返回 return; }
测试点:避免大量缓存集中在一段时间内失效,则会出现大量缓存穿透,所有的查询都落在数据库上,造成了缓存雪崩。 由于原有缓存失效,新缓存未存储,原来应该访问redis的请求都去访问数据库了,所以需要随机设置过期时间。
作者:Henry
来源:http://www.51testing.com/html/52/n-4479252.html