FunTester框架Redis性能测试之list操作

1968 篇文章 51 订阅
1221 篇文章 21 订阅

在这里插入图片描述
今天分享一下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 drive

    public static void main(String[] args) {
        String host = "FunTester"
        int port = 6379
        drive = new RedisBase(host, port)
        int times = 400
        int thread = 20
        Constant.RUNUP_TIME = 0
        def 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)
        }

        @Override
        protected void doing() throws Exception {
            drive.lpush(listName, StringUtil.getString(10), StringUtil.getString(10), StringUtil.getString(10), StringUtil.getString(10), StringUtil.getString(10))
        }

        @Override
        ThreadBase 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 drive

    public static void main(String[] args) {
        String host = "FunTester"
        int port = 6379
        drive = new RedisBase(host, port)
        int times = 400
        int thread = 20
        Constant.RUNUP_TIME = 0
        def 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)
        }

        @Override
        protected void doing() throws Exception {
            drive.lpop(listName)
        }

        @Override
        ThreadBase 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 drive

    public static void main(String[] args) {
        String host = "FunTester"
        int port = 6379
        drive = new RedisBase(host, port)
        int times = 100
        int thread = 20
        Constant.RUNUP_TIME = 0
        def 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)
        }

        @Override
        protected 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 + "验证失败!")

        }

        @Override
        ThreadBase 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就知足了…

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

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

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

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

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值