提示文章写完后,目录可以自动生成如何生成参考右边的帮助文档


Pipeline

前面我们已经说过,Redis客户端执行一条命令分为如下4个部分:1)发送命令2)命令排队3)命令执行4)返回结果

image.png

其中1和4花费的时间称为Round Trip Time (RTT,往返时间),也就是数据网络上传输的时间

Redis提供了批量操作命令(例如mgetmset等),有效地节约RTT。

但大部分命令是不支持批量操作的,例如执行n次 hgetall命令,并没有mhgetall命令存在需要消耗n次RTT。

举例

举例:Redis客户端和服务端可能部署不同机器上。例如客户端在本地,Redis服务器阿里云的广州,两地直线距离约为800公里,那么1次RTT时间=800 x2/ ( 300000×2/3 ) =8毫秒,(光在真空中传输速度每秒30万公里,这里假设光纤为光速的2/3 )。而Redis命令真正执行的时间通常在微秒(1000微妙=1毫秒)级别,所以才会有Redis 性能瓶颈是网络这样的说法

Pipeline流水线)机制能改善上面这类问题,它能将一组 Redis命令进行组装,通过一次RTT传输给Redis,再将这组Redis命令的执行结果顺序返回客户端,没有使用Pipeline执行了n条命令,整个过程需要n次RTT。

image.png

使用Pipeline 执行了n次命令,整个过程需要1次RTT。

image.png

Pipeline并不是什么新的技术机制,很多技术上都使用过。而且RTT在不同网络环境下会不同例如同机房和同机器比较快,跨机房跨地区会比较慢。

rediscli的–pipe选项实际上就是使用Pipeline机制,但绝对部分情况下,我们使用Java语言的Redis客户端中的Pipeline会更多一点。

比较普通模式与 PipeLine 模式

测试环境
  Windows:Eclipse + jedis2.9.0 + jdk 1.7
  Ubuntu:部署虚拟机上的服务器 Redis 3.0.7

	/*
	 * 测试普通模式与 PipeLine 模式效率: 
	 * 测试方法:向 redis插入 10000 组数据
	 */
	public static void testPipeLineAndNormal(Jedis jedis)
			throws InterruptedException {
		Logger logger = Logger.getLogger("javasoft");
		long start = System.currentTimeMillis();
		for (int i = 0; i < 10000; i++) {
			jedis.set(String.valueOf(i), String.valueOf(i));
		}
		long end = System.currentTimeMillis();
		logger.info("the jedis total time is:" + (end - start));

		Pipeline pipe = jedis.pipelined(); // 先创建一个 pipeline链接对象
		long start_pipe = System.currentTimeMillis();
		for (int i = 0; i < 10000; i++) {
			pipe.set(String.valueOf(i), String.valueOf(i));
		}
		pipe.sync(); // 获取所有的 response
		long end_pipe = System.currentTimeMillis();
		logger.info("the pipe total time is:" + (end_pipe - start_pipe));
		
		BlockingQueue<String> logQueue = new LinkedBlockingQueue<String>();
		long begin = System.currentTimeMillis();
		for (int i = 0; i < 10000; i++) {
			logQueue.put("i=" + i);
		}
		long stop = System.currentTimeMillis();
		logger.info("the BlockingQueue total time is:" + (stop - begin));
	}

在这里插入图片描述

小结

1、Pipeline执行速度一般比逐条执行要快。

2、客户端和服务端网络延时越大,Pipeline的效果越明显。

Pipeline虽然好用,但是每次Pipeline组装的命令个数不能没有节制,否则一次组装Pipeline数据量过大,一方面会增加客户端的等待时间,另一方面会造成一定的网络阻塞,可以将一次包含大量命令的Pipeline拆分多次较小的Pipeline来完成,比如可以将Pipeline的总发送大小控制内核输入输出缓冲区大小之内或者控制在单个TCP 报文最大值1460字节之内。

内核输入输出缓冲区大小一般是4K-8K,不同操作系统不同(当然也可以配置修改

最大传输单元(Maximum Transmission Unit,MTU),这个以太网最大值是1500字节。那为什么单个TCP 报文最大值是1460,因为因为还要扣减20个字节的IP头和20个字节的TCP头,所以是1460。

同时Pipeline只能操作一个Redis实例,但是即使在分布式Redis场景中,也可以作为批量操作的重要优化手段。

原文地址:https://blog.csdn.net/weixin_48052161/article/details/134758821

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_30526.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注