当前位置: 首页 > redis, 分布式系统, 缓存系统 > 正文

Redis官方主题 – Pipelining管道技术

1 星2 星3 星4 星5 星 (1 次投票, 评分: 5.00, 总分: 5)
Loading ... Loading ...
baidu_share

请求/响应协议和往返时延

Redis是一种基于客户端-服务端模型以及请求/响应协议的TCP服务。这意味着通常情况下一个请求会遵循以下步骤:

客户端向服务端发送一个查询请求,并监听Socket返回,通常是以阻塞模式,等待服务端响应。
服务端处理命令,并将结果返回给客户端。
这里有个执行四条命令序列的例子:

1
2
3
4
5
6
7
8
Client: INCR X
Server: 1
Client: INCR X
Server: 2
Client: INCR X
Server: 3
Client: INCR X
Server: 4

客户端和服务端通过网络进行连接。这样的连接可能非常快(在一个回路网络中),也可能非常慢(在广域网上经过多个结点才能互通的两个主机)。但是无论是否存在网络延迟,数据包从客户端传输到服务端,以及客户端从服务端获得相应都需要花费一些时间。

这段时间就成为往返时延(Round Trip Time)。因此当客户端需要执行一串请求的时候,很容易看出它对性能的影响(例如往同一个队列中加入大量元素,或者往数据库中插入大量的键)。如果RTT时长为250毫秒(在基于广域网的低速连接环境下),即使服务器每秒可以处理10万个请求,但是实际上我们依然只能每秒处理最多4个请求。

如果处于一个回路网络中,RTT时长则相当短(我的主机ping 127.0.0.1时只需要0.044ms),但是如果你执行一大串写入请求的时候,还是会有点长。

幸运的是,已经有种方法可以改善这个状况。

Redis管道技术

一个请求/相应服务可以实现为,即使客户端没有读取到旧请求的响应,服务端依旧可以处理新请求。通过这种方式,可以完全无需等待服务端应答地发送多条指令给服务端,并最终一次性读取所有应答。

这种技术就被称之为管道技术,是一种几十年来被广泛使用的技术。许多POP3协议实现都已经支持这种特性,提升从服务器发送和接收邮件的速度。

Redis其实很早就已经支持管道技术了,因此无论你使用任何版本的Redis,都可以用上这种技术。这是一个使用原始netcat工具的例子:

1
2
3
4
$ (echo -en “PINGrnPINGrnPINGrn”; sleep 1) | nc localhost 6379
+PONG
+PONG
+PONG

这次我们无需每次请求都为RTT买单了,三条命令只需要花费一次开销。

很清晰地看到,通过使用管道,在最初的例子中,操作会变成下面这样:

1
2
3
4
5
6
7
8
Client: INCR X
Client: INCR X
Client: INCR X
Client: INCR X
Server: 1
Server: 2
Server: 3
Server: 4

要点:当客户端通过管道技术发送命令的时候,服务端将被强制在内存中使用队列应答。因此如果你需要使用管道技术处理非常多的命令时,最好以一个合理的数量发送,例如1万条命令,接收应答后,再发送后续的1万条命令。其实处理速度上几乎相同,但是在队列中应答这1万条命令时所产生的额外内存开销将会达到最大。

一些测试数据

在下面的测试中,我们将使用Redis的Ruby客户端,支持管道技术特性,测试管道技术对速度的提升效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
require ‘rubygems’
require ‘redis’
 
def bench(descr)
start = Time.now
yield
puts “#{descr} #{Time.now-start} seconds”
end
 
def without_pipelining
r = Redis.new
10000.times {
r.ping
}
end
 
def with_pipelining
r = Redis.new
r.pipelined {
10000.times {
r.ping
}
}
end
 
bench(“without pipelining”) {
without_pipelining
}
bench(“with pipelining”) {
with_pipelining
}

从处于局域网中的Mac OS X系统上执行上面这个简单脚本的数据表明,开启了管道操作后,往返时延已经被改善得相当低了。

without pipelining 1.185238 seconds
with pipelining 0.250783 seconds
如你所见,开启管道后,我们的速度效率提升了5倍。

管道技术 VS 多条命令

我们经常在请求过程中,通过不断的加入一条新命令来完成多个操作。你无法一次性往一个集合中添加多个元素。这时候你需要执行多次SADD命令。

通过使用管道,你可以执行一个假想的MSADD命令,与此同时,我们可以避免Redis的命令集合中充斥太多命令。另外一点,无需使用管道技术的SADD命令将会在一个分布式环境(例如仍在开发过程中的Redis集群)的版本中实现。

本文固定链接: http://www.chepoo.com/redis-pipelining-guide.html | IT技术精华网

Redis官方主题 – Pipelining管道技术:等您坐沙发呢!

发表评论