eglid 发表于 2013-10-18 09:19:01

Redis学习手册(管线)

一、请求应答协议和RTT:

    Redis是一种典型的基于C/S模型的TCP服务器。在客户端与服务器的通讯过程中,通常都是客户端率先发起请求,服务器在接收到请求后执行相应的任务,最后再将获取的数据或处理结果以应答的方式发送给客户端。在此过程中,客户端都会以阻塞的方式等待服务器返回的结果。见如下命令序列:
    Client: INCR X
    Server: 1
    Client: INCR X
    Server: 2
    Client: INCR X
    Server: 3
    Client: INCR X
    Server: 4
    在每一对请求与应答的过程中,我们都不得不承受网络传输所带来的额外开销。我们通常将这种开销称为RTT(Round Trip Time)。现在我们假设每一次请求与应答的RTT为250毫秒,而我们的服务器可以在一秒内处理100k的数据,可结果则是我们的服务器每秒至多处理4条请求。要想解决这一性能问题,我们该如何进行优化呢?
   
二、管线(pipelining):

    Redis在很早的版本中就已经提供了对命令管线的支持。在给出具体解释之前,我们先将上面的同步应答方式的例子改造为基于命令管线的异步应答方式,这样可以让大家有一个更好的感性认识。
    Client: INCR X
    Client: INCR X
    Client: INCR X
    Client: INCR X
    Server: 1
    Server: 2
    Server: 3
    Server: 4
    从以上示例可以看出,客户端在发送命令之后,不用立刻等待来自服务器的应答,而是可以继续发送后面的命令。在命令发送完毕后,再一次性的读取之前所有命令的应答。这样便节省了同步方式中RTT的开销。
    最后需要说明的是,如果Redis服务器发现客户端的请求是基于管线的,那么服务器端在接受到请求并处理之后,会将每条命令的应答数据存入队列,之后再发送到客户端。
   
三、Benchmark:

    以下是来自Redis官网的测试用例和测试结果。需要说明的是,该测试是基于loopback(127.0.0.1)的,因此RTT所占用的时间相对较少,如果是基于实际网络接口,那么管线机制所带来的性能提升就更为显著了。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
    }
    //without pipelining 1.185238 seconds
    //with pipelining 0.250783 seconds




xuol001 发表于 2013-12-1 22:22:34

承诺总是太假,我改如何面对现实。

小雨点点789 发表于 2013-12-6 05:44:19

用文字来续写自己的悲伤华丽丽却那么的让人心疼

liyao20060101 发表于 2013-12-10 01:07:55

向日葵,赖着太阳而生存。

网中网 发表于 2013-12-14 05:34:18

我们曾相爱、想到就心酸

在水一万 发表于 2013-12-17 03:00:54

■■ヽ︶ㄣ还记得你说过你会娶莪吗?

bzxxaq 发表于 2013-12-19 20:03:33

害怕再一次的奋不顾身,背后无可预知的万一。
页: [1]
查看完整版本: Redis学习手册(管线)