hiredis的pipeline实现

大多数同学一直以来对 Redis 管道有一个误解,他们以为这是 Redis 服务器提供的一种特别的技术,有了这种技术就可以加速 Redis 的存取效率。但是实际上 Redis 管道 (Pipeline) 本身并不是 Redis 服务器直接提供的技术,这个技术本质上是由客户端提供的,跟服务器没有什么直接的关系。

hiredis pipeline 实现细节以及两种封装

hiredis的pipeline实现

使用方式

发送命令

通过连续调用

redisAppendCommand(context, cmd)

将命令拼接成一个长字符串,这个字符串包含所有的命令,且符合redis协议。

字符串拼接过程,如果原字符串空间不足了,就会触发内存再分配和拷贝动作。这是由sds.c完成的。

获取结果

通过反顺序调用

redisGetReply(context, reply)

获取对应cmd的reply

redisGetReply(context, reply)内部实现如下:

1.看看是否在context包含的buf中有reply可以get,如果有读取一个。这里一定是因为buf中的数据符合redis协议,n个reply以特定格式连在一起,因此每次可以get一个。如果有reply get,则返回成功,否则进入下一步2

2.阻塞方式从fd读取replys,并存储在context包含的buf中,并取出一个reply,然后返回。

C++ redis-client 对pipeline的封装

1.没有cluster的情况

 c++ redis-client抽象出了cmd对象,每个cmd对象包含命令字符串、返回值buf等。使用pipeline时,将cmd对象依次压人pipeline。然后调用pipeline 的flush接口,将命令发送给server。flush接口内部则是依次调用redisAppendCommand(),最后反向调用redisGetReply(),将reply一次保存在cmd对象自己的buf中,再提供一个fetchreply接口,依次从cmd的buf中取结果。

 2.有cluster的情况

  一个pipeline中的cmd将根据由key所属的slot,拆分成多个pipeline,每个pipeline按照1.中的方式执行。要注意的是,由于cmd的执行顺序被打乱了,因此需要保存cmd压人pipeline的次序,以供fetchreply使用。

C redis client 对pipeline的封装

1)没有cluster的情况

  由于不打算抽象出cmd对象,可以设计一个动态数组,存储cmd顺序和返回对象的地址。结果正向压入反向取出。

2)有cluster的情况

   除了上述动态数组,还需要为每个sub pipeline准备一个数组,数组中存储cmd的全局顺序。

3)为了统一1,2, 考虑将1当作2的特例,即自有一个sub pipeline的情况,也增加一个数组

M 操作和pipeline(管道,管线)区别

Pipeline操作和原生批量操作(M 操作)的对比

我们学过 M 操作,也是类似 pipeline,将多个命令一次执行,一次发送出去,节省网络时间。对比如下:

M操作在Redis队列中是一个原子操作,pipeline不是原子操作

pipeline与M操作都会将数据顺序的传送顺序地返回(redis 单线程)

M 操作一个命令对应多个键值对,而Pipeline是多条命令

1. mget、mset等原生批量操作

mget、mset等批量操作是原子操作

你可能感兴趣的:(Redis,redis,数据库)