Redis是一个cs模式的tcp server,使用和http类似的请求响应协议。

一个client可以通过一个socket连接发起多个请求命令。

每个请求命令发出后client通常会阻塞并等待redis服务处理,redis处理完后请求命令后会将结果通过响应报文返回给client。

基本的通信过程如下:

./bin/redis-cli -h 192.168.36.189 -p 6379
192.168.36.189:6379> incr x
(integer) 1
192.168.36.189:6379> incr x
(integer) 2
192.168.36.189:6379> incr x
(integer) 3

客户端和服务端通过网络进行连接。这样的连接可能非常快(在一个回路网络中),也可能非常慢(在广域网上经过多个结点才能互通的两个主机)。但是无论是否存在网络延迟,数据包从客户端传输到服务端,以及客户端从服务端获得相应都需要花费一些时间。这段时间就成为往返时延(Round Trip Time)。因此当客户端需要执行一串请求的时候,很容易看出它对性能的影响(例如往同一个队列中加入大量元素,或者往数据库中插入大量的键)。如果RTT时长为250毫秒(在基于广域网的低速连接环境下),即使服务器每秒可以处理10万个请求,但是实际上我们依然只能每秒处理最多4个请求。
如果处于一个回路网络中,RTT时长则相当短(我的主机ping 127.0.0.1时只需要0.044ms),但是如果你执行一大串写入请求的时候,还是会有点长。
幸运的是,redis给我们提供了管道技术。

1.Redis管道技术
一个请求/相应服务可以实现为,即使客户端没有读取到旧请求的响应,服务端依旧可以处理新请求。通过这种方式,可以完全无需等待服务端应答地发送多条指令给服务端,并最终一次性读取所有应答。管道技术最显著的优势是提高了redis服务的性能。
通过pipeline方式当有大批量的操作时候。我们可以节省很多原来浪费在网络延迟的时间。需要注意到是用pipeline方式打包命令发送,redis必须在处理完所有命令前先缓存起所有命令的处理结果。打包的命令越多,缓存消耗内存也越多。所以并是不是打包的命令越多越好。具体多少合适需要根据具体情况测试。

$(echo -en "PING\r\n SET key redis\r\nGET key\r\nINCR x\r\nINCR x\r\nINCR x\r\n"; sleep 10) | nc 192.168.36.189 6379
+PONG
+OK
$5
redis
:4
:5
:6

以上实例中我们通过使用 PING 命令查看redis服务是否可用, 之后我们们设置了key的值为 redis,然后我们获取key 的值并使得x自增 3 次。
在返回的结果中我们可以看到这些命令一次性向redis服务提交,并最终一次性读取所有服务端的响应。

2.java测试代码

    package cn.slimsmart.redis.demo.pipeline;  

    import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline; @SuppressWarnings("resource")
public class PipelineTest { public static void main(String[] args) {
long start = System.currentTimeMillis();
usePipeline();
long end = System.currentTimeMillis();
System.out.println("usePipeline:"+(end - start)); start = System.currentTimeMillis();
withoutPipeline();
end = System.currentTimeMillis();
System.out.println("withoutPipeline:"+(end - start));
} private static void withoutPipeline() {
try {
Jedis jedis = new Jedis("192.168.36.189", 6379);
for (int i = 0; i < 1000; i++) {
jedis.incr("test2");
}
jedis.disconnect();
} catch (Exception e) {
}
} private static void usePipeline() {
try {
Jedis jedis = new Jedis("192.168.36.189", 6379);
Pipeline pipeline = jedis.pipelined();
for (int i = 0; i < 1000; i++) {
pipeline.incr("test2");
}
pipeline.sync();
jedis.disconnect();
} catch (Exception e) {
}
}
}

运行结果:

127.0.0.1 循环10000次 效果

usePipeline:151
withoutPipeline:6229

外网IP循环10000次 效果

usePipeline:201
withoutPipeline:94909

结果还是很明显有较大的差距,所以多次操作用pipeline还是有明显的优势。

Redis 管道pipeline的更多相关文章

  1. redis管道pipeline

    Jedis jedis = new Jedis("127.0.0.1",6379); Pipeline pipeline = jedis.pipelined(); for(int ...

  2. redis管道技术

    1.redis管道pipeline解决的问题: 由于redis通信是通过tcp协议基础,并且是堵塞的处理方式,在第一个请求没有执行并返回前,无法处理第二个请求.所以事件浪费在了网络传输和堵塞请求中. ...

  3. redis使用管道pipeline提升批量操作性能(php演示)

    Redis是一个TCP服务器,支持请求/响应协议. 在Redis中,请求通过以下步骤完成: 客户端向服务器发送查询,并从套接字读取,通常以阻塞的方式,用于服务器响应. 服务器处理命令并将响应发送回客户 ...

  4. 分布式缓存Redis之Pipeline(管道)

    Redis的pipeline(管道)功能在命令行中没有,但redis是支持pipeline的,而且在各个语言版的client中都有相应的实现. 由于网络开销延迟,就算redis server端有很强的 ...

  5. 【redis】pipeline - 管道模型

    redis-pipeline 2020-02-10: 因为我把github相关的wiki删了,所以导致破图...待解决.(讲真github-wiki跟project是2个url,真的不好用) 因为用的 ...

  6. Redis管道功能

    Redis管道,Redis存储用户浏览数据 当频繁的存储获取Redis数据库中的数据时,可以使用Redis的pipeline(管道)功能,将多个相互没有依赖关系的读写操作,如:下一步执行的Redis操 ...

  7. Redis管道理解

    Redis管道理解 简介 管道并不是Redis本身提供的功能,通常是客户端提供的功能: 管道就是打包多条无关命令批量执行,以减少多个命令分别执行消耗的网络交互时间(TCP网络交互),可以显著提升Red ...

  8. redis学习(六)redis管道

    redis管道 1.redis管道介绍 redis采用的是CS架构,客户端与服务器端通过tcp协议进行连接通信,因此无论是发出请求还是接收响应,都必须经过网络传输.在tcp连接过程中,客户端和服务器端 ...

  9. 缓存数据库-redis(管道)

    一:Redis 管道技术 Redis是一种基于客户端-服务端模型以及请求/响应协议的TCP服务.这意味着通常情况下一个请求会遵循以下步骤: 客户端向服务端发送一个查询请求,并监听Socket返回,通常 ...

随机推荐

  1. sshpass密码

    使用sshpass sshpass -p "password" scp -r user@example.com:/some/remote/path /some/local/path ...

  2. JavaEE_Test2_Servlet

    package servlet; import javax.servlet.http.HttpSession; import java.io.IOException; import java.io.P ...

  3. Linux后台运行python程序并输出到日志文件

    后台运行python程序并标准输出到文件 现在有test.py程序要后台部署, 里面有输出内容 使用命令: nohup python -u test.py > test.log 2>&am ...

  4. Spring @Import注解 —— 导入资源

    在应用中,有时没有把某个类注入到IOC容器中,但在运用的时候需要获取该类对应的bean,此时就需要用到@Import注解.示例如下: 先创建两个类,不用注解注入到IOC容器中,在应用的时候在导入到当前 ...

  5. Python全栈开发之3、深浅拷贝、变量和函数、递归、函数式编程、内置函数

    一.深浅拷贝 1.数字和字符串 对于 数字 和 字符串 而言,赋值.浅拷贝和深拷贝无意义,因为其永远指向同一个内存地址. import copy # 定义变量 数字.字符串 # n1 = 123 n1 ...

  6. 利用微信web开发者工具调试企业微信页面

    1.只有企业号的管理员才能调试. 2.勾选企业号的开发者工具(具体位置见下图,这个入口位置总是在变,一般来说,找到”微工作台“就能找到了) 3.下载web开发者工具 https://developer ...

  7. jpa报错 Unable to acquire a connection from driver [null], user [null] and URL [null]

    jpa报错 Unable to acquire a connection from driver [null], user [null] and URL [null] 为啥报错 因为你在persist ...

  8. HDU2087 剪花布条(字符串...半暴力写的?

    一块花布条,里面有些图案,另有一块直接可用的小饰条,里面也有一些图案.对于给定的花布条和小饰条,计算一下能从花布条中尽可能剪出几块小饰条来呢? Input输入中含有一些数据,分别是成对出现的花布条和小 ...

  9. html重置模板

    新浪的初始化: html,body,ul,li,ol,dl,dd,dt,p,h1,h2,h3,h4,h5,h6,form,fieldset,legend,img { margin: 0; paddin ...

  10. 第一个SpringMVC应用流程总结