標籤:tcp串連 tween 0ms 延遲 詳情 實戰 為什麼 fas 模式
管道技術並不是Redis特有的,管道技術在電腦科學中有很多地方的應用。
來自wiki的解釋:
In computing, a pipeline, also known as a data pipeline,[1] is a set of data processing elements connected in series, where the output of one element is the input of the next one. The elements of a pipeline are often executed in parallel or in time-sliced fashion. Some amount of buffer storage is often inserted between elements.
在電腦中,管道又叫做資料管道,是資料處理元件。一個元件的輸出作為另一個元件的輸入。管道中元素經常是並行或者是基於事件分區。在元素之間會插入緩衝區。
說白了就是傳輸計算元素。與電腦領域相關的管道非常多,其中平時應用開發中遇到的就是網路通訊協定的HTTP pipelining。
HTTP Pipelining
HTTP pipelining is a technique in which multiple HTTP requests are sent on a single TCP connection without waiting for the corresponding responses.[1]
HTTP pipelining是一種技術,多個HTTP請求基於一個TCP串連以無等待匹配的響應的方式被發送。
HTTP中引入pipelining主要是為了提高效能。在一些高延遲的網路中,如果需要等待上一個HTTP請求的響應後再發送下一個請求,那麼網路延遲勢必是效能瓶頸之所在。pipelining為瞭解決這個問題,即流水線式發送HTTP請求,client不等待上一個請求的響應,只要server端按照請求的順序返迴響應即可。這樣雖然無法從根本上解決網路延遲的問題,但是卻可以減少request/response這種模式帶來的環回時間。
Pipelining帶來了以下的優勢:
- 如上所述,減少了多個請求的整體環回時間,提高了效能
- 對於server端,能夠在單位時間內接收到更多的請求,在server效能滿足的前提下,提高了server端的輸送量
同樣萬物平衡,Pipelining也有很多限制:
- 請求之間應該保證無依賴,後一個請求不能依賴前一個請求的響應結果。這種情境不適合使用pipelining
- 非等冪性請求不能使用pipelining(如post請求),同樣的post請求會改變資源的狀態,在使用pipelining技術中,會導致不等冪
引用wiki和《HTTP權威指南》中關於HTTP pipelining的描述:
參考
Pipelining
HTTP pipelining
《HTTP權威指南》
Redis-Pipelining
在看完pipelining,相信大家對管道(流水線)技術有一個初識。下面再來看下它是如何在Redis中被應用,為什麼應用。
- Redis Pipelining介紹
- Redis Pipelining解決的問題
- Jedis中Pipelining的使用
- Jedis中的Pipleling的Benchmark
- Redis Pipelining在項目實戰中的應用
一.Redis Pipelining介紹
Redis是是一種client-server的request/response的模式,Redis有單獨的TCP Server。
- client發送請求請求到server端,然後需要阻塞等待server端的響應
- server端處理請求然後返迴響應給client
即如上中介紹的HTTP的request/response一樣。在這種模式中,資料包必須從client發送到server端,然後再從server端返回到client端,這個時間叫做RTT(Round Trip Time)。
假設Redis Server每秒能處理100k請求,但是RTT是250ms,這樣Redis Server實際每秒只能處理4個請求,而且這種影響會隨著網路延遲越大而逐漸加劇。所帶來的直接影響:
- 阻塞用戶端線程或進程,消耗資源,大量請求時無疑降低client效能
- 降低server端的輸送量
為瞭解決該問題,需要一種client無等待響應的方式發送請求至server的模式,即Redis pipelining。
Redis pipelining使得client能夠無等待響應的方式連續發送多條命令請求至Redis Server端,然後Server端按照請求順序返迴響應結果,類似:
client> set k0 v0;client> set k1 v1;client> set k2 v2;server> okserver> okserver> ok
二.Redis Pipelining解決的問題
從以上的Redis pipelining介紹中可以看出,Redis pipelining降低了高延遲網路中,request/response方式帶來的請求應答的環回時間消耗:
- 無序等待響應的方式發送請求,減少等待時間(特別在高延遲網路中)
- 一次性返迴響應,減少多次響應的帶來的時間消耗
更重要的一點是,在request/response的方式中,逐次發送請求至server端,server端每次都需要read/write,這裡的read/write是systcall,涉及到核心態和使用者態的切換,非常消耗系統資源。Redis pipelining的方式盡量減少了這種系統狀態的切換開銷。
三.Jedis中Pipelining的使用
Pipelining急需要Redis Server端的支援又需要Redis client的支援。client需要能夠不擷取響應的情況下發送多個命令,server端需要編排好響應以請求的順序返回給用戶端。
Redis的經典Client jedis是支援Pipelining的。使用方式可以分為兩種,擷取回應程式式也可以分為兩種。
1.使用pipelining方式:
- 直接使用pipelining
- 在事務中使用pipelining
2.擷取回應程式式:
- 同步,一次性擷取所有請求的響應,以list方式返回
- 同步,在調用pipelining的操作時,指定返回的響應
關於測試的代碼和pipelining的api使用詳情可以戮
四.Jedis中的Pipleling的Benchmark
前面第二節中分析Pipelining就是解決網路延遲,提高輸送量。那麼在使用Pipelining的情況下,相對於不使用的情況下,效能是否提高了?提高多少?
一切都需要用資料來說話。下面分別跑下測試,比較下。Jedis的測試案例中有Benchmark模組,這裡直接使用其Pipelining和GetSet的Benchmark的測試程式:
執行命令數 |
ops(no pipelining/pipelining) |
100 |
6666 ops/9090 ops |
100000 |
26870 ops/316455 ops |
1000000 |
28967 ops/422922 ops |
從以上的可以看出使用Pipelining的情況下大致能提高20倍的效能。
五.Redis Pipelining在項目實戰中的應用
首先認識下Pipelining的特點:
兩個特點決定了應用情境必須有以下特點:
- 由於是批量流水線發送,所以每個請求之間需要無狀態,即後請求不依賴前請求的響應結果
- 由於一次返迴響應,所以響應中可能會存在有些請求命令執行成功,有些失敗。所以應用情境必須能夠容忍資料處理錯誤或者資料丟失的風險,或者能夠接受通過其他機制彌補丟失或者錯誤的資料方式
一般適用於批量快取資料或者預先載入快取資料。因為不需要逐條發送緩衝的資料,可以pipelining方式發送。因為是快取資料,緩衝的情境能夠容忍某一些資料緩衝失敗,無非是沒有命中,再次載入單條載入至緩衝。
最近在做一個業務資料預警檢查的項目,採用責任鏈模式,將需要預警檢查的每條資料遍曆責任鏈,完成資料一致性校正檢查。責任鏈中每個檢查器都是可配置生效失效,而且支援可擴充檢查器。擴充性、可配置型較強,但是帶來的問題即每條需要預警檢查的資料遍曆責任鏈檢查器時,都需要重複的查詢一些其他的表資料與配置。這裡從而引入了巨大的磁碟I/O,產生效能瓶頸。
後來想如果,能將這些其他表的資料預先載入進入緩衝中,每次遍曆需要預警檢查的資料時,不從DB中查詢擷取,直接從緩衝中擷取即可。由於服務是叢集的,所以需要使用分布式緩衝且本機快取容量有限。
這裡最終採用懶載入的方式緩衝其他表的資料或者配置,在預警檢查第一條資料時,各個檢查器將其他表的資料或者配置載入到緩衝中,同時採用pipelining模式緩衝到Redis中。
這樣下條預警資料的遍曆檢查器時,每個檢查器從緩衝中擷取其他表的資料或者配置即可。大幅度減少DB帶來的I/O,突破效能瓶頸。
Redis(六)管道(Pipelining)