博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《Redis官方文档》 Pipelining – 请求应答模式和往返延时
阅读量:6003 次
发布时间:2019-06-20

本文共 2062 字,大约阅读时间需要 6 分钟。

 Redis是一个CS结构的TCP服务器,使用”请求-应答”的模式。,客户端发起一个请求是这样的步骤:

  • 客户端发送一个请求给服务器,然后等待服务器的响应,一般客户端使用阻塞模式来等待服务器响应。
  • 服务器收到请求并处理完毕后,发送结果给客户端。

  举个例子,发送下面4个命令大概就是这样的顺序:

  • 客户端发送: INCR X
  • 服务器响应: 1
  • 客户端发送: INCR X
  • 服务器响应: 2
  • 客户端发送: INCR X
  • 服务器响应: 3
  • 客户端发送: INCR X
  • 服务器响应: 4

  客户端和服务器通过网络连接,网速可以非常快, 也可以非常慢。不管是快还是慢,消息包从客户端到服务器,再从服务器返回到客户端,总是要需要时间的。这个时间被称之为RTT(Round Trip Time,往返延时)。显然,当客户端需要发送多条请求时(比如往一个list中加很多元素,或者往一个数据库中填充很多keys),这个往返延时会影响到性能。假设网络非常慢,往返延时达到250毫秒,就算服务器每秒可以处理10万个请求,客户端也只能每秒处理4个请求。就算使用环回接口,往返延时非常小,如果需要执行很多写的操作, 也是要浪费许多时间的。

  幸好我们有办法改进这种情况。

Redis Pipelining

      “请求-响应”模式的服务器在处理完一个请求后就开始处理下一个请求,不管客户端是否读取到前一个请求的响应结果。这让客户端不需要发一个请求等一个响应的串行,可以一次发送多个请求,再最后一次性读取所有响应。这就叫piplining(管道化),这种技术几十年来广泛的使用。比如很多POP3协议支持这个特性,大大的加速了从服务器上下载新邮件的速度。

    Redis在很早的版本就支持pipeling,所以无论你用的是什么版本的redis,都可以用pipeling。下面是一个使用netcat的演示例子:

$ (printf "PING\r\nPING\r\nPING\r\n"; sleep 1) | nc localhost 6379+PONG+PONG+PONG

  我们的第一个例子,如果使用pipeline,客户端的请求和服务器的响应顺序就是如下:

  • 客户端发送: INCR X
  • 客户端发送: INCR X
  • 客户端发送: INCR X
  • 客户端发送: INCR X
  • 服务器响应: 1
  • 服务器响应: 2
  • 服务器响应: 3
  • 服务器响应: 4

  注意:当客户端使用pipelining发送很多请求时,服务器将在内存中使用队列存储这些指令的响应。所以批量发送的指令数量,最好在一个合理的范围内,比如每次发1万条指令,读取完响应后再发送另外1万条指令。2万条指令,一次性发送和分2次发送,对客户端来说速度是差不多的,但是对服务器来说,内存占用差了1万条响应的大小。

性能测试

  下面是我们用Redis Ruby客户端测试使用pipelining带来的性能改进:

require 'rubygems'require 'redis'def bench(descr)    start = Time.now    yield    puts "#{descr} #{Time.now-start} seconds"enddef without_pipelining    r = Redis.new    10000.times {        r.ping    }enddef with_pipelining    r = Redis.new    r.pipelined {        10000.times {            r.ping        }    }endbench("without pipelining") {    without_pipelining}bench("with pipelining") {    with_pipelining}

    在我的Mac OS X系统中运行上面的脚本,由于使用环回接口往返延时非常小,这样pipeling带来的优化非常小。可以得到下面的结果:

without pipelining 1.185238 secondswith pipelining 0.250783 seconds

  从结果可以看到,使用pipelining技术,我们的传输速度提高了5倍。

管道化 VS 脚本

    大部分使用pipelining的情况都可以用Redis脚本(2.6或高于2.6的版本才支持)来代替,使之更高效的在服务器端执行。使用脚本的最大好处是,在最小的延迟下可以读和写,比如可以:让“读,计算,写”这样一个流程非常快(pipeling不能处理这种情景,因为客户端需要得到响应之后才能计算和写)。有时候,应用程序可能需要在一个pipeline中发送多个EVAL或EVALSHA指令,redis的SCRITP LOAD指令能很好的满足这种需求(它保证了EVALSHA不会有调用失败的风险)。

  • 转载自 
你可能感兴趣的文章
才知道系列之GroupOn
查看>>
⑲云上场景:超级减肥王,基于OSS的高效存储实践
查看>>
linux kswapd浅析
查看>>
变更 Linux、Ubuntu 时区、时间
查看>>
高仿QQ空间 侧滑Menu效果且换肤功能《IT蓝豹》
查看>>
mac的git的21个客户端
查看>>
Django之form表单实例
查看>>
Spring Cloud自定义引导属性源
查看>>
OSChina 周日乱弹 ——程序员怎么攒钱买房子!(励志、温情)
查看>>
OSChina 周四乱弹 —— 未来人类的知识宝库
查看>>
mysql树状数据的数据库设计
查看>>
JavaScript快速入门
查看>>
Intger 自动装拆箱
查看>>
html中a连接触发表单提交
查看>>
Linux网卡名改eth0方法
查看>>
SQL or NoSQL——云计算环境中该选择谁
查看>>
托盘气泡很长时间才能消失,uTimeout没起到作用的解决办法
查看>>
利用webshell搭建socks代理
查看>>
nginx+keepalived构建主主负载均衡代理服务器
查看>>
LED灯的闪烁与熄灭也成了一个iptables target,强汗
查看>>