Redis 包括 redis-benchmark 实用程序,它模拟同时发送 M 个总查询的 N 个客户端执行的命令。redis-benchmark提供默认的一组测试,或者我们可以提供自定义的一组测试。

语法

redis 性能测试的基本命令如下:

1
redis-benchmark [option] [option value]

注意:该命令是在 redis 的目录下执行的,而不是 redis 客户端的内部指令。

可选参数如下所示:

序号 选项 描述 默认值
1 -h 指定服务器主机名 127.0.0.1
2 -p 指定服务器端口 6379
3 -s 指定服务器 socket
4 -c 指定并发连接数 50
5 -n 指定请求数 10000
6 -d 以字节的形式指定 SET/GET 值的数据大小 3
7 -k 1=keep alive 0=reconnect 1
8 -r SET/GET/INCR 使用随机 key, SADD 使用随机值
9 -P 通过管道传输 <numreq> 请求 1
10 -q 强制退出 redis。仅显示 query/sec 值
11 –csv 以 CSV 格式输出
12 -l(L 的小写字母) 生成循环,永久执行测试
13 -t 仅运行以逗号分隔的测试命令列表。
14 -I(i 的大写字母) Idle 模式。仅打开 N 个 idle 连接并等待。

运行测试的子集

以下实例我们使用了多个参数来测试 redis 性能:

1
2
3
$ redis-benchmark -h 127.0.0.1 -p 6379 -t set -n 2000000 -q

SET: 94670.08 requests per second, p50=0.279 msec

以上实例中主机为 127.0.0.1,端口号为 6379,执行的命令为 set,请求数为 2000000,通过 -q 参数让结果只显示每秒执行的请求数。

我们也可以对特定命令进行基准测试:

1
2
3
$ redis-benchmark -n 100000 -q script load "redis.call('set','foo','bar')"

script load redis.call('set','foo','bar'): 95877.28 requests per second, p50=0.263 msec

选择key空间的大小

默认情况下,基准测试针对单个 key 运行。在 Redis 中,这种综合基准测试与真实基准测试之间的差异并不大,因为它是内存系统,但是如果想要强调缓存未命中,以及模拟更真实的工作负载空间,我们可以手动设置更大的key空间。

我们可以使用 -r 开关自定义。例如,如果我们想运行一百万个 SET 操作,每个操作使用随机key,key的可能范围是10万个中的一个,命令如下:

1
2
3
4
5
6
$ redis-benchmark -t set -r 100000 -n 1000000 -q

SET: 103917.70 requests per second, p50=0.255 msec

$ redis-cli dbsize # 返回当前选定数据库中的key数
(integer) 100000

查看源码,发现-r指定了config.randomkeys_keyspacelen的值,随机值生成策略是这样的:

1
r = random() % config.randomkeys_keyspacelen;

其中,random()是linux的系统函数,能够随机生成 int 范围内的整数,然后,我们再将这个整数变成一个 12 位的字符串。

int整数范围:-2147483648~2147483647 ,最多10位数字,转成12位字符串,不足的补零。

image-20240408180425744

全部源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
static void randomizeClientKey(client c) {
size_t i;

for (i = 0; i < c->randlen; i++) {
char *p = c->randptr[i]+11;
size_t r = 0;
if (config.randomkeys_keyspacelen != 0)
r = random() % config.randomkeys_keyspacelen;
size_t j;

for (j = 0; j < 12; j++) {
*p = '0'+r%10;
r/=10;
p--;
}
}
}

使用 pipelining

默认情况下,每个客户端都是在一个请求完成之后才发送下一个请求 (benchmark 会模拟 50 个客户端除非使用 -c 指定特别的数量), 这意味着服务器几乎是按顺序读取每个客户端的命令。RTT也要付费!

真实世界会更复杂,Redis 支持 /topics/pipelining,使得可以一次性执行多条命令成为可能。 Redis pipelining 可以提高服务器的 TPS。

1
2
3
$ redis-benchmark -h 127.0.0.1 -p 6379 -n 2000000 -c 50 -t set -P 16 -q

SET: 1531393.62 requests per second, p50=0.407 msec

本机测试中,使用pipeline能够显著提升redis-benchmark的成绩(rps)

参考