通常我們用redis做接口緩存后棍辕,查詢接口的性能就能提升到ms級(jí)別余佛;
但是redis是純內(nèi)存操作啊罩抗,總不至于要到ms吧,根據(jù)官方的 benchmark 單實(shí)例也是能抗 7w+ qps 也就是說單個(gè)redis 操作在redis-server上耗時(shí)大概是 0.014ms峰鄙,那時(shí)間是消耗到哪里去了浸间?
redis是 client-server 模型,client客戶端將 command 通過tcp網(wǎng)絡(luò)連接發(fā)送到 server服務(wù)端先馆,服務(wù)端執(zhí)行完 command 后將響應(yīng)再通過 tcp 連接發(fā)送給client发框;
對(duì)于應(yīng)用服務(wù)來說,我們所關(guān)注的性能其實(shí)是客戶端時(shí)間煤墙,即前面的整個(gè)執(zhí)行過程梅惯,雖然 redis-server 命令執(zhí)行的非常快仿野,但每次命令執(zhí)行都需要在網(wǎng)絡(luò)上走一遭铣减,按照我們公司redis客戶端中間件統(tǒng)計(jì)的rt,一次命令的執(zhí)行平均是1ms 左右脚作,那么網(wǎng)絡(luò)耗時(shí)占比: 1-0.014 / 1 = 0.98(98%!!! ) 可見葫哗,大部分時(shí)間都耗在網(wǎng)絡(luò)io上
所以,減少網(wǎng)絡(luò)io次數(shù)就能大大提供 redis-client 感知的耗時(shí)球涛,redis提供的 pipeline 功能劣针,讓我們可以提交一個(gè)命令后,不用等這個(gè)返回結(jié)果就可以繼續(xù)執(zhí)行下一個(gè)命令亿扁,也就是說捺典,可以執(zhí)行多個(gè)命令后,一次性獲取所有結(jié)果从祝; 這樣就大大減少了在網(wǎng)絡(luò)上的消耗
比如
Client: INCR X
Client: INCR X
Client: INCR X
Client: INCR X
Server: 1
Server: 2
Server: 3
Server: 4
除此之外襟己,減少了網(wǎng)絡(luò)讀寫次數(shù)的同時(shí)引谜,也減少了 redis-server 內(nèi)核態(tài)和用戶態(tài)的上下文切換,進(jìn)一步提高了性能
性能提升了多少擎浴?
redis官方聲稱pipeline可帶來10倍的性能提升測(cè)試機(jī)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的時(shí)候贮预,多個(gè)命令的響應(yīng)是緩存在server端的贝室,所以在 pipeline 里一批命令的數(shù)量不要過多,以免服務(wù)端內(nèi)存壓力過大
類似的技術(shù)還有
- CSS Sprites萌狂,將很多小圖標(biāo)合并成一張圖片
- jdbc batch api批量提交sql
參考: