深入理解redis中multi与pipeline
背景
由于对redis缓存中数据有批量操作,例如预热缓存数据,或在列表页批量去获得缓存数据,在使用了multi批量提交事务后,发现redis压力高居不下,而使用了pipeline以后压力回落了平常,也由于这个案例,特在此写个分析与笔记。
multi
简介
标记一个事务块的开始。
事务块内的多条命令会依照前后顺序被放进一个队列当中,最后由 EXEC 命令原子性(atomic)地履行。
实现原理
我用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,抓包要求以下图所示:
redis客户端与服务端建立连接后,multi标记事务开始,以后每次履行,服务端返回queued队列标志。查看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服务端每次会把事务块中的命令保存到内存中,上述简介已解释过最后通过exec命令履行,再看下面示例图的返回结果可以了解到redis服务端一次性返回所有命令履行返回结果。
pipeline
简介
客户端将履行的命令写入到缓冲中,最后由exec命令一次性发送给redis履行返回。
实现原理
一样,用相关代码调用redis抓包;
$redis = new redis(); $redis->connect('127.0.0.1',6379); $handle = $redis->pipeline(); $handle->incr('a'); $handle->incr('b'); $handle->exec();
继续用wireshark抓包,以下图所示
pipeline 客户端要求包示例图
这上面的图片扼要分析一下,pipeline管道操作是需要客户端与服务真个支持,客户端将命令写入缓冲,最后再通过exec命令发送给服务端,服务端通过命令拆分,逐一履行返回结果。
二者的区分
由上面的要求也能够看出了二者最明显的区分是客户端发送要求的方式不一样,具体相关区分以下:
- pipeline选择客户端缓冲,multi选择服务端缓冲;
- 要求次数的不一致,multi需要每一个命令都发送一次给服务端,pipeline最后一次性发送给服务端,要求次数相对multi减少
- multi/exec可以保证原子性,而pipeline不保证原子性
到此这篇关于深入理解redis中multi与pipeline 的文章就介绍到这了,更多相关redis multi与pipeline 内容请搜索之前的文章或继续浏览下面的相关文章希望大家以后多多支持!
文章来源:丸子建站
文章标题:深入理解redis中multi与pipeline
https://www.wanzijz.com/view/70257.html