写在前面:
本文主要内容是从QA的角度,介绍Redis的特点、用法和测试角度。
对于读取数据,一般的方法是将数据存放在持久层中,可以采用直接文件存储或数据库存储。
而当数据量非常大的时候,磁盘的I/O读写速率就会成为性能的瓶颈点。
一方面可以通过优化数据库来提高性能;另一方面,可以增加缓存层,来打破瓶颈。
Redis的经验流程和思路大概:
把持久层中的数据,选取经常读取且变动不是很频繁的数据作为热点数据;
读数据时,首选访问缓存中是否存在所需数据,若存在,则直接读取;
若不存在,则去持久层查询,如果也不存在,则返回不存在;
若持久层中存在,则把数据写入缓存,且返回数据。
这里我们使用了Redis来做缓存中间件。Redis常用做缓存、计算器/限速器、好友关系、简单消息队列、Session共享等用途,其中缓存最为人熟知。
那为什么Redis会比较快?
1、Redis是纯内存操作,需要的时候需要我们手动持久化到硬盘中
2、Redis是单线程,从而避开了多线程中上下文频繁切换的操作
3、Redis数据结构简单、对数据的操作也比较简单
4、使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求
5、使用多路I/O复用模型,非阻塞I/O
利用缓存读写速度较快的特点,看上去似乎确实达到了提高读写速率的目的。实际中,对于数量量太大、访问频率很低、频繁变更的数据,不适合采用这种方式。也就是如果数据具有经常读取且变更不频繁的数据,采用这种方式可能可以提升较大的性能。
下面针对测试角度,讨论一些点
一、基本用法
(1)连接到Redis
linux命令:
redis-cli -h {host} -p {port} {command}
command包括
-a 带上配置的密码
-c 连接集群结点时使用,此选项可防止moved和ask异常
等等
(2)读数据
get key,key为具体的键名
(3)写数据
set key value [ex] [px] [nx|xx],key和value为具体的值
ex为键值设置秒级过期时间
px为键值设置毫秒级过期时间
nx键必须不存在,才可以设置成功,用于添加
xx与nx相反,键必须存在,才可以设置成功,用于更新
setnx、setex 与上面的nx、ex作用相同
(4)查询所有键
keys *
(5)键总数
dbsize
(6)删除键
del key [key...] ,key为具体的键名
二、功能测试
1.redis数据生效时,读取是否正确
2.redis数据不存在,能否正常从db中读取到正确的值,并正确写入Redis和返回给上层
3.数据在redis和db中都不存在时的表现是否正常
4.删除数据时,redis和db的数据是否一致
三、异常测试与性能测试
(1)缓存雪崩
缓存雪崩是指在我们设置缓存时采用了相同的过期时间或者其他情况,导致缓存在某一时刻同时失效,请求全部转发到DB,DB瞬时压力过重雪崩。
解决方案:
1.用加锁或者队列的方式保证缓存的单线程写,从而避免失效时大量的并发请求落到底层存储系统上。
2.将缓存失效时间分散开,比如我们可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。
(2)缓存击穿
对于一些设置了过期时间的key,如果这些key可能会在某些时间点被超高并发地访问,是一种非常“热点”的数据。这个时候,需要考虑一个问题:缓存被“击穿”的问题,这个和缓存雪崩的区别在于这里针对某一key缓存,前者则是很多key。
缓存在某个时间点过期的时候,恰好在这个时间点对这个Key有大量的并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。
解决方案:
使用互斥锁(mutex key),在缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用缓存工具的某些带成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法。
测试层面,可以模拟几种场景:
1.同一时间大量去请求”缓存中没有“且”数据库中有”的数据
2.同一时间大量去请求“缓存中没有”且“数据库中也没有”的数据
2.同一时间大量去请求“缓存中有”的数据
验证点是,接口能否成功正常响应以及响应时间是否符合性能要求。
网友评论