通常我們用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 里一批命令的數量不要過多,以免服務端內存壓力過大
類似的技術還有
- CSS Sprites,將很多小圖標合并成一張圖片
- jdbc batch api批量提交sql
參考: