深入理解redis中multi與pipeline
背景
由于對(duì)redis緩存中數(shù)據(jù)有批量操作,例如預(yù)熱緩存數(shù)據(jù),或者在列表頁批量去獲取緩存數(shù)據(jù),在使用了multi批量提交事務(wù)后,發(fā)現(xiàn)redis壓力高居不下,而使用了pipeline之后壓力回落了平常,也因?yàn)檫@個(gè)案例,特在此寫個(gè)分析與筆記。
multi
簡(jiǎn)介
標(biāo)記一個(gè)事務(wù)塊的開始。
事務(wù)塊內(nèi)的多條命令會(huì)按照先后順序被放進(jìn)一個(gè)隊(duì)列當(dāng)中,最后由 EXEC 命令原子性(atomic)地執(zhí)行。
實(shí)現(xiàn)原理
我用php擴(kuò)展調(diào)起redis服務(wù),執(zhí)行,代碼如下:
$redis = new redis(); $redis->connect('127.0.0.1',6379); $handle = $redis->multi(); $handle->incr('a'); $handle->incr('b'); $handle->exec();
為了查看這期間具體的連接過程,用wireshark監(jiān)聽回環(huán)地址端口6379,抓包請(qǐng)求如下圖所示:
redis客戶端與服務(wù)端建立連接后,multi標(biāo)記事務(wù)開始,之后每次執(zhí)行,服務(wù)端返回queued隊(duì)列標(biāo)志。查看redis源碼src/multi.c文件:
void queueMultiCommand(client *c) { multiCmd *mc; int j; c->mstate.commands = zrealloc(c->mstate.commands, sizeof(multiCmd)*(c->mstate.count+1)); mc = c->mstate.commands+c->mstate.count; mc->cmd = c->cmd; mc->argc = c->argc; mc->argv = zmalloc(sizeof(robj*)*c->argc); memcpy(mc->argv,c->argv,sizeof(robj*)*c->argc); for (j = 0; j < c->argc; j++) incrRefCount(mc->argv[j]); c->mstate.count++; }
在上述源碼中可以看到redis服務(wù)端每次會(huì)把事務(wù)塊中的命令保存到內(nèi)存中,上述簡(jiǎn)介已經(jīng)解釋過最后通過exec命令執(zhí)行,再看下面示例圖的返回結(jié)果可以了解到redis服務(wù)端一次性返回所有命令執(zhí)行返回結(jié)果。
pipeline
簡(jiǎn)介
客戶端將執(zhí)行的命令寫入到緩沖中,最后由exec命令一次性發(fā)送給redis執(zhí)行返回。
實(shí)現(xiàn)原理
同樣,用相關(guān)代碼調(diào)用redis抓包;
$redis = new redis(); $redis->connect('127.0.0.1',6379); $handle = $redis->pipeline(); $handle->incr('a'); $handle->incr('b'); $handle->exec();
繼續(xù)用wireshark抓包,如下圖所示
pipeline 客戶端請(qǐng)求包示例圖
這上面的圖片簡(jiǎn)要分析一下,pipeline管道操作是需要客戶端與服務(wù)端的支持,客戶端將命令寫入緩沖,最后再通過exec命令發(fā)送給服務(wù)端,服務(wù)端通過命令拆分,逐個(gè)執(zhí)行返回結(jié)果。
兩者的區(qū)別
由上面的請(qǐng)求也可以看出了兩者最明顯的區(qū)別是客戶端發(fā)送請(qǐng)求的方式不一樣,具體相關(guān)區(qū)別如下:
- pipeline選擇客戶端緩沖,multi選擇服務(wù)端緩沖;
- 請(qǐng)求次數(shù)的不一致,multi需要每個(gè)命令都發(fā)送一次給服務(wù)端,pipeline最后一次性發(fā)送給服務(wù)端,請(qǐng)求次數(shù)相對(duì)于multi減少
- multi/exec可以保證原子性,而pipeline不保證原子性
到此這篇關(guān)于深入理解redis中multi與pipeline 的文章就介紹到這了,更多相關(guān)redis multi與pipeline 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Redis發(fā)布訂閱和實(shí)現(xiàn).NET客戶端詳解
發(fā)布訂閱在應(yīng)用級(jí)其作用是為了減少依賴關(guān)系,通常也叫觀察者模式。主要是把耦合點(diǎn)單獨(dú)抽離出來作為第三方,隔離易變化的發(fā)送方和接收方。下面這篇文章主要給大家介紹了關(guān)于Redis發(fā)布訂閱和實(shí)現(xiàn).NET客戶端的相關(guān)資料,需要的朋友可以參考下2017-03-03Redis節(jié)省內(nèi)存的十個(gè)技巧分享
你是否在工作中遇到過Redis的bigkey導(dǎo)致的內(nèi)存占用嚴(yán)重、查詢耗時(shí)大大增加?同時(shí)bigKey還可能導(dǎo)致Redis實(shí)例的崩潰,因?yàn)閮?nèi)存不夠用了,所以本文給大家介紹了Redis極大節(jié)省內(nèi)存的10個(gè)技巧,需要的朋友可以參考下2024-04-04Redis實(shí)現(xiàn)主從復(fù)制方式(Master&Slave)
這篇文章主要介紹了Redis實(shí)現(xiàn)主從復(fù)制方式(Master&Slave),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06Redis在項(xiàng)目中常見的12種使用場(chǎng)景示例和說明
Redis是一個(gè)開源的高性能鍵值對(duì)數(shù)據(jù)庫,它以其內(nèi)存中數(shù)據(jù)存儲(chǔ)、鍵過期策略、持久化、事務(wù)、豐富的數(shù)據(jù)類型支持以及原子操作等特性,在許多項(xiàng)目中扮演著關(guān)鍵角色,以下是整理的12個(gè)Redis在項(xiàng)目中常見的使用場(chǎng)景舉例說明和解釋2024-06-06Redis概述及l(fā)inux安裝redis的詳細(xì)教程
這篇文章主要介紹了Redis概述及l(fā)inux安裝redis的詳細(xì)教程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10