Redis压测
测试命令
这条命令redis自带
redis-benchmark [option] [option value]
redis 性能测试工具可选参数如下所示:
序号 | 选项 | 描述 | 默认值 |
---|---|---|---|
1 | -h | 指定服务器主机名 | 127.0.0.1 |
2 | -p | 指定服务器端口 | 6379 |
3 | -s | 指定服务器 socket | |
4 | -c | 指定并发连接数 | 50 |
5 | -n | 指定请求数 | 10000 |
6 | -d | 以字节的形式指定 SET/GET 值的数据大小 | 2 |
7 | -k | 1=keep alive 0=reconnect | 1 |
8 | -r | SET/GET/INCR 使用随机 key, SADD 使用随机值 | |
9 | -P | 通过管道传输 请求 | 1 |
10 | -q | 强制退出 redis。仅显示 query/sec 值 | |
11 | –csv | 以 CSV 格式输出 | |
12 | -l | 生成循环,永久执行测试 | |
13 | -t | 仅运行以逗号分隔的测试命令列表。 | |
14 | -I | Idle 模式。仅打开 N 个 idle 连接并等待。 |
案例一 性能信息分析
机器配置
1.png
2.png
3.png
# 测试100个并发连接
# 一个并发连接有100000个请求
[root@node-a ~]# redis-benchmark -h 1.1.1.1 -p 6379 -c 100 -n 100000 -q
PING_INLINE: 94696.97 requests per second
PING_BULK: 116550.12 requests per second
SET: 121654.50 requests per second
GET: 121359.23 requests per second
INCR: 121065.38 requests per second
LPUSH: 122399.02 requests per second
RPUSH: 121802.68 requests per second
LPOP: 119189.52 requests per second
RPOP: 121654.50 requests per second
SADD: 121065.38 requests per second
HSET: 121802.68 requests per second
SPOP: 122399.02 requests per second
LPUSH (needed to benchmark LRANGE): 122850.12 requests per second
LRANGE_100 (first 100 elements): 59701.50 requests per second
LRANGE_300 (first 300 elements): 20088.39 requests per second
LRANGE_500 (first 450 elements): 13825.52 requests per second
LRANGE_600 (first 600 elements): 10363.77 requests per second
# 每秒处理87719个请求
MSET (10 keys): 87719.30 requests per second
set
[root@node-a ~]# redis-benchmark -h 1.1.1.1 -p 6379 -c 100 -n 100000 -t set
====== SET ======
10000 requests completed in 0.11 seconds
100 parallel clients
3 bytes payload
keep alive: 1
99.08% <= 1 milliseconds
100.00% <= 1 milliseconds
90090.09 requests per second
get
[root@node-a ~]# redis-benchmark -h 1.1.1.1 -p 6379 -c 100 -n 100000 -t get
====== GET ======
100000 requests completed in 1.03 seconds
100 parallel clients
3 bytes payload
keep alive: 1
99.87% <= 1 milliseconds
100.00% <= 1 milliseconds
96711.80 requests per second
pipelining
默认情况下,每个客户端都是在一个请求完成之后才发送下一个请求 (benchmark 会模拟 50 个客户端除非使用 -c 指定特别的数量), 这意味着服务器几乎是按顺序读取每个客户端的命令。Also RTT is payed as well.
真实世界会更复杂,Redis 支持 /topics/pipelining,使得可以一次性执行多条命令成为可能。 Redis pipelining 可以提高服务器的 TPS。 下面这个案例是在 Macbook air 11” 上使用 pipelining 组织 16 条命令的测试范例:
[root@node-a ~]# redis-benchmark -h 1.1.1.1 -p 6379 -n 100000 -t set,get -P 16
====== SET ======
100000 requests completed in 0.14 seconds
50 parallel clients
3 bytes payload
keep alive: 1
54.66% <= 1 milliseconds
100.00% <= 1 milliseconds
740740.69 requests per second
====== GET ======
100000 requests completed in 0.09 seconds
50 parallel clients
3 bytes payload
keep alive: 1
98.96% <= 1 milliseconds
100.00% <= 1 milliseconds
1063829.88 requests per second
小结
- Redis 是一个服务器:所有的命令都包含网络或 IPC 消耗。这意味着和它和 SQLite, Berkeley DB, Tokyo/Kyoto Cabinet 等比较起来无意义, 因为大部分的消耗都在网络协议上面。
- Redis 的大部分常用命令都有确认返回。有些数据存储系统则没有(比如 MongoDB 的写操作没有返回确认)。把 Redis 和其他单向调用命令存储系统比较意义不大。
- 简单的循环操作 Redis 其实不是对 Redis 进行基准测试,而是测试你的网络(或者 IPC)延迟。想要真正测试 Redis,需要使用多个连接(比如 redis-benchmark), 或者使用 pipelining 来聚合多个命令,另外还可以采用多线程或多进程。
- Redis 是一个内存数据库,同时提供一些可选的持久化功能。 如果你想和一个持久化服务器(MySQL, PostgreSQL 等等) 对比的话, 那你需要考虑启用 AOF 和适当的 fsync 策略。
- Redis 是单线程服务。它并没有设计为多 CPU 进行优化。如果想要从多核获取好处, 那就考虑启用多个实例吧。将单实例 Redis 和多线程数据库对比是不公平的。
影响 Redis 性能的因素
有几个因素直接决定 Redis 的性能。它们能够改变基准测试的结果, 所以我们必须注意到它们。一般情况下,Redis 默认参数已经可以提供足够的性能, 不需要调优。
-
网络带宽和延迟通常是最大短板。建议在基准测试之前使用 ping 来检查服务端到客户端的延迟。根据带宽,可以计算出最大吞吐量。 比如将 4 KB 的字符串塞入 Redis,吞吐量是 100000 q/s,那么实际需要 3.2 Gbits/s 的带宽,所以需要 10 GBits/s 网络连接, 1 Gbits/s 是不够的。 在很多线上服务中,Redis 吞吐会先被网络带宽限制住,而不是 CPU。 为了达到高吞吐量突破 TCP/IP 限制,最后采用 10 Gbits/s 的网卡, 或者多个 1 Gbits/s 网卡。
-
CPU 是另外一个重要的影响因素,由于是单线程模型,Redis 更喜欢大缓存快速 CPU, 而不是多核。这种场景下面,比较推荐 Intel CPU。AMD CPU 可能只有 Intel CPU 的一半性能(通过对 Nehalem EP/Westmere EP/Sandy 平台的对比)。 当其他条件相当时候,CPU 就成了 redis-benchmark 的限制因素。
-
在小对象存取时候,内存速度和带宽看上去不是很重要,但是对大对象(> 10 KB), 它就变得重要起来。不过通常情况下面,倒不至于为了优化 Redis 而购买更高性能的内存模块。
-
Redis 在 VM 上会变慢。虚拟化对普通操作会有额外的消耗,Redis 对系统调用和网络终端不会有太多的 overhead。建议把 Redis 运行在物理机器上, 特别是当你很在意延迟时候。在最先进的虚拟化设备(VMWare)上面,redis-benchmark 的测试结果比物理机器上慢了一倍,很多 CPU 时间被消费在系统调用和中断上面。
-
如果服务器和客户端都运行在同一个机器上面,那么 TCP/IP loopback 和 unix domain sockets 都可以使用。对 Linux 来说,使用 unix socket 可以比 TCP/IP loopback 快 50%。 默认 redis-benchmark 是使用 TCP/IP loopback。 当大量使用 pipelining 时候,unix domain sockets 的优势就不那么明显了。
-
当大量使用 pipelining 时候,unix domain sockets 的优势就不那么明显了。
-
当使用网络连接时,并且以太网网数据包在 1500 bytes 以下时, 将多条命令包装成 pipelining 可以大大提高效率。事实上,处理 10 bytes,100 bytes, 1000 bytes 的请求时候,吞吐量是差不多的,详细可以见下图。
-
在多核 CPU 服务器上面,Redis 的性能还依赖 NUMA 配置和 处理器绑定位置。 最明显的影响是 redis-benchmark 会随机使用 CPU 内核。为了获得精准的结果, 需要使用固定处理器工具(在 Linux 上可以使用 taskset 或 numactl)。 最有效的办法是将客户端和服务端分离到两个不同的 CPU 来高校使用三级缓存。 这里有一些使用 4 KB 数据 SET 的基准测试,针对三种 CPU(AMD Istanbul, Intel Nehalem EX, 和 Intel Westmere)使用不同的配置。请注意, 这不是针对 CPU 的测试。
-
在高配置下面,客户端的连接数也是一个重要的因素。得益于 epoll/kqueue, Redis 的事件循环具有相当可扩展性。Redis 已经在超过 60000 连接下面基准测试过, 仍然可以维持 50000 q/s。一条经验法则是,30000 的连接数只有 100 连接的一半吞吐量。 下面有一个关于连接数和吞吐量的测试。
-
在高配置下面,可以通过调优 NIC 来获得更高性能。最高性能在绑定 Rx/Tx 队列和 CPU 内核下面才能达到,还需要开启 RPS(网卡中断负载均衡)。更多信息可以在thread 。Jumbo frames 还可以在大对象使用时候获得更高性能。
-
在不同平台下面,Redis 可以被编译成不同的内存分配方式(libc malloc, jemalloc, tcmalloc),他们在不同速度、连续和非连续片段下会有不一样的表现。 如果你不是自己编译的 Redis,可以使用 INFO 命令来检查内存分配方式。 请注意,大部分基准测试不会长时间运行来感知不同分配模式下面的差异, 只能通过生产环境下面的 Redis 实例来查看。
其他需要注意的点
任何基准测试的一个重要目标是获得可重现的结果,这样才能将此和其他测试进行对比。
- 一个好的实践是尽可能在隔离的硬件上面测试。如果没法实现,那就需要检测 benchmark 没有受其他服务器活动影响。
- 有些配置(桌面环境和笔记本,有些服务器也会)会使用可变的 CPU 分配策略。 这种策略可以在 OS 层面配置。有些 CPU 型号相对其他能更好的调整 CPU 负载。 为了达到可重现的测试结果,最好在做基准测试时候设定 CPU 到最高使用限制。
- 一个重要因素是配置尽可能大内存,千万不要使用 SWAP。注意 32 位和 64 位 Redis 有不同的内存限制。
- 如果你计划在基准测试时候使用 RDB 或 AOF,请注意不要让系统同时有其他 I/O 操作。 避免将 RDB 或 AOF 文件放到 NAS 或 NFS 共享或其他依赖网络的存储设备上面(比如 Amazon EC2 上 的 EBS)。
- 将 Redis 日志级别设置到 warning 或者 notice。避免将日志放到远程文件系统。
- 避免使用检测工具,它们会影响基准测试结果。使用 INFO 来查看服务器状态没问题, 但是使用 MONITOR 将大大影响测试准确度;
111