Redis 性能問題的記錄


最近線上使用redis, 查詢的情況不甚理想, 這個查詢操作是個 lua 腳本, 包含如下操作

開發機 redis, 沒有其他干擾, 插入的 zset 有 5000 member 左右, 使用的 redis 客戶端是 spring-data, 底層 jedis 實現, 另外自己封裝了一層, 單線程單客戶端測試

1. zrange key 0 0 withscores

2. expire key

3. zadd key score member

A. 結果測試10w次發現平均每次拿到數據的時間需要 2800 us (2.8 ms). 也就是說 qps 只能達到 350 左右

B. 於是在本地在此進行測試, 結果是每次調用花費 300 us (0.3 ms), 差了 10 倍左右

而在本地和開發機上直接用 redis benchmark 測試 zadd, 使用單客戶端測試性能 , 測試命令如下

A. 本機測試

redis-benchmark -n 100000 -c 1 -r 100000 zadd testzset 10 __rand_int__
====== zadd testzset 10 __rand_int__ ======
  100000 requests completed in 3.37 seconds
  1 parallel clients
  3 bytes payload
  keep alive: 1

100.00% <= 0 milliseconds
29647.20 requests per second

 

約合 34 us / command

B. dev 機器測試

redis-benchmark -h l-remote1.com -p 6379 -n 10000 -c 1 -r 100000 zadd testzset 10 __rand_int__
====== zadd testzset 10 __rand_int__ ======
  10000 requests completed in 10.53 seconds
  1 parallel clients
  3 bytes payload
  keep alive: 1

47.43% <= 1 milliseconds
99.75% <= 2 milliseconds
99.90% <= 3 milliseconds
99.97% <= 4 milliseconds
99.99% <= 5 milliseconds
100.00% <= 10 milliseconds
949.58 requests per second

 

約合 1053 us / command

 

 下面是使用 java redis 客戶端詳細的測試數據

 

單位 us

Local Test 10W Zrange

No test on borrow
1. 
elapsed : 7296558 count : 99999 avg : 72
Mon elapsed : 7127632 count : 100000 avg : 71

2.
elapsed : 8026594 count : 99999 avg : 80
Mon elapsed : 7843030 count : 100000 avg : 78

3.
elapsed : 8149801 count : 99995 avg : 81
Mon elapsed : 8032342 count : 100000 avg : 80

4.
elapsed : 7961328 count : 99997 avg : 79
Mon elapsed : 7820042 count : 100000 avg : 78

Test on borrow
1.
elapsed : 10842955 count : 99999 avg : 108
Mon elapsed : 10710879 count : 100000 avg : 107

2.
elapsed : 11232565 count : 99998 avg : 112
Mon elapsed : 11130959 count : 100000 avg : 111

3.
elapsed : 11353824 count : 99998 avg : 113
Mon elapsed : 11224904 count : 100000 avg : 112

4.
elapsed : 11005635 count : 99999 avg : 110
Mon elapsed : 10868879 count : 100000 avg : 108 Local Test 10W Lua

No test

1.
elapsed : 25749403 count : 99998 avg : 257
Mon elapsed : 25630396 count : 100000 avg : 256

2.
elapsed : 25682824 count : 99997 avg : 256
Mon elapsed : 25592035 count : 100000 avg : 255

3.
elapsed : 26502975 count : 99997 avg : 265
Mon elapsed : 26373153 count : 100000 avg : 263

4.
elapsed : 50227904 count : 99997 avg : 251
Mon elapsed : 50019605 count : 100000 avg : 250

Test on borrow

1.
elapsed : 30026344 count : 99998 avg : 300
Mon elapsed : 29874080 count : 100000 avg : 298

2.
elapsed : 56238052 count : 99998 avg : 281
Mon elapsed : 56005620 count : 100000 avg : 280

3.
elapsed : 84591577 count : 99998 avg : 281
Mon elapsed : 84299240 count : 100000 avg : 280

4.
elapsed : 112992770 count : 99993 avg : 282
Mon elapsed : 112601651 count : 100000 avg : 281 Dev Redis 10W Zrange 
No borrow test

1.
elapsed : 118723620 count : 99993 avg : 1187
Mon elapsed : 118801299 count : 100000 avg : 1188

2.
elapsed : 248431698 count : 99993 avg : 1242
Mon elapsed : 248271355 count : 100000 avg : 1241

3.
elapsed : 360073711 count : 99993 avg : 1200
Mon elapsed : 359465633 count : 100000 avg : 1198

4.
elapsed : 116067058 count : 99996 avg : 1160
Mon elapsed : 115373200 count : 100000 avg : 1153

Test on borrow

1.
elapsed : 217290959 count : 94648 avg : 2295
Mon elapsed : 291451989 count : 100000 avg : 2914

2.
elapsed : 214828993 count : 99996 avg : 2148
Mon elapsed : 506368136 count : 200000 avg : 2531

3.
elapsed : 216495505 count : 100000 avg : 2164
Mon elapsed : 722433027 count : 300000 avg : 2408

4.
elapsed : 216426804 count : 99996 avg : 2164
Mon elapsed : 938483110 count : 400000 avg : 2346 Dev Redis 10W Lua

No borrow test

1.
elapsed : 139567804 count : 99928 avg : 1396
Mon elapsed : 140374850 count : 100000 avg : 1403

2.
elapsed : 137681314 count : 99996 avg : 1376
Mon elapsed : 278360257 count : 200000 avg : 1391

3.
elapsed : 138600259 count : 99995 avg : 1386
Mon elapsed : 416537097 count : 300000 avg : 1388

4.
elapsed : 152433076 count : 99997 avg : 1524
Mon elapsed : 568534621 count : 400000 avg : 1421

test on borrow

1.
elapsed : 275491060 count : 86077 avg : 3200
Mon elapsed : 458422068 count : 100000 avg : 4584

2.
elapsed : 245908497 count : 99989 avg : 2459
Mon elapsed : 704242016 count : 200000 avg : 3521

3.
elapsed : 253036141 count : 99161 avg : 2551
Mon elapsed : 967942699 count : 300000 avg : 3226

4.
elapsed : 251844305 count : 99965 avg : 2519
Mon elapsed : 1219753868 count : 400000 avg : 3049

 

可以發現實際上 java 客戶端的性能並沒有差多少, 使用 zrange 查詢遠端客戶端在沒有 test on borrow 的情況下也在 1 ms 左右, 加上 test on borrow 馬上翻倍, 這就是 RTT 的效果, 按照 netty 的工作線程數為 8 個, 這個線程數根本還無法將 RTT 的影響達到最低, 據我測試起碼需要大於 10 個並行客戶端的數量才可以消除

並發客戶端的數量對 benchmark 的測試的影響是非常大的, 由於 RTT (routnd trip time) 的存在, 本地網卡的網絡延時可能不明顯, 但是如果是非本地環境, RTT 就會顯得非常嚴重了, 例如只用單客戶端進行測試, 如下

本地測試單客戶端

edis-benchmark -n 100000 -c 1 zrange dp.1046 0 0
====== zrange dp.1046 0 0 ======
  100000 requests completed in 3.31 seconds
  1 parallel clients
  3 bytes payload
  keep alive: 1

100.00% <= 0 milliseconds
30229.75 requests per second

本地測試多客戶端

redis-benchmark -n 100000 -c 10 zrange dp.1046 0 0
====== zrange dp.1046 0 0 ======
  100000 requests completed in 1.38 seconds
  10 parallel clients
  3 bytes payload
  keep alive: 1

100.00% <= 0 milliseconds
72516.32 requests per second

遠程測試單客戶端, 發現連 1000 qps 都到不了

redis-benchmark -h l-remote1.com -p 6379 -n 10000 -c 1 zrange dp.1046 0 0
====== zrange dp.1046 0 0 ======
  10000 requests completed in 10.18 seconds
  1 parallel clients
  3 bytes payload
  keep alive: 1

73.23% <= 1 milliseconds
99.93% <= 2 milliseconds
99.99% <= 4 milliseconds
100.00% <= 5 milliseconds
982.80 requests per second

遠程 10 客戶端

redis-benchmark -h l-remote1.com -p 6379 -n 100000 -c 10 zrange dp.1046 0 0
====== zrange dp.1046 0 0 ======
  100000 requests completed in 10.56 seconds
  10 parallel clients
  3 bytes payload
  keep alive: 1

52.75% <= 1 milliseconds
99.81% <= 2 milliseconds
99.99% <= 3 milliseconds
100.00% <= 3 milliseconds
9468.80 requests per second

遠程 50 客戶端

redis-benchmark -h l-remote1.com -p 6379 -n 100000 -c 50 zrange dp.1046 0 0
====== zrange dp.1046 0 0 ======
  100000 requests completed in 4.86 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

1.19% <= 1 milliseconds
26.45% <= 2 milliseconds
98.55% <= 3 milliseconds
99.87% <= 4 milliseconds
99.94% <= 5 milliseconds
99.95% <= 360 milliseconds
99.96% <= 559 milliseconds
99.97% <= 560 milliseconds
99.99% <= 561 milliseconds
100.00% <= 561 milliseconds
20580.37 requests per second

可以發現多客戶端情況下 qps 不在一個級別

回到上面的測試

 我們單線程的 java 客戶端執行 zrange 也就 1000 qps 到不了, 算上現在 3 台機器 + 每台機器 8 個工作線程, 撐死達到 1000 * 3 * 8 = 24000 的 qps, 而且機器上還有很多別的任務, redis 操作也不止一個 zrange, 能到 10000 qps 已經很不錯了我相信. 所以最終還不能這么搞, 能解決問題辦法我初步考慮應該是

1. 異步 redis 客戶端, 別阻塞工作線程

2. 增加 redis 客戶端執行任務線程數 (目前這種同步情況下就是 netty 的工作線程)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM