社区平台Redis测试实践(1),软件测试权限处理

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新软件测试全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上软件测试知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024b (备注软件测试)
img

正文

Redis常用数据结构

Redis常用的数据结构主要有以下5种:

二、Redis使用场景

缓存

如上图为雪球APP手机号验证码登录界面,输入手机号,点击发送验证码,手机会收到一条短信验证码信息。这里就用了Redis来存储验证码,并设置了过期时间为5分钟。

服务端验证码存储方法:

public void setAndExpireSmsVerificationCache(UcTelephone ucTelephone, SmsVerification smsVerification, int expireAt) {
String cacheKey = SmsCacheKeyEmum.SMS_VERIFICATION.key(ucTelephone.areaCode(), ucTelephone.number());
usercenterV4.setAndExpire(cacheKey, JsonUtils.write(smsVerification),expireAt);
}

Redis存储:

redis-cli -h ${host} -p p o r t t t l s m s : v e r i f i c a t i o n : 86 : {port} ttl sms:verification:86: portttlsms:verification:86:{tel}
300
redis-cli -h ${host} -p p o r t g e t s m s : v e r i f i c a t i o n : 86 : {port} get sms:verification:86: portgetsms:verification:86:{tel}
{“code”:“2294”,“createdAt”:“Jun 14, 2022 10:45:28 AM”,“times”:1,“verifyTimes”:0,“status”:false}

计数器

上图为雪球APP,关注用户功能,业务限制普通用户每天最多允许关注100个用户,超过则提示;

我们可以想象一下,服务端应该是有一个计数器,用户每关注成功一人,计数器+1;每次点击关注按钮,会先判断当前计数器是否超过100,超过则提示「你今天已关注100人,请改天再试」。

在本例中,查询Redis,用户uid1在2023-02-07的日关注数Redis的值,已达到100,所以当天无法继续关注用户。

redis-cli -h ${host} -p ${port} get DAILYFUSER_2023-02-07_uid1
100

如下为Redis计数服务端代码实现,因为是用String数据结构存储的,Redis提供了incr()接口来实现+1操作。

Long followerNum = JedisCluster.master().incr(RelationKeys.createrFollowDailyKey(follower.getId()));

分布式锁

实现分布式锁也是Redis非常常见的使用场景。

下面以雪球的直播业务为例来介绍。用户在雪球直播,需要创建直播间,业务上是一个用户只能创建一个直播间。在测试的过程中,发现存在这么一个问题:多个用户并发创建直播间时会存在Bug,不同的用户会同时创建成功同一个直播间。

如下图:

为了解决这个问题,可以使用Redis分布式锁,优化代码,代码片段如下:

其中实现分布式锁的核心方法是setexnx(),该方法最终调用的是Redis的 set Key Value EX seconds NX 命令,该命令只在Key不存在时才对Key进行设置操作,并返回OK。如上面代码所示如果setexnx返回结果不是OK,则表明锁已存在,那么本次加锁操作失败,业务报错。

这里有一个需要注意的是finally代码块最终会释放锁,那为什么在加锁的时候还要设置过期时间呢?这个主要是为了防止意外发生,程序在走到finally之前,比如程序退出,导致无法释放锁,所以设置了一个兜底的策略,60s后自动释放锁。

三、Redis测试案例

案例一:用户分组查询接口升级

项目背景:用户分组查询从原来的RPC接口升级为gRPC接口,升级前后业务逻辑需保持完全一致。

发现的问题:

在测试过程中,发现分组信息缓存失效后,分组信息无法正常加载。

问题产生原因:

通过分析得知,查询分组信息,首先会从Redis里查询用户的分组成员,当缓存无数据时,会从DB加载数据并回写到缓存。接下来对比下接口升级前后Redis里的数据。

升级前Redis里的分组数据:

/**升级前Redis value格式为:uid -> 创建时间时间戳取负值 **/
redis-cli -h ${host} -p ${port} zrange MEMBER_MEMBERLIST_GROUPID_3615231762_14257441 0 -1 withscores
9485866208 -1669558282413
7371699344 -1663674830000

升级后Redis里的分组数据:

/**升级后Redis value格式为:uid -> 创建时间时间戳 **/
redis-cli -h ${host} -p ${port} zrange MEMBER_MEMBERLIST_GROUPID_3615231762_14257441 0 -1 withscores
7371699344 1663674830000
9485866208 1669558282413

通过对比发现,分组信息的score值不一致。升级前score值为创建时间时间戳取负值,升级后score值为创建时间时间戳,没有对时间戳取负值,最终导致分组信息无法正常加载。

解决方案:

对创建时间戳取负值,保持与原有写入逻辑一致。

总结:对于此类问题,测试过程中不但需要关注Redis值是否写入了,还要保证数据格式的正确性,包括数据结构、字段类型以及各字段的写入格式。

案例二:个股页新帖流数据不更新

问题:

用户反馈,雪球个股页:中天科技(SH600522),新帖流数据不更新。

问题产生原因:

当天雪球内网出现短暂故障,个股页新帖流接口在设置了Redis值后,由于网络错误,导致缓存过期时间设置失败,缓存永不过期(正常情况缓存60s会过期),从而出现部分个股页新帖流下的帖子一直不更新。

参照下图,由于设置Redis值和设置Redis过期时间,不是原子操作,在极端情况下,确实会出现缓存没有过期时间的问题。那从QA的角度,如何避免这种问题呢?

解决方案:

1、Code Review阶段,关注代码里设置Redis值和缓存过期时间,是否使用原子操作,如String结构,可以直接使用setex命令。测试过程中要去关注系统是否会存在缓存过期时间设置失败的问题。

2、一旦发生了缓存过期时间设置失败的问题,是否有相应的应对方案。从测试的角度要多考虑不同场景下系统异常的处理方案,对于极端情况下会出现的缓存无过期时间,系统要增加缓存过期检查机制,对于没有过期时间的缓存,程序要有设置过期时间的机制等。

案例三:行情逐笔Redis大Key优化测试

测试分析:

1、Key读写方式的变化:从原来的读写一级Key变为二级Key,且Key的名称已被改变。

2、二级Key读写必然存在跨Key读写数据的场景,如何进行场景覆盖。 3、由于行情逐笔交易数据量较大,如何验证数据的准确性。

测试覆盖:

1、股票品类覆盖

按照股票品类维度划分,每个品类选择至少一支股票覆盖。

2、Redis Key值覆盖

此次优化,涉及到不同的Redis Key,如盘前:trade:ext_pre:{symbol},盘中:trade:{symbol},盘后:trade:ext_after:{symbol} 等共6类Redis Key。

3、相关业务回归

梳理相关涉及到的此次的Redis Key的相关业务,并进行测试覆盖。

因新老key数据量较大,通过如下脚本来验证数据量是否一致。

#!/bin/bash
key=KaTeX parse error: Expected group after '_' at position 24: …levelkey="shard_̲{key}"
/** 查询老key里的数据量**/
old=$(sh connect_redis.sh zcard ${key} | awk ’ $1>0{print KaTeX parse error: Expected 'EOF', got '}' at position 2: 1}̲') /** 查询新key里的…(sh connect_redis.sh zrange ${levelkey} 0 -1 | grep trade | grep -v zrange)
for var in ${list}
do
i=sh connect_redis.sh zcard ${var} | awk '$1>0{ print $1}'
sum= ( ( (( ((sum+ i ) ) d o n e i f [ ! − n " i)) done if [ ! -n " i))doneif[!n"old" ]
then
old=0
fi
if [ ! -n “$sum” ]
then
sum=0
fi
echo “原KEY数据总数” ${old}
echo “新KEY数据总数” ${sum}
if [ $old -eq $sum ]
then
echo “数据总数一致”
else
echo “数据总数不一致”
fi

风险评估:

测试通过后,接下来就会下掉对老Redis Key的读写。

1、如何确定没有别的业务在调用老的Key?

因行情服务较多,如何保证没有任何服务在调用老的Redis Key了,主要是从两个方面,一方面,开发从代码的角度梳理相关服务调用,测试从业务的角度梳理并进行覆盖;另一方面,为了防止有梳理遗漏的地方,可以通过Redis的访问日志,持续观察老Redis Key还有没有访问量。

2、如何将上线风险降到最低?

一是线上逐步放量,持续观察;二是增加新老服务开关,一旦出问题可以快速的切换到老服务。

通过以上案例,介绍了测试过程中曾踩过的一些比较典型的坑,以及相应的应对方案。总结下Redis测试的一些关注点:

1、缓存数据存储逻辑的合理性。缓存数据写入的正确性以及缓存的写入数据格式是否合理。

2、缓存读取逻辑的合理性。有缓存要优先读缓存,无缓存查询数据库,并回写缓存。

3、缓存更新逻辑的合理性。什么情况下要更新缓存,以及缓存失效后是否会更新缓存内容。

4、缓存时间设置的合理性。缓存时间设置太短,会导致频繁访问数据库;时间设置太长,一方面会占用过多内存,造成资源浪费;另一方面会造成用户访问到的一直是老数据。因此要根据业务数据的实际更新频次,设置合理的过期时间。

5、缓存数据是否会重复。同样的数据,应只存在一条,重复的数据会浪费资源。

四、Redis常见问题

Redis有一些比较经典的问题,如缓存穿透,缓存击穿和缓存雪崩。在介绍这几个概念之前,我们先来看一个正常的缓存模型。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注软件测试)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
四、Redis常见问题

Redis有一些比较经典的问题,如缓存穿透,缓存击穿和缓存雪崩。在介绍这几个概念之前,我们先来看一个正常的缓存模型。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注软件测试)
[外链图片转存中…(img-QQGPRrSX-1713590752284)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 30
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值