一、性能問題
1、概述
Redis使用的是客戶端-服務端這種CS模型和請求/響應的TCP服務器。這意味着通常情況下一個請求會遵循以下步驟:
- 客戶端向服務端發送一個請求,並監聽SOCKET返回,通常是阻塞模式,等待服務端響應。
- 服務端處理客戶端發來的命令並進行處理,最終將結果返回給客戶端。
redis確實是非阻塞,但是redis服務端處理是非阻塞,用戶端來講還是阻塞。
至於redis爲什麼這麼快,可以看這個一文帶你徹底掌握Redis爲什麼這麼快?
2、舉例
也就是說一個客戶端可以通過一個socket連接發起多個請求命令,每個請求命令發出後客戶端通常會阻塞並等待redis服務器處理,redis處理完請求命令後會將結果通過響應報文返回給客戶端。因爲當執行多條命令的時候都需要等待上條命令執行完畢才能執行,比如:
set k1 1
keys *
get k1
Redis採取IO由於通信會有網絡延遲,假如 client 和 server 之間的包傳輸時間需要0.125秒。那麼上面的三個命令6個報文至少需要0.75秒才能完成。這樣即使 redis 每秒能處理100個命令,而我們的 client 也只能一秒鐘發出四個命令。這顯然沒有充分利用 redis 的處理能力。
二、什麼是Pipeline
我們已經知道上面的問題了,也知道性能是耗費再了通信上,這時候pipeline橫空出世,他的目的是將一批命令打包到一個內部維護的queue裏,然後建立socket與server交互,這時候是隻會發送一次命令,也就是隻會交互一次,然後queue內的命令都執行完後會一起返回結果,這樣大大減少了通信的次數,自然降低了通信所耗費的時間。queue是先進先出,所以可以保證執行順序。
三、說明
並不是pipeline就無敵了,以後都用這個。這需要看需求的。比如你的需求get key 實時性很高,而且要用他的返回值做處理。那你把get key這個命令與其他100個命令放到一起去批處理進行,那反而在業務角度分析,效率更爲低下。
四、測試
如下demo是從https://blog.csdn.net/u011489043/article/details/78769428這個地址而來,如有侵權請聯繫我~
/*
* 測試普通模式與 PipeLine 模式的效率:
* 測試方法:向 redis 中插入 10000 組數據
*/
public static void testPipeLineAndNormal(Jedis jedis) throws InterruptedException {
Logger logger = Logger.getLogger("javasoft");
long start = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
jedis.set(String.valueOf(i), String.valueOf(i));
}
long end = System.currentTimeMillis();
logger.info("the jedis total time is:" + (end - start));
Pipeline pipe = jedis.pipelined(); // 先創建一個 pipeline 的鏈接對象
long start_pipe = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
pipe.set(String.valueOf(i), String.valueOf(i));
}
pipe.sync(); // 獲取所有的 response
long end_pipe = System.currentTimeMillis();
logger.info("the pipe total time is:" + (end_pipe - start_pipe));
BlockingQueue<String> logQueue = new LinkedBlockingQueue<String>();
long begin = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
logQueue.put("i=" + i);
}
long stop = System.currentTimeMillis();
logger.info("the BlockingQueue total time is:" + (stop - begin));
}
五、使用場景
不適用場景:
- 要求可靠性高,每次都需要實時知道這次操作是否成功,數據是否寫入redis了等對實時性的這種需求都不適合。
適用場景:
- 對實時性要求不高的
- 批量的將數據寫入 redis,允許一定比例的寫入失敗
比如羣發短信、郵件這種,失敗了我補償,我不需要及時知道發送結果的,這種用pipeline合適 。
六、總結
- 什麼是Pipeline
- Pipeline可以性能調優
- 使用場景
七、個人公衆號
微信公衆號【Java碼農社區】