hiredis的pipeline實現
使用方式
發送命令
通過連續調用
redisAppendCommand(context, cmd)
將命令拼接成一個長字符串,這個字符串包含所有的命令,且符合redis協議。
字符串拼接過程,如果原字符串空間不足了,就會觸發內存再分配和拷貝動作。這是由sds.c完成的。
獲取結果
通過反順序調用
redisGetReply(context, reply)
獲取對應cmd的reply
redisGetReply(context, reply)內部實現如下:
- 看看是否在context包含的buf中有reply可以get,如果有讀取一個。這里一定是因為buf中的數據符合redis協議,n個reply以特定格式連在一起,因此每次可以get一個。如果有reply get,則返回成功,否則進入下一步2
- 以阻塞方式從fd讀取replys,並存儲在context包含的buf中,並取出一個reply,然后返回。
c++ redis-client 對pipeline的封裝
- 沒有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使用。
ccredis client 對pipeline的封裝
- 沒有cluster的情況
2. 有cluster的情況
除了上述動態數組,還需要為每個sub pipeline准備一個數組,數組中存儲cmd的全局順序。
3.為了統一1,2, 考慮將1當作2的特例,即自有一個sub pipeline的情況,也增加一個數組。