您当前的位置: 首页 > 慢生活 > 程序人生 网站首页程序人生
redis管道(php实现)
发布时间:2021-11-21 21:20:10编辑:雪饮阅读()
首先redis管道,在cli上没有明说,命令行上面你网上找到的大多都是不能运行的,像是下面这样:
$(echo -en "PING\r\n SET runoobkey redis\r\nGET runoobkey\r\nINCR visitor\r\nINCR visitor\r\nINCR visitor\r\n"; sleep 10) | nc localhost 6379
实际上哥这边尝试了:
[root@localhost ~]# /usr/local/redis-6.2.5/src/redis-server $(echo -en "PING\r\n SET runoobkey redis\r\nGET runoobkey\r\nINCR visitor\r\nINCR visitor\r\nINCR visitor\r\n"; sleep 10) | netcat localhost 6379
[root@localhost ~]# netstat -anpt
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1046/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1293/master
tcp 0 0 192.168.43.170:22 192.168.43.71:52513 ESTABLISHED 36497/sshd: root@no
tcp 0 0 192.168.43.170:22 192.168.43.71:52512 ESTABLISHED 36492/sshd: root@pt
tcp 0 64 192.168.43.170:22 192.168.43.71:64373 ESTABLISHED 31809/sshd: root@pt
tcp 0 0 192.168.43.170:22 192.168.43.71:64375 ESTABLISHED 31811/sshd: root@no
tcp6 0 0 :::22 :::* LISTEN 1046/sshd
tcp6 0 0 ::1:25 :::* LISTEN 1293/master
看起来也没有什么,而且redis还没有启动起来
那么就算是我在cli时候加入:
[root@localhost ~]# /usr/local/redis-6.2.5/src/redis-cli $(echo -en "PING\r\n SET runoobkey redis\r\nGET runoobkey\r\nINCR visitor\r\nINCR visitor\r\nINCR visitor\r\n"; sleep 10) | netcat localhost 6379
-ERR unknown command `ERR`, with args beginning with: `unknown`, `command`, ``PING`, ``,`, `with`, `args`, `beginning`, `with:`, ``SET`,`, ``runoobkey`,`, ``redis`, ``,`, ``GET`,`, ```,
还是一样的,没有什么用。
那么今天这里主要是从PHP的角度来解释实现:
Redis是一种基于客户端-服务端模型以及请求/响应协议的TCP服务。这意味着通常情况下一个请求会遵循以下步骤:
客户端向服务端发送一个查询请求,并监听Socket返回,通常是以阻塞模式,等待服务端响应。
服务端处理命令,并将结果返回给客户端。
Redis 管道技术可以在服务端未响应时,客户端可以继续向服务端发送请求,并最终一次性读取所有服务端的响应。
管道技术最显著的优势是提高了 redis 服务的性能。个人认为最明显的就是可以减少tcp连接,直接在一个tcp连接中做好多事情。
就算是已经在redis服务器内部了,那么pipe性能也是最棒的,对于一次处理多个命令时候。
这里为了公平起见,下面案例都是连接同一个redis服务。
首先我们用传统的方式。
在此之前先说下我这里的环境:
windows10、phpstudy自带redis3.0.504,php7.1.9nts(用phpstudy给其开启了redis缓存组件扩展,4.3.0扩展)。
那么接下来就是正常情况下php向redis操作1000个key(一次性发过去,不进行多次连接,因为减少tcp多次连接一次性将要操作的命令给服务端,这个用脚趾头想都能想到是会节省性能开销的。):
common.php:
<?php
$redis=new Redis();
try{
$redis->connect("192.168.43.170",6379);
//开始的时间
$t1=microtime(true);
for($i=0;$i<1000;$i++){
$redis->set("key".$i,"val".$i);
}
$t2=microtime(true);
$runTime=$t2-$t1;
echo $runTime;
$redis->flushDB();
$redis->close();
}
catch(\Exception $e){
var_dump($e->getMessage());
}
然后再做一个通过multi这个redis事务形式来操作1000个命令,multi本身就能一次性执行多个命令。
multi.php:
<?php
$redis=new Redis();
try{
$redis->connect("192.168.43.170",6379);
$pipe=$redis->multi();
//开始的时间
$t1=microtime(true);
for($i=0;$i<1000;$i++){
$pipe->set("key".$i,"val".$i);
}
$pipe->exec();
$t2=microtime(true);
$runTime=$t2-$t1;
echo $runTime;
$redis->flushDB();
$redis->close();
}
catch(\Exception $e){
var_dump($e->getMessage());
}
最后就是通过pipeline即管道的形式来批量操作命令了,pipeline其实就是在multi上的一种模式:
pipe.php:
<?php
$redis=new Redis();
try{
$redis->connect("192.168.43.170",6379);
$pipe=$redis->multi(REDIS::PIPELINE);
//开始的时间
$t1=microtime(true);
for($i=0;$i<1000;$i++){
$pipe->set("key".$i,"val".$i);
}
$pipe->exec();
$t2=microtime(true);
$runTime=$t2-$t1;
echo $runTime;
$redis->flushDB();
$redis->close();
}
catch(\Exception $e){
var_dump($e->getMessage());
}
那么最后就是他们3种不同的操作redis多个命令的方式的性能比较了:
C:\Users\Administrator>D:\phpstudy_pro\Extensions\php\php7.1.9nts\php.exe D:\phpstudy_pro\WWW\xuexibiji\common.php
0.38158202171326
C:\Users\Administrator>D:\phpstudy_pro\Extensions\php\php7.1.9nts\php.exe D:\phpstudy_pro\WWW\xuexibiji\pipe.php
0.00211501121521
C:\Users\Administrator>D:\phpstudy_pro\Extensions\php\php7.1.9nts\php.exe D:\phpstudy_pro\WWW\xuexibiji\multi.php
0.32743096351624
很明显可以看到普通方式操作的性能最慢,multi操作的性能快于普通操作的方式,而pipeline操作方式又比multi操作方式更快。
关键字词:redis,管道,pipe,pipeline,php,实现