通常我們用redis做介面快取後,查詢介面的效能就能提升到ms級別;
但是redis是純記憶體操作啊,總不至於要到ms吧,根據官方的 benchmark 單例項也是能抗 7w+ qps 也就是說單個redis 操作在redis-server上耗時大概是 0.014ms,那時間是消耗到哪裡去了?
redis是 client-server 模型,client客戶端將 command 通過tcp網路連線傳送到 server服務端,服務端執行完 command 後將響應再通過 tcp 連線傳送給client;
對於應用服務來說,我們所關注的效能其實是客戶端時間,即前面的整個執行過程,雖然 redis-server 命令執行的非常快,但每次命令執行都需要在網路上走一遭,按照我們公司redis客戶端中介軟體統計的rt,一次命令的執行平均是1ms 左右,那麼網路耗時佔比: 1-0.014 / 1 = 0.98(98%!!! ) 可見,大部分時間都耗在網路io上
所以,減少網路io次數就能大大提供 redis-client 所感知的耗時,提升應用服務效能,redis提供的 pipeline 功能,讓我們可以提交一個命令後,不用等這個返回結果就可以繼續執行下一個命令,也就是說,可以執行多個命令後,一次性獲取所有結果; 這樣就大大減少了在網路上的消耗
比如
Client: INCR X
Client: INCR X
Client: INCR X
Client: INCR X
Server: 1
Server: 2
Server: 3
Server: 4
除此之外,減少了網路讀寫次數的同時,也減少了 redis-server 核心態和使用者態的上下文切換,進一步提高了效能
效能提升了多少?
redis官方聲稱pipeline可帶來10倍的效能提升
測試機Intel(R) Xeon(R) CPU E5520 @ 2.27GHz, 用pipeline比沒用pipeline效能提升了將近7倍
// 用pipeline
$ ./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
// 沒用pipeline
SET: 122556.53 requests per second
GET: 123601.76 requests per second
LPUSH: 136752.14 requests per second
LPOP: 132424.03 requests per second
注意,使用pipeline的時候,多個命令的響應是快取在server端的,所以在 pipeline 裡一批命令的數量不要過多,以免服務端記憶體壓力過大
其實,減少網路io次數的處理技巧還是比較常見的,如
- CSS Sprites,將很多小圖示合併成一張圖片
- jdbc batch api批量提交sql
參考: