初識 Redis pipelining

使用Redis pipelining可以加速Redis查詢

1. 請求/響應協議和RTT

Redis是一個使用client-server模型和請求/響應協議的TCP服務器。

過程如下:

  1. client 發送一個請求給server,通常以阻塞的方式從套接字中讀取server的響應。
  2. server 處理命令並將響應發送回client
Client: INCR X
Server: 1
Client: INCR X
Server: 2
Client: INCR X
Server: 3
Client: INCR X
Server: 4

clientserver 通過網絡連接。 這樣的連接可能非常快(環回接口),也可能非常慢(通過 Internet 建立的連接在兩臺主機之間有很多躍點)。 無論網絡等待時間是多少,數據包都會有一段時間從 client 傳到 server ,然後再從 server 傳回 client

這段時間稱爲RTT(往返時間)。 當 client 需要連續執行多個請求時(例如,將多個元素添加到同一列表中,或使用許多鍵填充數據庫),很容易看到這會對性能產生怎樣的影響。 例如,如果RTT 時間爲250毫秒(在 Internet 上的鏈接非常慢的情況下),即使 server 有每秒處理10萬個請求的能力,我們每秒也最多隻可以處理4個請求。

如果使用的接口是環回接口(loopback interface),則 RTT 會短得多(例如,我的主機顯示 ping 到127.0.0.1時爲0.044毫秒),但是如果連續執行多次寫操作,RTT 則會大得多。

幸運的是,有一種方法可以改善此用例。

3. Redis Pipelining

可以實現請求/響應服務器,以便 即是 client 尚未讀取舊響應,它也可以處理新請求。 這樣,可以將多個命令發送到服務器,而根本不用等待答覆,最後來讀取答覆。

這就是pipelining,在近數十年來已經廣泛使用的技術。 例如,許多POP3協議已支持此功能,從而極大地加快了從服務器下載新電子郵件的過程。

Redis從很早就開始支持管道傳輸,因此無論您運行的是哪個版本,都可以在Redis中使用管道傳輸。

按如下過程,只需一次RTT即可:

  • Client: INCR X
  • Client: INCR X
  • Client: INCR X
  • Client: INCR X
  • Server: 1
  • Server: 2
  • Server: 3
  • Server: 4

需要注意的是,當 clientpipelining發送命令時,server必須將回復也放入內存隊列中。因此,如果使用 pipelining, 最好一次性批量發送大量(例如 10K)的命令。所以管道中命令的數量應該有一個合理的值,不能無限多

3. 不只是RTT問題

pipelining 不僅減少 RTT 的延遲成本,它實際上還可以極大地提高給定 Redis 服務器每秒可執行的總操作數。 在不使用 pipelining 時,執行命令得到回覆這個過程很快,但是整個Redis的服務效率被 socket I/O 限制了。

使用 pipelining 時,通常使用1次 read() 系統調用讀取許多命令,再使用1次 write() 系統調用傳遞多個答覆。 因此,每秒執行的總查詢數最初隨着 pipelines 地增長而幾乎呈線性增加,最終趨於某一個值。

4. Pipelining VS Scripting

使用 Redis LUA 腳本(在Redis 2.6或更高版本中可用),使用Redis LUA腳本 來完成某些 pipelining 的工作更加高效。 LUA腳本 的一大優勢在於,它能夠以最小的延遲讀取和寫入數據,從而使讀取,計算,寫入等操作非常快(在某些情況下,pipelining無濟於事,例如 client 需要在執行寫命令之前得到服務器的回覆)。

有時,應用程序可能還希望在管道中發送EVALEVALSHA命令。Redis 通過SCRIPT LOAD命令實現此功能(它可以保證調用EVALSHA不會失敗)。

5. 擴展

前面我們提到,爲了解決網絡開銷帶來的延遲問題,可以把客戶端和服務器放到一臺物理機上。但是有時用benchmark進行壓測的時候發現這仍然很慢。

這時客戶端和服務端實際是在一臺物理機上的,所有的操作都在內存中進行,沒有網絡延遲,按理來說這樣的操作應該是非常快的。爲什麼會出現上面的情況的呢?

實際上,這是由內核調度導致的。比如說,benchmark運行時,讀取了服務器返回的結果,然後寫了一個新的命令。這個命令就在迴環接口的send buffer中了,如果要執行這個命令,內核需要喚醒Redis服務器進程。所以在某些情況下,本地接口也會出現類似於網絡延遲的延遲。其實是內核特別繁忙,一直沒有調度到Redis服務器進程。

6. 參看文獻

Redis 官方文檔 pipelining
速度不夠,管道來湊——Redis管道技術

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章