redis pipeline服用指南

pipeline是Redis的一個提升吞吐量的機制,適用於多key讀寫場景,好比同時讀取多個key的value,或者更新多個key的value。 工做過程當中發現挺多小夥伴都對pipeline多少有些瞭解,可是更深刻的理解或者說有哪些坑就不知道了,下面我們就一塊兒分析下redis pipeline機制,揭開它的神祕面紗。redis

Redis自己是基於Request/Response協議(停等機制)的,正常狀況下,客戶端發送一個命令,等待Redis返回結果,Redis接收到命令,處理後響應。在這種狀況下,若是同時須要執行大量的命令,那就是等待上一條命令應答後再執行,這中間不只僅多了RTT(Round Time Trip),並且還頻繁調用系統IO,發送網絡請求。爲了提高效率,這時候pipeline出現了,它容許客戶端能夠一次發送多條命令,而不等待上一條命令執行的結果,這和網絡的Nagel算法有點像(TCP_NODELAY選項)。 pipeline不只減小了RTT,同時也減小了IO調用次數(IO調用涉及到用戶態到內核態之間的切換) 。算法

要支持Pipeline,其實既要服務端的支持,也要客戶端支持。對於服務端來講,所須要的是可以處理一個客戶端經過同一個TCP鏈接發來的多個命令,能夠理解爲,這裏將多個命令切分,和處理單個命令同樣(以前老生常談的黏包現象),Redis就是這樣處理的。而客戶端,則是要將多個命令緩存起來,緩衝區滿了或者達到發送條件就發送出去,最後才處理Redis的應答。緩存

注意:Redis的Pipeline和Transaction(Redis事務)不一樣,Transaction會存儲客戶端的命令,最後一次性執行,而Pipeline則是處理一條(批次),響應一條,從兩者的不一樣處理機制來看,Redis事務中命令的執行是原子的(注意,其中一部分命令出現錯誤後續命令會繼續執行,這裏的原子說的是命令執行是完整的,中間不會被其餘Redis命令所打斷),而pipeline中命令的執行不必定是原子的。可是這裏卻有一點不一樣,就是pipeline機制中,客戶端並不會調用read去讀取socket裏面的緩衝數據(除非已經發完pipeline中全部命令),這也就形成了,若是Redis應答的數據填滿了該接收緩衝(SO_RECVBUF),那麼客戶端會經過ACK,WIN=0(接收窗口)來控制服務端不能再發送數據,那樣子,數據就會緩衝在Redis的客戶端應答緩衝區裏面。因此須要 注意控制Pipeline的大小 。以下圖:

這裏能夠設想一下,若是客戶端經過ACK,WIN=0(接收窗口)來控制服務端不能再發送數據,那麼數據就會堆積在服務端socket發送緩衝區中,若是服務端socket發送緩衝區也滿了,那麼此時服務端調用write(socket)就會阻塞或者失敗。服務器

既然提到了tcp/ip的滑動窗口概念,這裏就簡單總結下滑動窗口:網絡

滑動窗口在TCP中的做用是提供TCP的可靠性和流控特性,滑動窗口可分爲發送窗口和接收窗口,它們分別對應於發送緩衝區和接收緩衝區。發送窗口的大小是根據客戶端接收緩衝區的大小而設定的(三次握手的目的是鏈接服務器指定端口,創建 TCP 鏈接,並同步鏈接雙方的序列號和確認號,交換 TCP 窗口大小信息)。socket

發送窗口中包含的內容是已發送但還未收到Ack的數據和未發送但對端容許發送的數據。tcp

TCP接收緩衝區中包含應用爲讀取數據、已接收數據(已回覆ACK)、待接收,其中待接收空間可稱爲接收窗口。性能

使用pipeline過程當中,要注意控制一次pipeline中的命令總大小,不能使響應結果撐爆socket接收緩衝區。這裏咱們思考一個問題,還有沒有其餘方式提升pipeline的處理性能呢?理論上是有的,好比可使用數據壓縮機制,進一步減少數據傳輸的總大小,不過這須要客戶端和服務端提供解壓縮機制,同時會耗費必定量服務器CPU。3d

相關文章
相關標籤/搜索