Redis【有与无】【Admin-13】Redis基准测试

Linode 2048 instance (with pipelining)本文基于Redis 6.0.9版本,前提至少 Redis 3.0或更高版本。

目录

1.Redis基准测试

1.1.仅运行部分测试

1.2.选择键空间的大小

1.3.使用流水线(pipelining)

1.4.陷阱和误解(Pitfalls and misconceptions)

1.5.影响Redis性能的因素

1.6.其他要考虑的事情

2.在不同的虚拟化服务器和裸机服务器上获得基准测试结果

2.1.没有流水线的更详细的测试

3.其他Redis基准测试工具

4.优化高端服务器硬件的Redis基准测试结果示例


1.Redis基准测试

查看Redis在不同平台上的运行速度。

Redis包含redis-benchmark实用程序,该实用程序模拟N个客户端同时发送M个总计查询的正在运行的命令(类似于Apache的ab 实用程序)。 在下面,你将找到针对Linux系统执行的基准测试的完整输出。

支持以下选项:

Usage: redis-benchmark [-h ] [-p ] [-c ] [-n  [-k ]

 -h       Server hostname (default 127.0.0.1)
 -p           Server port (default 6379)
 -s         Server socket (overrides host and port)
 -a       Password for Redis Auth
 -c        Number of parallel connections (default 50)
 -n       Total number of requests (default 100000)
 -d           Data size of SET/GET value in bytes (default 2)
 --dbnum        SELECT the specified db number (default 0)
 -k        1=keep alive 0=reconnect (default 1)
 -r    Use random keys for SET/GET/INCR, random values for SADD
  Using this option the benchmark will expand the string __rand_int__
  inside an argument with a 12 digits number in the specified range
  from 0 to keyspacelen-1. The substitution changes every time a command
  is executed. Default tests use this to hit random keys in the
  specified range.
 -P         Pipeline  requests. Default 1 (no pipeline).
 -q                 Quiet. Just show query/sec values
 --csv              Output in CSV format
 -l                 Loop. Run the tests forever
 -t          Only run the comma separated list of tests. The test
                    names are the same as the ones produced as output.
 -I                 Idle mode. Just open N idle connections and wait.

启动基准之前,你需要具有运行中的Redis实例。 一个典型的例子是:

redis-benchmark -q -n 100000

使用此工具非常容易,你也可以编写自己的基准测试,但与任何基准测试活动一样,有一些陷阱要避免。

1.1.仅运行部分测试

你无需在每次执行redis-benchmark时都运行所有默认测试。 仅选择测试子集的最简单方法是使用 -t 选项,如以下示例所示:

$ redis-benchmark -t set,lpush -n 100000 -q
SET: 74239.05 requests per second
LPUSH: 79239.30 requests per second

在上面的示例中,我们要求以安静模式运行测试SET和LPUSH命令(请参见 -q 开关)。

也可以像下面的示例一样直接指定要进行基准测试的命令:

$ redis-benchmark -n 100000 -q script load "redis.call('set','foo','bar')"
script load redis.call('set','foo','bar'): 69881.20 requests per second

1.2.选择键空间的大小

默认情况下,基准测试针对单个键运行。 在Redis中,这样的综合基准与实际基准之间的差异并不大,因为它是内存系统,但是可以强调缓存未命中,并且通常可以使用大键来模拟更实际的工作负载空间。

这是通过使用 -r 开关获得的。 例如,如果我要运行一百万个SET操作,并对100k个可能的键中的每个操作使用一个随机键,我将使用以下命令行:

$ redis-cli flushall
OK

$ redis-benchmark -t set -r 100000 -n 1000000
====== SET ======
  1000000 requests completed in 13.86 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

99.76% `<=` 1 milliseconds
99.98% `<=` 2 milliseconds
100.00% `<=` 3 milliseconds
100.00% `<=` 3 milliseconds
72144.87 requests per second

$ redis-cli dbsize
(integer) 99993

1.3.使用流水线(pipelining)

默认情况下,每个客户端(基准测试模拟50个客户端,如果未使用 -c 另行指定)仅在收到前一个命令的回复时才发送下一个命令,这意味着服务器可能需要read调用才能读取每个命令来自每个客户。 另外,RTT也要付费。

Redis支持流水线(pipelining),因此可以一次发送多个命令,这是现实世界应用程序经常利用的功能。 Redis流水线能够极大地提高服务器每秒能够执行的操作数量。

这是使用16条命令的流水线,在MacBook Air 11中,运行基准测试的示例:

$ redis-benchmark -n 1000000 -t set,get -P 16 -q
SET: 403063.28 requests per second
GET: 508388.41 requests per second

使用流水线可显着提高性能。

1.4.陷阱和误解(Pitfalls and misconceptions)

第一点很明显:有用的基准测试的黄金法则是只比较apples 和apples 。 例如,可以在相同的工作负载上比较不同版本的Redis。 或相同版本的Redis,但具有不同的选项。 如果你打算将Redis与其他东西进行比较,那么评估功能和技术差异并加以考虑就很重要。

  • Redis是一台服务器:所有命令都涉及网络或IPC往返。 将其与嵌入式数据存储(例如SQLite,Berkeley DB,Tokyo / Kyoto Cabinet等)进行比较是没有意义的,因为大多数操作的成本主要在网络/协议管理中。
  • Redis命令返回所有常用命令的确认。 其他一些数据存储则没有。 将Redis与涉及单向查询的商店进行比较仅会适度有用。
  • 天真地迭代同步Redis命令不会对Redis本身进行基准测试,而是可以衡量你的网络(或IPC)延迟和客户端库固有延迟。 要真正测试Redis,你需要多个连接(例如redis-benchmark)and/or使用流水线来聚合多个命令and/or多个线程或进程。
  • Redis是一个内存数据存储,具有一些可选的持久性选项。 如果打算将其与事务服务器(MySQL,PostgreSQL等)进行比较,则应考虑激活AOF并决定合适的fsync策略。
  • Redis在大多数情况下是命令执行POV中的单线程服务器(实际上,Redis的现代版本将线程用于不同的事物)。 它并非旨在受益于多个CPU内核。 人们应该启动多个Redis实例,以在需要时扩展到多个核心。 将一个Redis实例与一个多线程数据存储区进行比较并不公平。

一个常见的误解是redis-benchmark旨在使Redis的性能看起来很出色,redis-benchmark所实现的吞吐量有些人为,而实际应用无法实现。 这实际上是不正确的。

redis-benchmark程序是获取一些数字并评估给定硬件上Redis实例性能的一种快速而有用的方法。 但是,默认情况下,它不代表Redis实例可以维持的最大吞吐量。 实际上,通过使用流水线和快速客户端(hiredis),编写一个比redis-benchmark产生更多吞吐量的程序相当容易。 redis-benchmark的默认行为是仅通过利用并发来实现吞吐量(即,它创建到服务器的多个连接)。 如果未通过 -P 参数明确启用,则它根本不使用流水线或任何并行性(每个连接最多一个未决查询,并且没有多线程)。 因此,通过某种方式使用redis-benchmark并在后台同时触发例如BGSAVE 操作,将为用户提供比最坏情况更接近最佳情况的数字。

要使用流水线模式运行基准测试(并实现更高的吞吐量),你需要显式使用-P选项。 请注意,由于许多基于Redis的应用程序都在积极使用流水线来提高性能,因此这仍然是现实的行为。 但是,你应该使用的流水线大小应大于或小于你可以在应用程序中使用的平均流水线长度,以便获得实际数字。

最后,基准测试应应用相同的操作,并以相同的方式处理要比较的多个数据存储。 将redis-benchmark的结果与另一个基准程序的结果进行比较并推断是绝对没有意义的。

例如,可以在GET/SET操作上比较单线程模式下的Redis和memcached。 两者都是内存中的数据存储,在协议级别上大多数都以相同的方式工作。 如果它们各自的基准应用程序以相同的方式(流水线)聚合查询并使用相似数量的连接,则该比较实际上是有意义的。

Redis(antirez)和memcached(dormando)开发人员之间的对话框说明了这个完美的示例。

  • antirez 1-关于Redis,Memcached,速度,基准和更衣室
  • dormando-Redis VS Memcached(更好的替补席)
  • antirez 2-Memcached / Redis基准测试的更新

你可以看到,一旦考虑了所有技术方面,两种解决方案之间的差异就不会那么惊人。 请注意,在这些基准测试之后,Redis和memcached均已进行了进一步优化。

最后,当对非常高效的服务器进行基准测试(并且Redis或memcached之类的存储肯定属于此类)时,可能很难使服务器饱和。 有时,性能瓶颈在客户端而不是服务器端。 在那种情况下,客户端(即基准程序本身)必须是固定的,或者可能是横向扩展的,以便达到最大吞吐量。

1.5.影响Redis性能的因素

有多种因素直接影响Redis的性能。 我们在这里提到它们,因为它们可以改变任何基准测试的结果。 但是请注意,在低端,未调整的盒子上运行的典型Redis实例通常为大多数应用程序提供足够好的性能。

  • 网络带宽和延迟通常会直接影响性能。 在启动基准测试之前,最好使用ping程序快速检查客户端和服务器主机之间的延迟是否正常。 关于带宽,通常以Gbit/s为单位估算吞吐量并将其与网络的理论带宽进行比较通常很有用。 例如,在Redis中以100000 q/s的速度设置4 KB字符串的基准测试实际上会消耗3.2 Gbit/s的带宽,并且可能适合10Gbit/s的链路,而不是1 Gbit/s的链路。 在许多实际情况下,Redis吞吐量在很大程度上受到网络的限制,然后才受到CPU的限制。 要在单个服务器上整合多个高吞吐量Redis实例,值得考虑放置一个10 Gbit / s NIC或多个具有TCP/IP绑定的1 Gbit/s NIC。
  • CPU是另一个非常重要的因素。 由于是单线程的,Redis更喜欢具有大缓存且内核不多的快速CPU。 在这场比赛中,英特尔CPU当前是赢家。 与具有Redis的类似Nehalem EP / Westmere EP / Sandy Bridge Intel CPU相比,在AMD Opteron CPU上仅获得一半的性能并不少见。 当客户端和服务器在同一盒上运行时,CPU是redis-benchmark的限制因素。
  • RAM的速度和内存带宽对于全局性能似乎不太重要,特别是对于小型对象。 对于大对象(> 10 KB),它可能会变得很明显。 通常,购买昂贵的快速内存模块来优化Redis并不真正具有成本效益。
  • 与没有使用相同硬件进行虚拟化的情况相比,Redis在VM上的运行速度较慢。 如果你有机会在物理机上运行Redis,则首选此方法。 但是,这并不意味着Redis在虚拟环境中运行缓慢,交付的性能仍然非常好,并且在虚拟环境中可能引起的大多数严重性能问题是由于配置过多,延迟高的非本地磁盘或过旧 具有慢速分叉syscall实现的管理程序软件。
  • 当服务器和客户端基准测试程序在同一盒上运行时,可以使用TCP/IP回送和Unix域套接字。 根据平台的不同,Unix域套接字可以实现比TCP/IP回送(loopback)(例如,在Linux上)多50%的吞吐量。 redis-benchmark的默认行为是使用TCP/IP回送(loopback)。
  • 当大量使用流水线(即长流水线)时,与TCP/IP回送(loopback)相比,Unix域套接字的性能优势趋于降低。
  • 当使用以太网网络访问Redis时,当数据大小保持在以太网数据包大小(约1500字节)以下时,使用流水线聚合命令特别有效。 实际上,处理10个字节,100个字节或1000个字节的查询几乎会导致相同的吞吐量。 
  • 在多CPU套接字服务器上,Redis的性能取决于NUMA配置和进程位置。 最明显的效果是,redis-benchmark结果似乎不确定,因为客户端和服务器进程随机分布在核心上。 为了获得确定的结果,需要使用流程放置工具(在Linux上:taskset或numactl)。 最有效的组合始终是将客户端和服务器放在同一CPU的两个不同内核上,以从L3缓存中受益。 以下是针对具有不同相对位置的3个服务器CPU(AMD Istanbul, Intel Nehalem EX, Intel Westmere)的4 KB SET基准测试的一些结果。 请注意,该基准测试无意于比较它们之间的CPU型号(因此,不披露CPU的确切型号和频率)。
  • 对于高端配置,客户端连接数也是一个重要因素。 基于epoll/kqueue,Redis事件循环具有很好的可扩展性。 Redis已经以超过60000个连接为基准,并且在这些条件下仍能够维持50000 q/s。 根据经验,具有30000个连接的实例只能处理100个连接可达到的吞吐量的一半。
  • 使用高端配置,可以通过调整NIC配置和相关的中断来实现更高的吞吐量。 通过在Rx/Tx NIC队列和CPU内核之间设置亲缘关系并激活RPS(接收数据包导向)支持,可以实现最佳吞吐量。 此线程中的更多信息。 使用大型物体时,巨型帧还可以提高性能。
  • 取决于平台,Redis可以针对不同的内存分配器(libc malloc,jemalloc,tcmalloc)进行编译,这些分配器在原始速度,内部和外部碎片方面可能具有不同的行为。 如果你自己没有编译Redis,则可以使用INFO命令来检查mem_allocator字段。 请注意,大多数基准测试的运行时间不足以产生明显的外部碎片(与生产Redis实例相反)。

1.6.其他要考虑的事情

任何基准测试的一个重要目标是获得可重复的结果,因此可以将它们与其他测试的结果进行比较。

  • 一个好的做法是尝试尽可能在隔离的硬件上运行测试。 如果不可能,那么必须对系统进行监视,以检查基准是否受到某些外部活动的影响。
  • 某些配置(当然是台式机和笔记本电脑,还有一些服务器)具有可变的CPU核心频率机制。 可以在OS级别上设置控制此机制的策略。 在调整CPU核心频率以适应工作负载方面,某些CPU模型比其他模型更具攻击性。 为了获得可重现的结果,最好为基准测试中涉及的所有CPU内核设置尽可能高的固定频率。
  • 重要的一点是根据基准确定系统的大小。 系统必须具有足够的RAM,并且不能交换。 在Linux上,不要忘记正确设置overcommit_memory参数。 请注意,32位和64位Redis实例的内存占用不同。
  • 如果计划将RDB或AOF用作基准,请检查系统中是否没有其他I/O活动。 避免将RDB或AOF文件放在NAS或NFS共享上,或影响网络带宽和/或延迟的任何其他设备上(例如,Amazon EC2上的EBS)。
  • 将Redis日志记录级别(loglevel参数)设置为警告或注意。 避免将生成的日志文件放在远程文件系统上。
  • 避免使用会改变基准测试结果的监视工具。 例如,定期使用INFO收集统计信息可能很好,但是MONITOR将对测量的性能产生重大影响。

2.在不同的虚拟化服务器和裸机服务器上获得基准测试结果

警告:请注意,以下大多数基准测试已有几年历史,并且是通过旧硬件与今天的标准进行比较获得的。 该页面应该进行更新,但是在许多情况下,使用硬硬件状态,你可以期望看到的数字是此处看到的数字的两倍。 而且,Redis 4.0在许多工作负载中都比2.6快。

  • 测试是由50个同时执行200万个请求的客户端完成的。
  • Redis 2.6.14用于所有测试。
  • 使用回送接口执行了测试。
  • 使用一百万个键的键空间执行测试。
  • 使用和不使用流水线(16条命令流水线)执行测试。

Intel(R) Xeon(R) CPU E5520 @ 2.27GHz (有流水线)

$ ./redis-benchmark -r 1000000 -n 2000000 -t get,set,lpush,lpop -P 16 -q
SET: 552028.75 requests per second
GET: 707463.75 requests per second
LPUSH: 767459.75 requests per second
LPOP: 770119.38 requests per second

Linode 2048 instance (有流水线)

$ ./redis-benchmark -r 1000000 -n 2000000 -t get,set,lpush,lpop -q -P 16
SET: 195503.42 requests per second
GET: 250187.64 requests per second
LPUSH: 230547.55 requests per second
LPOP: 250815.16 requests per second

Linode 2048 instance (无流水线)

$ ./redis-benchmark -r 1000000 -n 2000000 -t get,set,lpush,lpop -q
SET: 35001.75 requests per second
GET: 37481.26 requests per second
LPUSH: 36968.58 requests per second
LPOP: 35186.49 requests per second

2.1.没有流水线的更详细的测试

$ redis-benchmark -n 100000

====== SET ======
  100007 requests completed in 0.88 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

58.50% <= 0 milliseconds
99.17% <= 1 milliseconds
99.58% <= 2 milliseconds
99.85% <= 3 milliseconds
99.90% <= 6 milliseconds
100.00% <= 9 milliseconds
114293.71 requests per second

====== GET ======
  100000 requests completed in 1.23 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

43.12% <= 0 milliseconds
96.82% <= 1 milliseconds
98.62% <= 2 milliseconds
100.00% <= 3 milliseconds
81234.77 requests per second

====== INCR ======
  100018 requests completed in 1.46 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

32.32% <= 0 milliseconds
96.67% <= 1 milliseconds
99.14% <= 2 milliseconds
99.83% <= 3 milliseconds
99.88% <= 4 milliseconds
99.89% <= 5 milliseconds
99.96% <= 9 milliseconds
100.00% <= 18 milliseconds
68458.59 requests per second

====== LPUSH ======
  100004 requests completed in 1.14 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

62.27% <= 0 milliseconds
99.74% <= 1 milliseconds
99.85% <= 2 milliseconds
99.86% <= 3 milliseconds
99.89% <= 5 milliseconds
99.93% <= 7 milliseconds
99.96% <= 9 milliseconds
100.00% <= 22 milliseconds
100.00% <= 208 milliseconds
88109.25 requests per second

====== LPOP ======
  100001 requests completed in 1.39 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

54.83% <= 0 milliseconds
97.34% <= 1 milliseconds
99.95% <= 2 milliseconds
99.96% <= 3 milliseconds
99.96% <= 4 milliseconds
100.00% <= 9 milliseconds
100.00% <= 208 milliseconds
71994.96 requests per second

注意:将有效负载从256更改为1024或4096字节不会显着改变数字(但是,答复数据包最多粘合到1024字节,因此对于较大的有效负载,GET可能会变慢)。 客户端数量相同,从50到256个客户端,我得到的数量相同。 只有10个客户端,它开始变得有点慢。

你可以从不同的盒子获得不同的结果。 例如,一个运行在Linux 2.6上,频率为1.66 GHz的Intel Core du T5500等低调机箱将输出以下内容:

$ ./redis-benchmark -q -n 100000
SET: 53684.38 requests per second
GET: 45497.73 requests per second
INCR: 39370.47 requests per second
LPUSH: 34803.41 requests per second
LPOP: 37367.20 requests per second

另一个使用64位盒的Xeon L5420时钟频率为2.5 GHz:

$ ./redis-benchmark -q -n 100000
PING: 111731.84 requests per second
SET: 108114.59 requests per second
GET: 98717.67 requests per second
INCR: 95241.91 requests per second
LPUSH: 104712.05 requests per second
LPOP: 93722.59 requests per second

3.其他Redis基准测试工具

有几种第三方工具可用于对Redis进行基准测试。 有关每个工具的目标和功能的更多信息,请参阅每个工具的文档。

  • Redis Labs的memtier_benchmark 是NoSQL Redis和Memcache流量生成和基准测试工具。
  • Twitter 的rpc-perf是用于对支持Redis和Memcache的RPC服务进行基准测试的工具。
  • Yahoo @Yahoo的YCSB是一个基准测试框架,具有许多数据库(包括Redis)的客户端。

4.优化高端服务器硬件的Redis基准测试结果示例

  • Redis版本2.4.2
  • 默认连接数,有效负载大小= 256
  • Linux机器正在运行SLES10 SP3 2.6.16.60-0.54.5-smp,CPU是2.x Intel X5670 @ 2.93 GHz。
  • 在同一CPU上运行Redis服务器和基准客户端但内核不同时执行的测试。

使用Unix域套接字:

$ numactl -C 6 ./redis-benchmark -q -n 100000 -s /tmp/redis.sock -d 256
PING (inline): 200803.22 requests per second
PING: 200803.22 requests per second
MSET (10 keys): 78064.01 requests per second
SET: 198412.69 requests per second
GET: 198019.80 requests per second
INCR: 200400.80 requests per second
LPUSH: 200000.00 requests per second
LPOP: 198019.80 requests per second
SADD: 203665.98 requests per second
SPOP: 200803.22 requests per second
LPUSH (again, in order to bench LRANGE): 200000.00 requests per second
LRANGE (first 100 elements): 42123.00 requests per second
LRANGE (first 300 elements): 15015.02 requests per second
LRANGE (first 450 elements): 10159.50 requests per second
LRANGE (first 600 elements): 7548.31 requests per second

使用TCP回送(loopback):

$ numactl -C 6 ./redis-benchmark -q -n 100000 -d 256
PING (inline): 145137.88 requests per second
PING: 144717.80 requests per second
MSET (10 keys): 65487.89 requests per second
SET: 142653.36 requests per second
GET: 142450.14 requests per second
INCR: 143061.52 requests per second
LPUSH: 144092.22 requests per second
LPOP: 142247.52 requests per second
SADD: 144717.80 requests per second
SPOP: 143678.17 requests per second
LPUSH (again, in order to bench LRANGE): 143061.52 requests per second
LRANGE (first 100 elements): 29577.05 requests per second
LRANGE (first 300 elements): 10431.88 requests per second
LRANGE (first 450 elements): 7010.66 requests per second
LRANGE (first 600 elements): 5296.61 requests per second

 

你可能感兴趣的:(Redis,redis)