首頁 > 軟體

redis批次操作pipeline管道操作方法

2022-10-02 14:01:50

redis | pipeline(管道)

背景

Redis是一種基於使用者端-伺服器端模型以及請求/響應的TCP服務。這意味著通常情況下一個請求會遵循以下步驟:

  • 使用者端向伺服器端傳送一個查詢請求,並監聽 Socket 返回,通常是以阻塞模式,等待伺服器端響應。
  • 伺服器端處理命令,並將結果返回給使用者端。

Redis 使用者端與 Redis 伺服器之間使用 TCP 協定進行連線,一個使用者端可以通過一個 socket 連線發起多個請求命令。每個請求命令發出後 client 通常會阻塞並等待 redis 伺服器處理,redis 處理完請求命令後會將結果通過響應報文返回給 client,因此當執行多條命令的時候都需要等待上一條命令執行完畢才能執行。

Redis本身是基於一個Request一個Response方式的同步請求,正常情況下,使用者端傳送一個命令,等待Redis伺服器返回結果,Redis伺服器接收到命令,處理後響應結果給使用者端。

無論網路延如何延時,封包總是能從使用者端到達伺服器,並從伺服器返回資料回覆使用者端。 這個時間被稱之為 RTT (Round Trip Time - 往返時間)。

如果同時需要執行大量的命令,那麼就要等待上一條命令應答後再執行,這中間不僅僅多了RTT(Round Time Trip),而且還頻繁呼叫系統IO,傳送網路請求,同時需要redis呼叫多次read() 和write()系統方法,系統方法會將資料從使用者態轉移到核心態,這樣就會對程序上下文有比較大的影響了。

什麼是流水線(pipeline)

官網:https://redis.io/docs/manual/pipelining/

管道(pipeline)可以一次性傳送多條命令並在執行完後一次性將結果返回,pipeline 通過減少使用者端與 redis 的通訊次數來實現降低往返延時時間,而且 Pipeline 實現的原理是佇列,而佇列的原理是時先進先出,這樣就保證資料的順序性。

通俗點:pipeline就是把一組命令進行打包,然後一次性通過網路傳送到Redis。同時將執行的結果批次的返回回來。

pipeline,將多個命令一次執行,一次傳送出去,節省網路時間。 pipeline技術最顯著的優勢是提高了 redis 服務的效能。

管道技術並不是Redis特有的技術,管道技術往往需要使用者端-伺服器的共同配合,大部分工作任務其實是在使用者端完成,很顯然Redis支援管道技術,按照官網的意思,Redis的最低版本就考慮了管道技術的支援性設計。

如下圖,多個連續的incr指令,使用pipeline(管道)後,多個連續的incr指令只會花費一次網路來回開銷,這個開銷會隨著n數值的增大,大幅減少網路io開銷,從而提升整體服務的效能。管道技術優化的是網路傳輸的耗時時間。

總結:使用管道技術可以解決多個命令執行時的網路等待,它是把多個命令整合到一起傳送給伺服器端處理之後統一返回給使用者端,這樣就免去了每條命令執行後都要等待的情況,從而有效地提高了程式的執行效率,但使用管道技術也要注意避免傳送的命令過大,或管道內的資料太多而導致的網路阻塞。

適用場景

如果出現集中大批次的請求時,因為每個請求都要經歷先請求再響應的過程,這就會造成網路資源浪費,此時就需要管道技術來把所有的命令整合一次發給伺服器端,再一次響應給使用者端,這樣就能大大的提升了 Redis 的響應速度。

要求實時性也沒那麼高,但是最求高效能,這時候用 pipeline 最好了。

benchmark壓測pipeline

使用Redis提供的benchmark對Redis進行效能測試,
如過你是Windows下的Redis,在安裝目錄下有個redis-benchmark.exe,進入cmd命令模式測試即可。
如果你是在Linux下的redis,在安裝目錄的src目錄下有個redis-benchmark

通過普通方式測試set指令和pipeline方式測試set指令,可以看到Redis服務不同的QPS:

普通set方式,Redis QPS 大概在5.3萬左右
當使用pipeline set時,隨著管道內並行請求數量的增加,Redis QPS可以達到100萬以上

程式碼測試-python: StrictRedis

#引入模組
#這個模組中提供了StrictRedis物件,⽤於連線redis伺服器,並按照不同型別提供 了不同⽅法,進⾏互動操作

from redis import StrictRedis

我們使用 StrictRedis使用者端提供的 Pipeline 物件來實現管道技術。首先先獲取 Pipeline 物件,再為 Pipeline 物件設定需要執行的命令,最後再使用excute() 方法來統一執行這些命令,程式碼如下:

from redis import StrictRedis
redis_cli = StrictRedis(host="xx", port=xx, password="xx", db=xx, decode_responses=True)
import time
def main():
    t1 = time.time()
    pipe = redis_cli.pipeline()
    num = 1
    for i in range(100):
        pipe.set("name_" + str(num), num)
        pipe.delete("name_" + str(num))
        num += 1
    pipe.execute()
    t2 = time.time()
    print(t2-t1)

接下來我們用普通的命令執行此迴圈,看下程式的執行時間,程式碼如下:

def test():
    t1 = time.time()
    num = 10000
    for i in range(100):
        redis_cli.set("test_" + str(num), num)
        redis_cli.delete("test_" + str(num))
        num += 10
    t2 = time.time()
    print(t2 - t1)

從結果可以看出,管道的執行時間是0.165秒,而普通命令執行時間是9.09秒,管道技術要比普通的執行快了 56 倍。

程式碼測試-java:Jedis使用pipeline

package com.liziba.redis;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;
 
import java.io.IOException;

public class PipelineTest {
 
    public static void main(String[] args) throws IOException {
        Jedis client = new Jedis("127.0.0.1", 6379);
 
        long startPipe = System.currentTimeMillis();
        Pipeline pipe = client.pipelined();
        pipe.multi();
        for (int i = 0; i < 100000; i++) {
            pipe.set("pipe" + i, i + "" );
        }
        pipe.exec();
        pipe.close();
        long endPipe = System.currentTimeMillis();
        System.out.println("pipeline set cost time : " + (endPipe - startPipe) + "ms");
 
 
        for (int i = 0; i < 100000; i++) {
            client.set("normal" + i, i + "");
        }
        System.out.println("normal set cost time : " + (System.currentTimeMillis() - endPipe)+ "ms");
    }
}

pipeline注意事項

管道技術雖然有它的優勢,但在使用時還需注意以下幾個細節:

  • 每次pipeline攜帶數量不推薦過大,否則會影響網路效能
  • 如果管道的資料過多可能會導致使用者端的等待時間過長,導致網路阻塞
  • 傳送的命令數量不會被限制,但輸入快取區也就是命令的最大儲存體積為 1GB,當傳送的命令超過此限制時,命令不會被執行,並且會被 Redis 伺服器端斷開此連結
  • pipeline每次只能作用在一個Redis節點上
  • 部分使用者端自己本身也有快取區大小的設定,如果管道命令沒有沒執行或者是執行不完整,可以排查此情況

參考資料

分散式快取Redis之Pipeline(管道)

URL: https://blog.csdn.net/u011489043/article/details/78769428
【推薦】Redis精通系列——Pipeline(管道)
參考URL: https://blog.csdn.net/qq_41125219/article/details/120298689
Redis的批次操作是什麼?怎麼實現的延時佇列?以及訂閱模式、LRU
參考URL: https://baijiahao.baidu.com/s?id=1687918953043523907

到此這篇關於redis批次操作pipeline管道的文章就介紹到這了,更多相關redis批次操作內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com