redis批量操作pipeline管道操作方法
redis | pipeline(管道)
背景
Redis是一種基于客戶端-服務(wù)端模型以及請求/響應(yīng)的TCP服務(wù)。這意味著通常情況下一個請求會遵循以下步驟:
- 客戶端向服務(wù)端發(fā)送一個查詢請求,并監(jiān)聽 Socket 返回,通常是以阻塞模式,等待服務(wù)端響應(yīng)。
- 服務(wù)端處理命令,并將結(jié)果返回給客戶端。
Redis 客戶端與 Redis 服務(wù)器之間使用 TCP 協(xié)議進行連接,一個客戶端可以通過一個 socket 連接發(fā)起多個請求命令。每個請求命令發(fā)出后 client 通常會阻塞并等待 redis 服務(wù)器處理,redis 處理完請求命令后會將結(jié)果通過響應(yīng)報文返回給 client,因此當執(zhí)行多條命令的時候都需要等待上一條命令執(zhí)行完畢才能執(zhí)行。
Redis本身是基于一個Request一個Response方式的同步請求,正常情況下,客戶端發(fā)送一個命令,等待Redis服務(wù)器返回結(jié)果,Redis服務(wù)器接收到命令,處理后響應(yīng)結(jié)果給客戶端。
無論網(wǎng)絡(luò)延如何延時,數(shù)據(jù)包總是能從客戶端到達服務(wù)器,并從服務(wù)器返回數(shù)據(jù)回復(fù)客戶端。 這個時間被稱之為 RTT (Round Trip Time - 往返時間)。
如果同時需要執(zhí)行大量的命令,那么就要等待上一條命令應(yīng)答后再執(zhí)行,這中間不僅僅多了RTT(Round Time Trip),而且還頻繁調(diào)用系統(tǒng)IO,發(fā)送網(wǎng)絡(luò)請求,同時需要redis調(diào)用多次read() 和write()系統(tǒng)方法,系統(tǒng)方法會將數(shù)據(jù)從用戶態(tài)轉(zhuǎn)移到內(nèi)核態(tài),這樣就會對進程上下文有比較大的影響了。
什么是流水線(pipeline)
官網(wǎng):https://redis.io/docs/manual/pipelining/
管道(pipeline)可以一次性發(fā)送多條命令并在執(zhí)行完后一次性將結(jié)果返回,pipeline 通過減少客戶端與 redis 的通信次數(shù)來實現(xiàn)降低往返延時時間,而且 Pipeline 實現(xiàn)的原理是隊列,而隊列的原理是時先進先出,這樣就保證數(shù)據(jù)的順序性。
通俗點:pipeline就是把一組命令進行打包,然后一次性通過網(wǎng)絡(luò)發(fā)送到Redis。同時將執(zhí)行的結(jié)果批量的返回回來。
pipeline,將多個命令一次執(zhí)行,一次發(fā)送出去,節(jié)省網(wǎng)絡(luò)時間。 pipeline技術(shù)最顯著的優(yōu)勢是提高了 redis 服務(wù)的性能。
管道技術(shù)并不是Redis特有的技術(shù),管道技術(shù)往往需要客戶端-服務(wù)器的共同配合,大部分工作任務(wù)其實是在客戶端完成,很顯然Redis支持管道技術(shù),按照官網(wǎng)的意思,Redis的最低版本就考慮了管道技術(shù)的支持性設(shè)計。
如下圖,多個連續(xù)的incr指令,使用pipeline(管道)后,多個連續(xù)的incr指令只會花費一次網(wǎng)絡(luò)來回開銷,這個開銷會隨著n數(shù)值的增大,大幅減少網(wǎng)絡(luò)io開銷,從而提升整體服務(wù)的性能。管道技術(shù)優(yōu)化的是網(wǎng)絡(luò)傳輸?shù)暮臅r時間。
總結(jié):使用管道技術(shù)可以解決多個命令執(zhí)行時的網(wǎng)絡(luò)等待,它是把多個命令整合到一起發(fā)送給服務(wù)器端處理之后統(tǒng)一返回給客戶端,這樣就免去了每條命令執(zhí)行后都要等待的情況,從而有效地提高了程序的執(zhí)行效率,但使用管道技術(shù)也要注意避免發(fā)送的命令過大,或管道內(nèi)的數(shù)據(jù)太多而導致的網(wǎng)絡(luò)阻塞。
適用場景
如果出現(xiàn)集中大批量的請求時,因為每個請求都要經(jīng)歷先請求再響應(yīng)的過程,這就會造成網(wǎng)絡(luò)資源浪費,此時就需要管道技術(shù)來把所有的命令整合一次發(fā)給服務(wù)端,再一次響應(yīng)給客戶端,這樣就能大大的提升了 Redis 的響應(yīng)速度。
要求實時性也沒那么高,但是最求高性能,這時候用 pipeline 最好了。
benchmark壓測pipeline
使用Redis提供的benchmark對Redis進行性能測試,
如過你是Windows下的Redis,在安裝目錄下有個redis-benchmark.exe,進入cmd命令模式測試即可。
如果你是在Linux下的redis,在安裝目錄的src目錄下有個redis-benchmark
通過普通方式測試set指令和pipeline方式測試set指令,可以看到Redis服務(wù)不同的QPS:
普通set方式,Redis QPS 大概在5.3萬左右
當使用pipeline set時,隨著管道內(nèi)并行請求數(shù)量的增加,Redis QPS可以達到100萬以上
代碼測試-python: StrictRedis
#引入模塊
#這個模塊中提供了StrictRedis對象,?于連接redis服務(wù)器,并按照不同類型提供 了不同?法,進?交互操作
from redis import StrictRedis
我們使用 StrictRedis客戶端提供的 Pipeline 對象來實現(xiàn)管道技術(shù)。首先先獲取 Pipeline 對象,再為 Pipeline 對象設(shè)置需要執(zhí)行的命令,最后再使用excute() 方法來統(tǒng)一執(zhí)行這些命令,代碼如下:
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)
接下來我們用普通的命令執(zhí)行此循環(huán),看下程序的執(zhí)行時間,代碼如下:
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)
從結(jié)果可以看出,管道的執(zhí)行時間是0.165秒,而普通命令執(zhí)行時間是9.09秒,管道技術(shù)要比普通的執(zhí)行快了 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注意事項
管道技術(shù)雖然有它的優(yōu)勢,但在使用時還需注意以下幾個細節(jié):
- 每次pipeline攜帶數(shù)量不推薦過大,否則會影響網(wǎng)絡(luò)性能
- 如果管道的數(shù)據(jù)過多可能會導致客戶端的等待時間過長,導致網(wǎng)絡(luò)阻塞
- 發(fā)送的命令數(shù)量不會被限制,但輸入緩存區(qū)也就是命令的最大存儲體積為 1GB,當發(fā)送的命令超過此限制時,命令不會被執(zhí)行,并且會被 Redis 服務(wù)器端斷開此鏈接
- pipeline每次只能作用在一個Redis節(jié)點上
- 部分客戶端自己本身也有緩存區(qū)大小的設(shè)置,如果管道命令沒有沒執(zhí)行或者是執(zhí)行不完整,可以排查此情況
參考資料
分布式緩存Redis之Pipeline(管道)
URL: https://blog.csdn.net/u011489043/article/details/78769428
【推薦】Redis精通系列——Pipeline(管道)
參考URL: https://blog.csdn.net/qq_41125219/article/details/120298689
Redis的批量操作是什么?怎么實現(xiàn)的延時隊列?以及訂閱模式、LRU
參考URL: https://baijiahao.baidu.com/s?id=1687918953043523907
到此這篇關(guān)于redis批量操作pipeline管道的文章就介紹到這了,更多相關(guān)redis批量操作內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
redis學習之RDB、AOF與復(fù)制時對過期鍵的處理教程
這篇文章主要給大家介紹了關(guān)于redis學習之RDB、AOF與復(fù)制時對過期鍵處理的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用redis具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧2019-11-11Redis數(shù)據(jù)結(jié)構(gòu)之intset整數(shù)集合使用學習
這篇文章主要為大家介紹了Redis數(shù)據(jù)結(jié)構(gòu)之整數(shù)集合使用學習,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-07-07Quarkus集成redis操作Redisson實現(xiàn)數(shù)據(jù)互通
這篇文章主要為大家介紹了Quarkus集成redis操作Redisson實現(xiàn)數(shù)據(jù)互通的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步2022-02-02