今天分享一下FunTester测试框架对Redis数据库key-list数据操作的性能测试,分为添加、删除和组合测试。

场景

线上分成了三个测试场景:

  1. 往Redis添加一批key-list数据,然后并发去往每个key-list中添加元素。
  2. 基于1中的数据,并发去从key-valu中,获取并删除元素。
  3. 同时想Redis的key-list数据中添加和删除元素。(其中包含从列表头和列表尾添加和删除元素),思路中详细说明。

思路

由于测试Redis服务性能比较差,之前文章实测也就100 ~ 150的QPS,本次暂不对同一个key进行并发测试,每个线程拥有唯一的key。这样测试方案稍微复杂一点,用到了java.util.concurrent.atomic.AtomicInteger线程安全类。在每个多线程任务com.funtester.base.constaint.FixedThread实现类中多一个属性com.funtest.redis.RedisList01.FunTester#listName。

总体思路就是多线程+Redis连接池,每个线程拥有唯一不重复的key,然后不断执行三个测试场景中的操作。

对于第三个测试的场景,这里有必要说明一下测试用例:首先往数据库里面存在一些key和对应的List类型的value。然后我会从list的的头部添加一个元素a,然后我从list的尾部添加一个元素b,然后我从list的头部获取并删除一个元素c,从list尾部获取并删除一个元素d,最后我验证ac并且bd。

以下是三个测试场景的具体实现。由于功能重复性比较多,我会着重的讲第三个测试场景的实现和测试结果。前两个场景只分享一下测试的脚本和数据即可。

场景1

用例

class RedisList01 extends RedisBase {static AtomicInteger num = new AtomicInteger(0)static RedisBase drivepublic static void main(String[] args) {String host = "FunTester"int port = 6379drive = new RedisBase(host, port)int times = 400int thread = 20Constant.RUNUP_TIME = 0def tester = new FunTester(times)def task = new Concurrent(tester, thread, "redis测试实践,list添加测试")task.start()drive.close()}private static class FunTester extends FixedThread {String listName = DEFAULT_STRING + num.getAndIncrement()FunTester(int limit) {super(null, limit, true)}@Overrideprotected void doing() throws Exception {drive.lpush(listName, StringUtil.getString(10), StringUtil.getString(10), StringUtil.getString(10), StringUtil.getString(10), StringUtil.getString(10))}@OverrideThreadBase clone() {return new FunTester(this.limit)}}}

测试结果

此处省略进度条展示和图形化统计测试数据,只分享测试结果。table使用base64解码之后就是图形化测试结果,有兴趣的可以转一下看看分布图。

~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~ JSON ~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~
>  {
>  ① . "rt":165,
>  ① . "failRate":0.0,
>  ① . "threads":20,
>  ① . "deviation":"0.44%",
>  ① . "errorRate":0.0,
>  ① . "executeTotal":7899,
>  ① . "qps2":120.67464136761538,
>  ① . "total":7899,
>  ① . "qps":121.21212121212122,
>  ① . "startTime":"2021-09-16 16:05:22",
>  ① . "endTime":"2021-09-16 16:06:28",
>  ① . "mark":"redis测试实践,list添加测试161605",
>  ① . "table":"eJztkzsKwkAQhnshd5gDRIjBKscQLxBwwQU3SlZBS18oWptSPIFWYuFtAorHcESND8SNRt0gs/wwIcX830c2RgaUx2clLrfL8W4x2cynu9XSrHBZ367Wm9Hs+BpsC+pln7kl9TYjYzzvLDBZq3qSQZEL5kAzK5nP3Qp4DWFCKyuQxvVUHWoOwT047nJyeQuENIXbdGzLxscPWCQ9YTDExDJJd0sYdDDfbQqDNgZHH3Ou+lRjtLyLwdHDXKoGmMu4Ln44XqSJ1a0sfXmoKCOs06f9Edab5BHtLeaDu5KmcTa5vwIpx45l9ux//YdxMEwBBhmSIRnqxyBDMiRD/RhkSIZkqB+DDMmQDPVjkCEZkqF+DDJMZLgHx9E+BA=="
>  }
~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~ JSON ~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~

场景2

用例

class RedisList02 extends RedisBase {static AtomicInteger num = new AtomicInteger(0)static RedisBase drivepublic static void main(String[] args) {String host = "FunTester"int port = 6379drive = new RedisBase(host, port)int times = 400int thread = 20Constant.RUNUP_TIME = 0def tester = new FunTester(times)def task = new Concurrent(tester, thread, "redis测试实践,list从头获取并删除测试")task.start()drive.close()}private static class FunTester extends FixedThread {String listName = DEFAULT_STRING + num.getAndIncrement()FunTester(int limit) {super(null, limit, true)}@Overrideprotected void doing() throws Exception {drive.lpop(listName)}@OverrideThreadBase clone() {return new FunTester(this.limit)}}}

测试结果

~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~ JSON ~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~
>  {
>  ① . "rt":172,
>  ① . "failRate":0.0,
>  ① . "threads":20,
>  ① . "deviation":"0.25%",
>  ① . "errorRate":0.0,
>  ① . "executeTotal":7912,
>  ① . "qps2":115.98962074677847,
>  ① . "total":7912,
>  ① . "qps":116.27906976744185,
>  ① . "startTime":"2021-09-16 16:08:43",
>  ① . "endTime":"2021-09-16 16:09:51",
>  ① . "mark":"redis测试实践,list从头获取并删除测试161608",
>  ① . "table":"eJzj5VLAD4pSUzKLn23tfrF+6tN1815s36qTk1lc8mR339MlW170bX/aP+3pzm1POxa8nLkEokrByEChJKMoNTGFgMkKvFy8+G0PSi0uyM8rTlUIycxNtVKo0C1OLcpMzFHIK83VUajUzQU6LTGPkB2EXKGgkJuZpwAxy8rQxFght1gnN7HCysjMAsgkrJugLygFj6Z1ABFRPhm1ZdSWkW3Lo2ntQERzmx5NawYimDVUt+3RtEYgAlJNQISgWoAIzYcUuQDdGqifoNa0AhGCglqK227iKbyuhLsJn2Mosp56rh/0biXRV0SksKFJ8XINCmeM+nDUh6M+HHhnjPpw1IejPhx4Z4z6cNSHoz4ceGeM+nDUh6M+HHhn0NSHAKoNkl0="
>  }

场景3

class RedisList03 extends RedisBase {static AtomicInteger num = new AtomicInteger(0)static RedisBase drivepublic static void main(String[] args) {String host = "FunTester"int port = 6379drive = new RedisBase(host, port)int times = 100int thread = 20Constant.RUNUP_TIME = 0def tester = new FunTester(times)def task = new Concurrent(tester, thread, "redis测试实践,list从尾获取并删除测试")task.start()drive.close()}private static class FunTester extends FixedThread {String listName = DEFAULT_STRING + num.getAndIncrement()FunTester(int limit) {super(null, limit, true)}@Overrideprotected void doing() throws Exception {def a = Time.getTimeStamp() + StringUtil.getString(10)def b = Time.getTimeStamp() + StringUtil.getString(10)drive.lpush(listName, a)drive.rpush(listName, b)def c = drive.lpop(listName)def d = drive.rpop(listName)if (a != c || b != d) com.funtester.base.exception.FailException.fail(this.threadName + "验证失败!")}@OverrideThreadBase clone() {return new FunTester(this.limit)}}}

测试结果

进度条截取:

INFO-> redis测试实践,list从尾获取并删除测试进度:▍▍▍  5% ,当前QPS: 33
INFO-> redis测试实践,list从尾获取并删除测试进度:▍▍▍▍▍▍  10% ,当前QPS: 30
INFO-> redis测试实践,list从尾获取并删除测试进度:▍▍▍▍▍▍▍▍▍▍  15% ,当前QPS: 32
INFO-> redis测试实践,list从尾获取并删除测试进度:▍▍▍▍▍▍▍▍▍▍▍▍  19% ,当前QPS: 31
INFO-> redis测试实践,list从尾获取并删除测试进度:▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍  24% ,当前QPS: 31
INFO-> redis测试实践,list从尾获取并删除测试进度:▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍  28% ,当前QPS: 30

可以看出QPS大概是单独操作测试结果的1/4,比较符合预期。

QPS变化曲线图:


redis测试实践,list从尾获取并删除测试QPS变化曲线

测试结果:

~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~ JSON ~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~
>  {
>  ① . "rt":673,
>  ① . "failRate":0.0,
>  ① . "threads":20,
>  ① . "deviation":"0.55%",
>  ① . "errorRate":0.0,
>  ① . "executeTotal":1981,
>  ① . "qps2":29.55481291400609,
>  ① . "total":1981,
>  ① . "qps":29.71768202080238,
>  ① . "startTime":"2021-09-16 16:23:31",
>  ① . "endTime":"2021-09-16 16:24:38",
>  ① . "mark":"redis测试实践,list从尾获取并删除测试161623",
>  ① . "table":"eJzj5VLAD4pSUzKLn23tfrF+6tN1815s36qTk1lc8mR339MN+170bX/aP+3pzm1POxa8nLkEokrByEChJKMoNTGFgMkKvFy8+G0PSi0uyM8rTlUIycxNtVKo0C1OLcpMzFHIK83VUajUzQU6LTGPkB2EXKGgkJuZpwAxy8rU3Ewht1gnN7HCysLUGMgkrJugLygFj6Z1ABFRPhm1ZYjb8mhaIxABqSYgQlDNQASkWoAIZi0ltqPbAjW3FYgQVDsQoVlGMkXIdXCHoHqQ+g6h0OX43TkgDiTPR3CPoPpgEDiPYt9hzR7DiAL5cBA4Y9SHoz4c9eHAO2PUh6M+HPXhwDtj1IejPhz14cA7Y9SHoz4c9eHAO2PUh6M+HPXhwDuDpj4EAOQLudM="

响应时间分布图:

redis测试实践,list从尾获取并删除测试

总结

在写FunTester测试框架对Redis进行性能测试这个系列的过程中。有一些粉丝。跟我聊就是说问这个实际的应用场景是什么?因为在测试的过程中,很少有遇到Redis性能出现平静,或者说Redis性能需要调优的这样的情况。一般认为ready是性能非常快的,只有向cpu,内存,带宽会成为ready的平静。但是有些比较极端的情况下,像Redis的key分布以及Redis数据存储的设计,都会成为系统性能平静。我个人对ready的这类调油也没有什么经验。写这个教程呢,主要是因为开发对Redis存储设计的有了几种替代(解决)方案,需要性能测试工程师协助验证这几种方案的在不同场景下的性能指标。

最后: 可以关注公众号:伤心的辣条 ! 进去有许多资料共享!资料都是面试时面试官必问的知识点,也包括了很多测试行业常见知识,其中包括了有基础知识、Linux必备、Shell、互联网程序原理、Mysql数据库、抓包工具专题、接口测试工具、测试进阶-Python编程、Web自动化测试、APP自动化测试、接口自动化测试、测试高级持续集成、测试架构开发测试框架、性能测试、安全测试等。

如果我的博客对你有帮助、如果你喜欢我的博客内容,请 “点赞” “评论” “收藏” 一键三连哦!喜欢我们自动化的小伙伴们,可以加入我们的技术交流扣扣群:914172719(里面有超多学习资料免费分享哟)


好文推荐

转行面试,跳槽面试,软件测试人员都必须知道的这几种面试技巧!

面试经:一线城市搬砖!又面软件测试岗,5000就知足了…

面试官:工作三年,还来面初级测试?恐怕你的软件测试工程师的头衔要加双引号…

什么样的人适合从事软件测试工作?

那个准点下班的人,比我先升职了…

测试岗反复跳槽,跳着跳着就跳没了…

FunTester框架Redis性能测试之list操作相关推荐

  1. FunTester框架Redis性能测试之map INCR

    本篇文章接直接分享性能测试案例,分为map操作性和INCR操作. map 思路 设计了一个简单的测试场景,用户先往某个值为map类型数据里面放一个key-value数据,然后查询这个key的value ...

  2. FunTester框架Redis压测预备

    在超万字回顾FunTester的前世今生一文中我分享了FunTester测试框架一个优点:针对所有Java可实现的接口都能进行功能封装进而进行性能测试. 之前都已经分享过了HTTP协议.Socket协 ...

  3. 多测师肖sir__性能测试之jmeter操作(2)

    一.jmeter 介绍 1·.jmeter jmeter 性能测试工具,是apache组织开发基于java的压力测试工具. 2.jmeter 的特点 (1)jmeter可以对http和ftp 服务器进 ...

  4. redis提高oracle性能,redis性能分析与优化建议

    首先,并不是说redis是内存应用就完全没性能问题,用的不好,还是会出现各种状况,例如RDB频繁,碎片太多等. 性能分析 info信息: 在redis-cli进入登录界面后,输入info all,或者 ...

  5. 首长,Redis 性能优化十三条军规立好了,请过目~

    点击上方"芋道源码",选择"设为星标" 管她前浪,还是后浪? 能浪的浪,才是好浪! 每天 8:55 更新文章,每天掉亿点点头发... 源码精品专栏 原创 | J ...

  6. 首长,Redis性能优化十三条军规立好了,请过目~

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 前言 Redis作为高性能的内存数据库,在大数据量的情况下 ...

  7. Redis 性能问题分析(好文推荐)

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者: 刘思宁 整理:朱小厮 www.jianshu.com/p/ ...

  8. 硬货 | Redis 性能问题分析

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源:rrd.me/gteAC 在一些网络服务的系统中,Redis ...

  9. Redis为什么变慢了?一文讲透如何排查Redis性能问题 | 万字长文

    阅读本文大约需要 30 分钟. Redis 作为优秀的内存数据库,其拥有非常高的性能,单个实例的 OPS 能够达到 10W 左右.但也正因此如此,当我们在使用 Redis 时,如果发现操作延迟变大的情 ...

最新文章

  1. windows 下搭建python虚拟环境
  2. 我花了 8 小时,掌握了一下 Flutter | Flutter 中文站上线
  3. DCMTK:测试DcmSCPPool类,包括DcmSCP和DcmSCU交互
  4. 已有打开的与此 Command 相关联的 DataReader,必须首先将它关闭
  5. Linux下查看CPU使用率 --- top命令的使用
  6. 2022牛客寒假算法基础集训营4 签到题7题
  7. SDWebImage的简单使用
  8. E20170603-ts
  9. Qt qlabel 设置字体、大小、加粗等
  10. 译文 [ROM][多国语言][2015.06.11] Lenovo S750 (MTK6589) - andrea_d86-lenovos750-4.2.2
  11. 前端如何设置浏览器网页标签页前的小图标favicon.ico
  12. EXSI6怎么设置虚拟机从光驱启动
  13. html+css的音乐网站
  14. html自动调音量,HTML5 音量调节控件
  15. python的内置函数
  16. EasyCVR边缘计算网关助力安防视频场景化AI落地,让智能无处不在
  17. 《基于Python的大数据分析基础及实战》第一章
  18. 计算机知识高级试题,计算机高级技能证试题目计算机操作员高级理论知识复习.doc...
  19. php设置系统时区,php 设置时区
  20. Dava基础Day17

热门文章

  1. springboot酒店管理信息系统答辩PPT模板
  2. python图片顶端_用python进行图片整理
  3. java stream byte_乐字节-Java8新特性之Stream流(上)
  4. php 检测 变量是否设置,PHP中检测一个变量是否有设置的函数是什么?
  5. mysql的jar包文件在哪找_数据库的jar在哪找
  6. python获取交易软件数据_几行Python代码,轻松获取美股阿里巴巴的交易数据
  7. Python+OpenCV:基于SVM手写数据OCR(OCR of Hand-written Data using SVM)
  8. MFC m_pMainWnd
  9. 高并发架构系列:如何解决Redis雪崩、穿透、并发等5大难题
  10. 构建 Vue.js 2.0项目