性能测试分析案例-定位redis响应延迟

环境准备

预先安装 docker、sysstat 、git、make 等工具,如 apt install docker.io sysstat

操作和分析

案例由 Python 应用 +Redis 两部分组成。其中,Python 应用是一个基于 Flask 的应用,它会利用 Redis ,来管理应用程序的缓存,并对外提供三个 HTTP 接口:
/:返回 hello redis;
/init/:插入指定数量的缓存数据,如果不指定数量,默认的是 5000 条;
缓存的键格式为 uuid:
缓存的值为 good、bad 或 normal 三者之一
/get_cache/:查询指定值的缓存数据,并返回处理时间。其中,type_name 参数只支持 good, bad 和 normal(也就是找出具有相同 value 的 key 列表)。
案例需要两台虚拟机,其中一台用作案例分析的目标机器,运行 Flask 应用,它的 IP 地址是 xxx.xxx.xxx.xxx;而另一台作为客户端,请求缓存查询接口
性能测试分析案例-定位redis响应延迟_第1张图片
在第一个终端中,执行下面的命令,运行本次案例要分析的目标应用。正常情况下,你应该可以看到下面的输出:

# 注意下面的随机字符串是容器ID,每次运行均会不同,并且你不需要关注它
docker run --name=redis -itd -p 10000:80 feisky/redis-server

docker run --name=app --network=container:redis -itd feisky/redis-app

再运行 docker ps 命令,确认两个容器都处于运行(Up)状态:

docker ps

在这里插入图片描述
第二个终端,使用 curl 工具,访问应用首页。如果你看到 hello redis 的输出,说明应用正常启动:

curl http://xxx.xxx.xxx.xxx:10000/

在这里插入图片描述

继续在终端二中,执行下面的 curl 命令,来调用应用的 /init 接口,初始化 Redis 缓存,并且插入 5000 条缓存信息。这个过程比较慢,比如我的机器就花了十几分钟时间。耐心等一会儿后,你会看到下面这行输出:

# 案例插入5000条数据,在实践时可以根据磁盘的类型适当调整,比如使用SSD时可以调大,而HDD可以适当调
curl http://xxx.xxx.xxx.xxx:10000/init/5000

继续执行下一个命令,访问应用的缓存查询接口。如果一切正常,你会看到如下输出

curl http://xxx.xxx.xxx.xxx:10000/get_cache

在这里插入图片描述
这个接口调用居然要花3秒!这么长的响应时间,显然不能满足实际的应用需求。
要把 curl 命令放到一个循环里来执行。你可以在终端二中,继续执行下面的命令:

$ while true; do curl http://xxx.xxx.xxx.xxx:10000/get_cache; done

终端一中执行 top 命令,分析系统的 CPU 使用情况:
性能测试分析案例-定位redis响应延迟_第2张图片
CPU的 iowait 比较高,已经达到了 30%;而各个进程的 CPU 使用率都不太高,最高的 python 和 redis-server ,也分别只有 19和 12。
综合 top 的信息,最有嫌疑的就是 iowait。所以,接下来还是要继续分析,是不是 I/O 问题。
执行下面的 iostat 命令,查看有没有 I/O 性能问题:

iostat -d -x 1

在这里插入图片描述
磁盘 sda 每秒的写数据(wkB/s)为 1.3MB,I/O 使用率(%util)是 70。看来,虽然有些 I/O 操作,但并没导致磁盘的 I/O 瓶颈。

案例问题是从 Redis 缓存中查询数据慢。对查询来说,对应的 I/O 应该是磁盘的读操作,但刚才我们用 iostat 看到的却是写操作。虽说 I/O 本身并没有性能瓶颈,但这里的磁盘写也是比较奇怪的。为什么会有磁盘写呢?那我们就得知道,到底是哪个进程在写磁盘。
运行下面的 pidstat 命令

pidstat -d 1

在这里插入图片描述
I/O 最多的进程是 PID 为 4355的 redis-server,并且它也刚好是在写磁盘。这说明,确实是 redis-server 在进行磁盘写。
执行 strace 命令

strace -f -T -tt -p 4355

性能测试分析案例-定位redis响应延迟_第3张图片
运行 lsof 命令

lsof -p 4355

性能测试分析案例-定位redis响应延迟_第4张图片
描述符编号为 3 的是一个 pipe 管道,5 号是 eventpoll,7 号是一个普通文件,而 8 号是一个 TCP socket。
我们就找出了 Redis 正在进行写入的文件,也知道了产生大量 I/O 的原因。

你可能感兴趣的:(性能测试,性能测试小白,redis,性能优化)