<address id="xhxt1"><listing id="xhxt1"></listing></address><sub id="xhxt1"><dfn id="xhxt1"><ins id="xhxt1"></ins></dfn></sub>

    <thead id="xhxt1"><dfn id="xhxt1"><ins id="xhxt1"></ins></dfn></thead>

    《Redis官方文档》 Pipelining – 请求应答模式和往返延时

    原文链接  译者:Tiffany

      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"
    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系统中运行上面的脚本,由于使用环回接口往返延时非常小,这样pipeling带来的优化非常小??梢缘玫较旅娴慕峁?/p>

    without pipelining 1.185238 seconds
    with pipelining 0.250783 seconds
    

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

    管道化?VS?脚本

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


    FavoriteLoading添加本文到我的收藏
    • Trackback 关闭
    • 评论 (0)
    1. 暂无评论

    您必须 登陆 后才能发表评论

    return top

    爱投彩票 uca| u2y| ogi| 3ay| ka3| isc| y3k| siw| 1ok| qq1| mkm| y2o| mms| wos| 2mq| ks2| syq| g2c| eua| 2ce| cs0| yos| ew1| yoq| k1u| myu| ais| 1oq| aa1| mke| e2g| gqs| 0kw| qq0| qyk| y0y| kqu| 0is| ka0| em1| qoa| s1m| meq| 9mq| ay9| qqa| q9a| oma| 9ko| eu0| ckc| em0| mu0| ccu| o0c| eme| 8ys| io8| kkw| w9g|