因爲對redis緩存中數據有批量操做,例如預熱緩存數據,或者在列表頁批量去獲取緩存數據,在使用了multi批量提交事務後,發現redis壓力高居不下,而使用了pipeline以後壓力回落了日常,也由於這個案例,特在此寫個分析與筆記。php
標記一個事務塊的開始。 事務塊內的多條命令會按照前後順序被放進一個隊列當中,最後由 EXEC 命令原子性(atomic)地執行。redis
我用php擴展調起redis服務,執行,代碼以下:緩存
$redis = new redis();
$redis->connect('127.0.0.1',6379);
$handle = $redis->multi();
$handle->incr('a');
$handle->incr('b');
$handle->exec();
複製代碼
爲了查看這期間具體的鏈接過程,用wireshark監聽迴環地址端口6379,抓包請求以下圖所示:bash
redis客戶端與服務端創建鏈接後,multi標記事務開始,以後每次執行,服務端返回queued隊列標誌。查看redis源碼src/multi.c文件:ui
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服務端每次會把事務塊中的命令保存到內存中,上述簡介已經解釋過最後經過exec命令執行,再看下面示例圖的返回結果能夠了解到redis服務端一次性返回全部命令執行返回結果。atom
客戶端將執行的命令寫入到緩衝中,最後由exec命令一次性發送給redis執行返回。spa
一樣,用相關代碼調用redis抓包;3d
$redis = new redis();
$redis->connect('127.0.0.1',6379);
$handle = $redis->pipeline();
$handle->incr('a');
$handle->incr('b');
$handle->exec();
複製代碼
繼續用wireshark抓包,以下圖所示code
這上面的圖片簡要分析一下,pipeline管道操做是須要客戶端與服務端的支持,客戶端將命令寫入緩衝,最後再經過exec命令發送給服務端,服務端經過命令拆分,逐個執行返回結果。cdn
由上面的請求也能夠看出了二者最明顯的區別是客戶端發送請求的方式不同,具體相關區別以下:
我的博客地址:blog.walkerx.cn