Redis研究(十八)—管道(pipeline)
来源:互联网 发布:ug8.0编程教学视频 编辑:程序博客网 时间:2024/06/01 08:56
客户端和Redis使用TCP协议连接。不论是客户端向Redis发送命令还是Redis向客户端返回命令的执行结果,都需要经过网络传输,这两个部分的总耗时称为往返时延。根据网络性能不同,往返时延也不同,大致来说到本地回环地址(loop back address)的往返时延在数量级上相当于Redis处理一条简单命令(如LPUSH list 1 2 3)的时间。如果执行较多的命令,每个命令的往返时延累加起来对性能还是有一定影响的。
在执行多个命令时每条命令都需要等待上一条命令执行完(即收到Redis的返回结果)才能执行,即使命令不需要上一条命令的执行结果。如要获得post :1、post :2和post :3这3个键中的title字段,需要执行三条命令:
Redis的底层通信协议对管道(pipeline )提供了支持。通过管道可以一次性发送多条命令并在执行完后一次性将结果返回,当一组命令中每条命令都不依赖于之前命令的执行结果时就可以将这组命令一起通过管道发出。管道通过减少客户端与Redis的通信次数来实现降低往返时延累计值的目的:
下面具体分析之:
Redis是一个cs模式的tcp server,使用和http类似的请求响应协议。一个client可以通过一个socket连接发起多个请求命令。每个请求命令发出后client通常会阻塞并等待redis服务处理,redis处理完后请求命令后会将结果通过响应报文返回给client。基本的通信过程如下:
Client: INCR XServer: 1Client: INCR XServer: 2Client: INCR XServer: 3Client: INCR XServer: 4
基本上四个命令需要8个tcp报文才能完成。由于通信会有网络延迟,假如从client和server之间的包传输时间需要0.125秒。那么上面的四个命令8个报文至少会需要1秒才能完成。这样即使redis每秒能处理100个命令,而我们的client也只能一秒钟发出四个命令。这显示没有充分利用 redis的处理能力。除了可以利用mget,mset之类的单条命令处理多个key的命令外我们还可以利用pipeline的方式从client打包多条命令一起发出,不需要等待单条命令的响应返回,而redis服务端会处理完多条命令后会将多条命令的处理结果打包到一起返回给客户端。通信过程如下:
Client: INCR XClient: INCR XClient: INCR XClient: INCR XServer: 1Server: 2Server: 3Server: 4
通过pipeline方式当有大批量的操作时候。我们可以节省很多原来浪费在网络延迟的时间。需要注意到是用 pipeline方式打包命令发送,redis必须在处理完所有命令前先缓存起所有命令的处理结果。打包的命令越多,缓存消耗内存也越多。所以并是不是打包的命令越多越好。具体多少合适需要根据具体情况测试。下面是个jedis客户端使用pipeline的测试:
import redis.clients.jedis.Jedis;import redis.clients.jedis.Pipeline; public class PipelineTest { public static void main(String[] args) { int count = 1000; long start = System.currentTimeMillis(); withoutPipeline(count); long end = System.currentTimeMillis(); System.out.println("withoutPipeline: " + (end-start)); start = System.currentTimeMillis(); usePipeline(count); end = System.currentTimeMillis(); System.out.println("usePipeline: " + (end-start)); } private static void withoutPipeline(int count){ Jedis jr = null; try { jr = new Jedis("10.10.224.44", 6379); for(int i =0; i<count; i++){ jr.incr("testKey1"); } } catch (Exception e) { e.printStackTrace(); } finally{ if(jr!=null){ jr.disconnect(); } } } private static void usePipeline(int count){ Jedis jr = null; try { jr = new Jedis("10.10.224.44", 6379); Pipeline pl = jr.pipelined(); for(int i =0; i<count; i++){ pl.incr("testKey2"); } pl.sync(); } catch (Exception e) { e.printStackTrace(); } finally{ if(jr!=null){ jr.disconnect(); } } }}
输出:
withoutPipeline: 11341usePipeline: 344
测试结果还是很明显有较大的差距,所以多次操作用pipeline还是有明显的优势。
- Redis研究(十八)—管道(pipeline)
- Redis管道(pipeline)
- Redis管道(pipeline)
- Redis中文文档——1.2管道(pipeline)
- 分布式缓存Redis之Pipeline(管道)
- Redis学习笔记(十六)Redis管道(pipeline)
- Redis学习笔记7--Redis管道(pipeline)
- Redis学习笔记7--Redis管道(pipeline)
- Redis学习笔记7--Redis管道(pipeline)
- 使用Redis的管道(Pipeline)进行批量操作
- Redis 管道pipeline
- 012redis管道(pipeline)
- Redis 管道pipeline
- pipeline(管道)设计模式
- redis大幅性能提升之使用管道(PipeLine)和批量(Batch)操作
- .NET客户端实现Redis中的管道(PipeLine)与事物(Transactions)(八)
- MongoDB 聚合管道(一)(Aggregation Pipeline)
- MongoDB 聚合管道(二)(Aggregation Pipeline)
- 六款值得推荐的android(安卓)开源框架简介
- Smali--Dalvik虚拟机指令语言-->【android_smali语法学习一】
- zookeeper技术浅析
- crontab简易入门
- OpenMP并行构造的schedule子句详解
- Redis研究(十八)—管道(pipeline)
- Android Studio不能新建project解决办法
- 蓝桥杯 基础练习 数列排序
- VS2013中VirtualBasic.PowerPacks文件的缺失的安装与配置
- 单例
- 一、Unity4.6UI-------Canvas
- ZgiBee分配短地址
- 浏览器客户端-自定义服务端
- poj 2573 bridge