http://blog.csdn.net/oyl822/article/details/44460949
Redis是一個(gè)響應(yīng)式的服務(wù),當(dāng)客戶端發(fā)送一個(gè)請求后,就處于阻塞狀態(tài)等待Redis返回結(jié)果。這樣一次命令消耗的時(shí)間就包括三個(gè)部分:請求從客戶端到服務(wù)器的時(shí)間、結(jié)果從服務(wù)器到客戶端的時(shí)間和命令真正執(zhí)行時(shí)間,前兩個(gè)部分消耗的時(shí)間總和稱為RTT(Round Trip Time),當(dāng)客戶端與服務(wù)器存在網(wǎng)絡(luò)延時(shí)時(shí),RTT就可能會很大,這樣就會導(dǎo)致性能問題。管道(Pipeline)就是為了改善這個(gè)情況的,利用管道,客戶端可以一次性發(fā)送多個(gè)請求而不用等待服務(wù)器的響應(yīng),待所有命令都發(fā)送完后再一次性讀取服務(wù)的響應(yīng),這樣可以極大的降低RTT時(shí)間從而提升性能。
下面這個(gè)例子,在本地分別以普通請求和管道對一個(gè)鍵調(diào)用2000次incr命令的測試。
- public class App
- {
- public static void main( String[] args ) {
- long start = System.currentTimeMillis();
- withoutPipeline();
- System.out.println("Without Pipeline takes: " + (System.currentTimeMillis() - start) + " ms.");
-
- start = System.currentTimeMillis();
- withPipeline();
- System.out.println("With Pipeline takes: " + (System.currentTimeMillis() - start) + " ms.");
- }
-
- public static void withPipeline() {
- Jedis jedis = null;
-
- try {
- jedis = new Jedis("localhost", 6379);
- jedis.flushDB();
- Pipeline p = jedis.pipelined();
-
- p.set("thekey", Integer.toString(0));
-
- for (int i = 1; i <= 2000; i++) {
- p.incr("thekey");
- }
-
- Response<String> r = p.get("thekey");
-
- p.sync();
-
- System.out.println(r.get());
- } finally {
- jedis.close();
- }
-
- }
-
- public static void withoutPipeline() {
- Jedis jedis = null;
-
- try {
- jedis = new Jedis("localhost", 6379);
- jedis.flushDB();
- jedis.set("thekey", Integer.toString(0));
-
- for (int i = 1; i <= 2000; i++) {
- jedis.incr("thekey");
- }
-
- System.out.println(jedis.get("thekey"));
- } finally {
- jedis.close();
- }
-
- }
- }
-
- //輸出結(jié)果
- 2000
- Without Pipeline takes: 183 ms.
- 2000
- With Pipeline takes: 47 ms.
結(jié)果很直觀的反映出兩者的差別,要知道這是在本地測試,幾乎不存在網(wǎng)絡(luò)延時(shí)的問題,如果是在不同的網(wǎng)段測試的話,效果會更明顯。雖然管道在一定程度上對性能有所提升,但是在使用時(shí)一點(diǎn)要注意,每個(gè)命令的返回結(jié)果是先被緩存在服務(wù)器端的,最后一次性返回給客戶端。如果一次批量提交涉及大量的返回結(jié)果,可能會導(dǎo)至服務(wù)器的內(nèi)存溢出,這在生產(chǎn)環(huán)境是致命的,一次批次處理多少量,最好在設(shè)計(jì)階段做出合理評估。
最后,管道只是一個(gè)方案,并不意味著在任何時(shí)候都要盡可能的使用它,而是應(yīng)該結(jié)合考慮網(wǎng)絡(luò)延遲時(shí)間、業(yè)務(wù)涉及的請求量等等因素綜合考慮,畢竟創(chuàng)建管道本身也會有一定的消耗。