6 predixy 批量set測試
7 redis 批量get測試
8 predixy 批量get測試
圖片還是不方便看,我們總結(jié)為表格:
測試指標 redis used redis user redis sys predixy used predixy user predixy sys redis qps predixy qps
redis set?0.990?0.247?0.744?0?0?0?167000?3?
predixy set?0.475?0.313?0.162?0.986?0.252?0.734?174000?174000?
redis get?0.922?0.180?0.742?0?0?0?163000?3?
predixy get?0.298?0.195?0.104?0.988?0.247?0.741?172000?172000?
redis批量set?1.006?0.796?0.21?0?0?0?782000?3?
predixy批量set?0.998?0.940?0.058?0.796?0.539?0.256?724000?724000?
redis批量get?1?0.688?0.312?0?0?0?1708000?3?
predixy批量get?0.596?0.582?0.014?0.999?0.637?0.362?935000?935000?
看到前四個的結(jié)果如果感到驚訝不用懷疑是自己看錯了或者是測試結(jié)果有問題,這個結(jié)果是無誤的。根據(jù)這個結(jié)果,那么可以回答我們最初提出的疑問,增加了代理之后并不一定會降低服務(wù)整體的吞吐!雖然benchmark并不是我們的實際應(yīng)用,但是redis的大部分應(yīng)用場景都是這樣的,并發(fā)的接受眾多客戶端的請求,處理然后返回。
為什么會是這樣的結(jié)果,看到這個結(jié)果后我們肯定想知道原因,這好像跟我們的想象不太一樣。要分析這個問題,我們還是從測試的數(shù)據(jù)來入手,首先看測試1的數(shù)據(jù),redis的CPU使用率幾乎已經(jīng)達到了1,對于單線程程序來說,這意味著CPU已經(jīng)跑滿了,性能已經(jīng)達到了極限,不可能再提高了,然而這時redis的吞吐卻只有167000。測試2的redis吞吐都比它高,并且我們明顯能看出測試2里redis的CPU使用率還不如測試1的高,測試2里redis CPU使用率只有0.475。為什么CPU使用率降低了吞吐反而卻還高了呢?仔細對比一下兩個測試的數(shù)據(jù),可以發(fā)現(xiàn)在測試1里,redis的CPU大部分都花在了內(nèi)核態(tài),高達0.744,而用戶態(tài)只有0.247,CPU運行在內(nèi)核態(tài)時雖然我們不能稱之為瞎忙活,但是卻無助于提升程序的性能,只有CPU運行在用戶態(tài)才可能提升我們的程序性能,相比測試1,測試2的redis用戶態(tài)CPU使用率提高到了0.313,而內(nèi)核態(tài)CPU則大幅下降至0.162。這也就解釋了為什么測試2的吞吐比測試1還要高。當然了,我們還是要繼續(xù)刨根問底,為什么測試2里經(jīng)過一層代理predixy后,redis的CPU使用情況發(fā)生變化了呢?這是因為redis接受一個連接批量的發(fā)送命令過來處理,也就是redis里所謂的pipeline。而predixy正是利用這一特性,predixy與redis之間只有一個連接(大多數(shù)情況下),predixy在收到客戶端的請求后,會將它們批量的通過這個連接發(fā)送給redis處理,這樣一來就大大降低了redis用于網(wǎng)絡(luò)IO操作的開銷,而這一部分開銷基本都是花費在內(nèi)核態(tài)。
對比測試1和測試2,引入predixy不僅直接提高了吞吐,還帶來一個好處,就是redis的CPU使用率只有一半不到了,這也就意味著如果我再把剩下的這一半CPU用起來還可以得到更高的吞吐,而如果沒有predixy這樣一層的話,測試1結(jié)果告訴我們redis的CPU利用率已經(jīng)到頭了,吞吐已經(jīng)不可能再提高。
測試3和測試4說明的問題與測試1和測試2一樣,如果我只做了這四個測試,那么看起來好像代理的引入完全有助于提升我們的吞吐嘛。正如上面所分析的那樣,predixy提升吞吐的原因是因為采用了批量發(fā)送手段。那么如果客戶端的使用場景就是批量發(fā)送命令,那結(jié)果會如何呢?
于是有了后面四個測試,后面四個測試給我們的直接感受就是太震撼了,吞吐直接提升幾倍甚至10倍!其實也正是因為redis批量模式下性能非常強悍,才使得predixy在單命令情況下改進吞吐成為可能。當然到了批量模式,從測試結(jié)果看,predixy使得服務(wù)的吞吐下降了。
具體到批量set時,直連redis和通過predixy,redis的CPU使用率都滿了,雖然采用predixy使得redis的用戶態(tài)CPU從0.796提高到了0.940,但是吞吐卻不升反降,從782000到724000,大約下降了7.4%。至于為什么用戶態(tài)CPU利用率提高了吞吐卻下降了,要想知道原因就需要分析redis本身的實現(xiàn),這里我們就不做詳細探討??梢宰鲆粋€粗糙的解釋,在redis CPU跑滿的情況下,不同的負載情況會使得用戶態(tài)和內(nèi)核態(tài)的使用率不同,而這其中有一種分配情況會是吞吐最大,而用戶態(tài)使用率高于或者低于這種情況時都會出現(xiàn)吞吐下降的情況。
再來看批量get,直連redis時吞吐高達1708000,而通過predixy的話就只有935000了,下降了45%!就跟納了個人所得稅上限一般??吹竭@,剛剛對predixy建立的美好形象是不是又突然覺得要坍塌了?先別急,再看看其它指標,直連redis時,redis CPU跑滿;而通過predixy時redis CPU只用了0.596,也就是說redis還有四成的CPU等待我們?nèi)赫ァ?/p>
寫到這,既然上面提到批量get時,通過predixy的話redis并未發(fā)揮出全部功力,于是就想著如果全部發(fā)揮出來會是什么情況呢?我們繼續(xù)增加兩個測試,既然單個predixy在批量的情況下造成了吞吐下降,但是給我們帶來了一個好處是redis還可以提升的余地,那么我們就增加predixy的處理能力。因此我們把predixy改為三線程,再來跑一遍測試6和測試8。
兩個測試的整體結(jié)果如下。
三線程predixy批量set
三線程predixy批量get
測試指標 redis used redis user redis sys predixy used predixy user predixy sys redis qps predixy qps
predixy pipeline set?1.01?0.93?0.07?1.37?0.97?0.41?762000?762000?
predixy pipeline get?0.93?0.85?0.08?2.57?1.85?0.72?1718000?1718000?
原本在單線程predixy的批量set測試中,predixy和redis的CPU都已經(jīng)跑滿了,我們覺得吞吐已經(jīng)達到了極限,但是實際結(jié)果顯示在三線程predixy的批量set測試中,吞吐還是提高了,從原來的724000到現(xiàn)在的76200,與直連的782000只有2.5%的差距。多線程和單線程的主要差別在于單線程時predixy與redis只有一個連接,而三線程時有三個連接。
而對于三線程predixy的批量get測試,不出我們所料的吞吐得到了極大的提升,從之前的935000直接飆到1718000,已經(jīng)超過了直連的1708000。
最后,我們來總結(jié)一下,我們整個測試的場景比較簡單,只是單純的set、get測試,并且數(shù)據(jù)大小為默認的2字節(jié),實際的redis應(yīng)用場景遠比這復(fù)雜的多。但是測試結(jié)果的數(shù)據(jù)依舊可以給我們一些結(jié)論。代理的引入并不一定會降低服務(wù)的吞吐,實際上根據(jù)服務(wù)的負載情況,有時候引入代理反而可以提升整個服務(wù)的吞吐,如果我們不計較代理本身所消耗的資源,那么引入代理幾乎總是一個好的選擇。根據(jù)我們上面的分析,一個最簡單實用的判斷原則,看看你的redis CPU使用情況,如果花費了太多時間在內(nèi)核態(tài),那么考慮引入代理吧。
評論
查看更多