1. 程式人生 > >Redis效能壓測工具 redis-benchmark

Redis效能壓測工具 redis-benchmark

Redis有多快?

Redis 自帶了一個叫 redis-benchmark 的工具來模擬 N 個客戶端同時發出 M 個請求。 (類似於 Apache ab 程式)。你可以使用 redis-benchmark -h 來檢視基準引數。

以下引數被支援:

Usage: redis-benchmark [-h <host>] [-p <port>] [-c <clients>] [-n <requests]> [-k <boolean>]

 -h <hostname>      Server hostname (default 127.0.0.1)
 -p <port>          Server port (default 6379)
 -s <socket>        Server socket (overrides host and port)
 -a <password>      Password for Redis Auth
 -c <clients>       Number of parallel connections (default 50)
 -n <requests>      Total number of requests (default 100000)
 -d <size>          Data size of SET/GET value in bytes (default 2)
 -dbnum <db>        SELECT the specified db number (default 0)
 -k <boolean>       1=keep alive 0=reconnect (default 1)
 -r <keyspacelen>   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 <numreq>        Pipeline <numreq> requests. Default 1 (no pipeline).
 -q                 Quiet. Just show query/sec values
 --csv              Output in CSV format
 -l                 Loop. Run the tests forever
 -t <tests>         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

這個工具使用起來非常方便,同時你可以使用自己的基準測試工具, 不過開始基準測試時候,我們需要注意一些細節。

只執行一些測試用例的子集

你不必每次都執行 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

選擇測試鍵的範圍大小

預設情況下面,基準測試使用單一的 key。在一個基於記憶體的資料庫裡, 單一 key 測試和真實情況下面不會有巨大變化。當然,使用一個大的 key 範圍空間, 可以模擬現實情況下面的快取不命中情況。

這時候我們可以使用 -r 命令。比如,假設我們想設定 10 萬隨機 key 連續 SET 100 萬次,我們可以使用下列的命令:

$ 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

使用 pipelining

預設情況下,每個客戶端都是在一個請求完成之後才傳送下一個請求 (benchmark 會模擬 50 個客戶端除非使用 -c 指定特別的數量), 這意味著伺服器幾乎是按順序讀取每個客戶端的命令。Also RTT is payed as well.

真實世界會更復雜,Redis 支援 /topics/pipelining,使得可以一次性執行多條命令成為可能。 Redis pipelining 可以提高伺服器的 TPS。 下面這個案例是在 Macbook air 11” 上使用 pipelining 組織 16 條命令的測試範例:

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

記得在多條命令需要處理時候使用 pipelining。

陷阱和錯誤的認識

第一點是顯而易見的:基準測試的黃金準則是使用相同的標準。 用相同的任務量測試不同版本的 Redis,或者用相同的引數測試測試不同版本 Redis。 如果把 Redis 和其他工具測試,那就需要小心功能細節差異。

  • 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-benchmark 特意讓基準測試看起來更好, 所表現出來的資料像是人造的,而不是真實產品下面的。

Redis-benchmark 程式可以簡單快捷的對給定硬體條件下面的機器計算出效能引數。 但是,通常情況下面這並不是 Redis 伺服器可以達到的最大吞吐量。 事實上,使用 pipelining 和更快的客戶端(hiredis)可以達到更大的吞吐量。 redis-benchmark 預設情況下面僅僅使用併發來提高吞吐量(建立多條連線)。 它並沒有使用 pipelining 或者其他並行技術(僅僅多條連線,而不是多執行緒)。

如果想使用 pipelining 模式來進行基準測試(了達到更高吞吐量),可以使用 -P 引數。這種方案的確可以提高效能,有很多使用 Redis 的應用在生產環境中這樣做。

最後,基準測試需要使用相同的操作和資料來對比,如果這些不一樣, 那麼基準測試是無意義的。

比如,Redis 和 memcached 可以在單執行緒模式下面對比 GET/SET 操作。 兩者都是記憶體資料庫,協議也基本相同,甚至把多個請求合併為一條請求的方式也類似 (pipelining)。在使用相同數量的連線後,這個對比是很有意義的。

下面這個很不錯例子是在 Redis(antirez)和 memcached(dormando)測試的。

你可以發現相同條件下面最終結果是兩者差別不大。請注意最終測試時候, 兩者都經過了充分優化。

最後,當特別高效能的伺服器在基準測試時候(比如 Redis、memcached 這類), 很難讓伺服器效能充分發揮,通常情況下,客戶端回事瓶頸限制而不是伺服器端。 在這種情況下面,客戶端(比如 benchmark 程式自身)需要優化,或者使用多例項, 從而能達到最大的吞吐量。

影響 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 的請求時候,吞吐量是差不多的,詳細可以見下圖。

Data size impact

  • 在多核 CPU 伺服器上面,Redis 的效能還依賴 NUMA 配置和 處理器繫結位置。 最明顯的影響是 redis-benchmark 會隨機使用 CPU 核心。為了獲得精準的結果, 需要使用固定處理器工具(在 Linux 上可以使用 taskset 或 numactl)。 最有效的辦法是將客戶端和服務端分離到兩個不同的 CPU 來高校使用三級快取。 這裡有一些使用 4 KB 資料 SET 的基準測試,針對三種 CPU(AMD Istanbul, Intel Nehalem EX, 和 Intel Westmere)使用不同的配置。請注意, 這不是針對 CPU 的測試。

NUMA chart

  • 在高配置下面,客戶端的連線數也是一個重要的因素。得益於 epoll/kqueue, Redis 的事件迴圈具有相當可擴充套件性。Redis 已經在超過 60000 連線下面基準測試過, 仍然可以維持 50000 q/s。一條經驗法則是,30000 的連線數只有 100 連線的一半吞吐量。 下面有一個關於連線數和吞吐量的測試。

connections chart

  • 在高配置下面,可以通過調優 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 將大大影響測試準確度。

不同雲主機和物理機器上的基準測試結果

  • 這些測試模擬了 50 客戶端和 200w 請求。
  • 使用了 Redis 2.6.14。
  • 使用了 loopback 網絡卡。
  • key 的範圍是 100 w。
  • 同時測試了 有 pipelining 和沒有的情況(16 條命令使用 pipelining)。

Intel(R) Xeon(R) CPU E5520 @ 2.27GHz (with pipelining)

$ ./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

Intel(R) Xeon(R) CPU E5520 @ 2.27GHz (without pipelining)

$ ./redis-benchmark -r 1000000 -n 2000000 -t get,set,lpush,lpop -q
SET: 122556.53 requests per second
GET: 123601.76 requests per second
LPUSH: 136752.14 requests per second
LPOP: 132424.03 requests per second

Linode 2048 instance (with pipelining)

$ ./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 (without pipelining)

$ ./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

更多使用 pipeline 的測試

$ 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 bytes 不會改變結果的量級 (但是到 1024 bytes 後,GETs 操作會變慢)。同樣的,50 到 256 客戶端的測試結果相同。 10 個客戶端時候,吞吐量會變小(譯者按:總量到不了最大吞吐量)。

不同機器可以獲的不一樣的結果,下面是 Intel T5500 1.66 GHz 在 Linux 2.6 下面的結果:

$ ./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

高效能硬體下面的基準測試

  • Redis 2.4.2
  • 預設連線數,資料包大小 256 bytes。
  • Linux 是 SLES10 SP3 2.6.16.60-0.54.5-smp,CPU 是 Intel X5670 @ 2.93 GHz.
  • 固定 CPU,但是使用不同 CPU 核心。

使用 unix domain socket:

$ 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
源自:http://www.redis.cn/topics/benchmarks.html