Redis客户端如何实现流水线处理?

10
在Redis的协议文档中指出:(链接)

一个客户端可以通过同一连接来发送多个命令。支持管道,因此客户端可以通过单个写操作发送多个命令,不需要在发出下一个命令前读取服务器的回复。所有的回复都可以在结尾处读取。

然而,我找不到任何关于这如何实现的示例。 Redis客户端是如何实现pipelining的?
3个回答

6
只是在以上回答中加入了更多见解。理解Redis管道的一种方式是认识到Redis管道完全是客户端实现的,与Redis服务器无关。虽然这在不同的客户端实现之间有所不同,但以下是概括的想法:
管道旨在解决高网络延迟环境下的响应延迟问题。因此,在发送命令和读取响应时花费的时间越少,越好。这可以通过缓冲来有效实现。客户端可以(也可能不)在TCP堆栈中缓冲命令(如其他答案中所述)然后将它们发送到服务器。一旦它们被发送到服务器,服务器执行它们并在服务器端缓冲它们。与通常情况下客户端接收到响应后立即读取响应不同,在管道的情况下,客户端从服务器端缓冲区部分地读取响应或者当应用程序执行“sync”(关闭管道)时读取响应。这是有利的,因为客户端在读取响应时花费的时间要少得多。
以下是我的博客文章,您可以参考以获得更好的理解:http://nachivpn.blogspot.in/2014/11/redis-pipeline-explained.html

5
以下是关于如何实现此功能的简单示例,可以在Ruby redis客户端redis-rb和Python的redis-py源代码中找到。
它们基本上执行了TaylorOtwell上面提到的操作,将将要发送到redis的请求在客户端连接中串联成一个网络请求,而事务则使用redis命令MULTI/EXEC来开始和结束一个事务。
以下是redis-rb的示例代码(来自redis.rbpipeline.rb):
def pipelined(options = {})
  synchronize do
    begin
      original, @client = @client, Pipeline.new
      yield
      if @client.commands.empty?
        []
      else
        original.call_pipelined(@client.commands, options)
      end
    ensure
      @client = original
    end
  end
end

def call_pipelined(commands, options = {})
  @commands.concat commands
  nil
end

另一个很好的例子可以在redis-py源代码中找到,这是一个Python Redis客户端。希望这能帮到您。


4
只要您能轻松地在TCP流上划分消息,服务器实际上不需要太多支持来支持流水线操作,TCP堆栈将为您缓冲数据,作为服务器,您只需逐个读取/解析请求,并在完成请求后发送回复。客户端/服务器只需要注意并处理这些缓冲区填满时的情况,以避免死锁。

话虽如此,对于Redis,请查看networking.c中的processInputBuffer()/processMultibulkBuffer(),Redis还具有自己的输出缓冲,例如addReply()。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接