作为一个测试同学,被测系统架构中有使用到 redis 吗?对 redis 常见的故障有了解吗?又是如何进行测试的呢?
针对常见的 redis 面试问题,怎样才算一个高质量的回答呢,回答思路一般包括
一般对于测试同学来说,面试过程中不需要去了解 redis 的源码和实现方式(当然了解更好),但是对于相应故障场景及原因、解决方案是需要有所了解的。
定义: 由于原来的缓存数据失效,而新的缓存数据还没有更新到缓存中时,导致所有请求都直接去查询数据库,对数据库 CPU 和内存造成巨大压力,严重的会造成数据库宕机。从而形成一系列连锁反应,造成整个系统崩溃。
场景: 比如设置定时过期的数据使用定时任务刷新到缓存就有有可能造成缓存雪崩。假设现在有一个秒杀系统,如果所有首页的 Key 失效时间都是 12 小时,中午 12 点刷新的,零点有个秒杀活动大量用户涌入,假设当时每秒 6000 个请求,本来缓存在可以扛住每秒 5000 个请求,但是缓存当时所有的 Key 都失效了。此时 1 秒 6000 个请求全部落数据库,数据库必然扛不住,它会报一下警,真实情况可能 DBA 都没反应过来就直接挂了。此时,如果没用什么特别的方案来处理这个故障,DBA 很着急,重启数据库,但是数据库立马又被新的流量给打死了,这会导致一系列的服务请求数据库都会报错,形成雪崩效应。这就是我理解的缓存雪崩。
解决方案:
使用 BloomFilter 过滤器,BloomFilter 的特点是存在性检测,如果 BloomFilter 中不存在,那么数据一定不存在;如果 BloomFilter 中存在,实际数据也有可能会不存在;
延伸:布隆过滤器:布隆过滤器(Bloom Filter)的核心实现是一个超大的 bitmap 和 K 个哈希函数。当一个元素被加入集合时,通过K个散列函数将这个元素映射成一个位数组中的K个点,并把它们置为1。检索时,我们只要看看这些点是不是都是1就(大约)知道集合中有没有这个数据了:如果这些点有任何一个0,则被检元素一定不在;如果都是1,则被检元素很可能在。这就是布隆过滤器的基本思想。优点:空间效率和查询效率高,且不会漏判,但是会误判
在接口层增加校验,比如用户权限校验,参数做校验,不合法的参数直接代码 Return,比如:id 做基础校验,id <=0 的直接拦截等
从缓存取不到的数据,在数据库中也没有取到,可以将对应 Key 的 Value 对写为 null、网络错误、稍后重试等值。这样的值具体取啥看产品,或者具体场景,缓存有效时间可以设置短一些如 30 秒(设置太长会导致正常情况无法使用)
正常用户是不会在单秒内发起这么多次请求的,网关层 Nginx 有相关配置项,可以让运维对单个 IP 每秒访问次数超出阈值的 IP 都拉黑。
三者之间异同:三者都是因为缓存没有形成对数据库的有效保护,而导致请求直接到了数据库。不同点:缓存雪崩是大量缓存失效而导致一些列连锁反应;缓存穿透是针对不存在的数据,一般是恶意攻击;缓存击穿是针对具体的热点数据在高并发场景下瞬时失效的情况。以上缓存雪崩、缓存穿透、缓存击穿如何从 redis 本身的高可靠性的架构中去避免呢? 一般避免以上情况发生我们从三个时间段去分析:
tips:限流组件,是指设置每秒通过请求数的限流工具,一般在集群服务无法再继续扩容的时候使用。使用后可能导致部分请求不通过,但是只会影响一部分。
定义:缓存预热就是系统上线后,将相关的缓存数据直接加载到缓存系统。这样就可以避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题。用户可以直接查询事先被预热的缓存数据。
缓存更新除了缓存服务器自带的缓存失效策略之外 (Redis 默认的有 6 中策略可供选择),我们还可以根据具体的业务需求进行自定义的缓存淘汰,常见的策略有两种:
当访问量剧增、服务出现问题 (如响应时间慢或不响应) 或非核心服务影响到核心流程的性能时,即使是有损服务仍然需要保证服务还是可用的。系统可以根据一些关键数据进行自动降级,也可以配置开 关实现人工降级。降级的最终目的是保证核心服务可用,即使是有损的。但是核心服务是无法降级的 (如加入购物车、结算等主链路上的服务)。走降级!可以返回一些默认的值,或者友情提示,或者空白的值。只要保证数据库不挂,就能保证系统还可用,就只会影响部分体验问题。
主备:即主库和备库,备库只提供备份功能但不提供服务。有的公司可能是主备模式,这就需要 SRE 配合进行主备切换测试,验证应用服务系统架构设计中是否有主备切换的设计。
主从:主从都提供服务,主库进行写,从库进行读。这时候也需要考虑主从切换过程中,Master 是否正常切换为 Slave,且切换过程中写是否失败的情况。
更多内容可以学习《测试工程师 Python 工具开发实战》书籍、《大话性能测试 JMeter 实战》书籍