Redis是一种基于客户端-服务端模型以及请求/响应协议的TCP服务。
这意味着通常情况下一个请求会遵循以下步骤:
客户端向服务端发送一个查询请求,并监听Socket返回,通常是以阻塞模式,等待服务端响应。
服务端处理命令,并将结果返回给客户端。
因此,例如下面是4个命令序列执行情况:
Client: INCR X
Server: 1
Client: INCR X
Server: 2
Client: INCR X
Server: 3
Client: INCR X
Server: 4
客户端和服务器通过网络进行连接。这个连接可以很快(loopback接口)或很慢(建立了一个多次跳转的网络连接)。无论网络延如何延时,数据包总是能从客户端到达服务器,并从服务器返回数据回复客户端。
这个时间被称之为 RTT (Round Trip Time - 往返时间). 当客户端需要在一个批处理中执行多次请求时很容易看到这是如何影响性能的(例如添加许多元素到同一个list,或者用很多Keys填充数据库)。例如,如果RTT时间是250毫秒(在一个很慢的连接下),即使服务器每秒能处理100k的请求数,我们每秒最多也只能处理4个请求。
如果采用loopback接口,RTT就短得多(比如我的主机ping 127.0.0.1只需要44毫秒),但它任然是一笔很多的开销在一次批量写入操作中。
幸运的是有一种方法可以改善这种情况。
Redis 管道(Pipelining)
一次请求/响应服务器能实现处理新的请求即使旧的请求还未被响应。这样就可以将多个命令发送到服务器,而不用等待回复,最后在一个步骤中读取该答复。
这就是管道(pipelining),是一种几十年来广泛使用的技术。例如许多POP3协议已经实现支持这个功能,大大加快了从服务器下载新邮件的过程。
Redis很早就支持管道(pipelining)技术,因此无论你运行的是什么版本,你都可以使用管道(pipelining)操作Redis。下面是一个使用的例子:
$ (printf "PING\r\nPING\r\nPING\r\n"; sleep 1) | nc localhost 6379
+PONG
+PONG
+PONG
这一次我们没有为每个命令都花费了RTT开销,而是只用了一个命令的开销时间。
非常明确的,用管道顺序操作的第一个例子如下:
Client: INCR X
Client: INCR X
Client: INCR X
Client: INCR X
Server: 1
Server: 2
Server: 3
Server: 4
重要说明: 使用管道发送命令时,服务器将被迫回复一个队列答复,占用很多内存。所以,如果你需要发送大量的命令,最好是把他们按照合理数量分批次的处理,例如10K的命令,读回复,然后再发送另一个10k的命令,等等。这样速度几乎是相同的,但是在回复这10k命令队列需要非常大量的内存用来组织返回数据内容。
案例演示
1、linux安装netcat(nc)
netcat(nc)不仅可以通过使用TCP或UDP协议的网络连接读写数据,同时还是一个功能强大的网络调试和探测工具,能够建立你需要的几乎所有类型的网络连接
# 在Linux终端窗口可以直接使用yum工具进行安装
127.0.0.1:6379> yum install nc
# 安装完毕后,在终端模式下运行nc -help查看命令是否正常安装
127.0.0.1:6379> yum install nc
2、测试
安装nc正常,下面我们就可以使用 nc localhost 6379 来监听端口,并发送数据
# 启动redis 服务端
[root@iZ2ze5v2vdwv6veyksylhxZ /]# cd /usr/local/bin
[root@iZ2ze5v2vdwv6veyksylhxZ bin]# ls
6379,log dump6381.rdb pcre-config
6380.log dump.rdb pcregrep
6381.log easy_install pcretest
appendonly.aof easy_install-3.6 redis-benchmark
chardetect easy_install-3.8 redis-check-aof
cloud-id jsondiff redis-check-rdb
cloud-init jsonpatch redis-cli
cloud-init-per jsonpointer redis-sentinel
dump6379.rdb jsonschema redis-server
dump6380.rdb muzhen_config
[root@iZ2ze5v2vdwv6veyksylhxZ bin]# redis-server muzhen_config/redis.conf
[root@iZ2ze5v2vdwv6veyksylhxZ bin]# redis-cli -p 6379
127.0.0.1:6379> ping
PONG
[root@iZ2ze5v2vdwv6veyksylhxZ /]# cd /usr/local/bin
[root@iZ2ze5v2vdwv6veyksylhxZ bin]# redis-server muzhen_config/redis.conf
[root@iZ2ze5v2vdwv6veyksylhxZ bin]# redis-cli -p 6379
127.0.0.1:6379> ping
PONG
127.0.0.1:6379>
# nc连接通信
[root@iZ2ze5v2vdwv6veyksylhxZ bin]# nc localhost 6379
keys *
*2
$2
k1
$2
k2
get k2
$5
hello
再开一台主机,进行测试
[root@iZ2ze5v2vdwv6veyksylhxZ bin]# redis-cli -p 6379
127.0.0.1:6379> keys *
1) "k1"
2) "k2"
127.0.0.1:6379> get k2
"hello"
127.0.0.1:6379>
3、管道案例
管道作用:降低了通信的成本
举例:a和b两个人聊天,以前是a 说一句,b回一句,现在是a直接说很多,b统一恢复,提高了效率
[root@iZ2ze5v2vdwv6veyksylhxZ bin]# echo -e "set k2 99\n incr k2\n get k2" | nc localhost 6379
+OK
:100
$3
100
[root@iZ2ze5v2vdwv6veyksylhxZ bin]#