你真的了解redis为什么要提供pipeline功能

Redis本身是一个cs模式的tcp server, client可以通过一个socket连续发起多个请求命令。 每个请求命令发出后client通常会阻塞并等待redis服务端处理,redis服务端处理完后将结果返回给client。

redis的pipeline(管道)功能在命令行中没有,但redis是支持pipeline的,而且在各个语言版的client中都有相应的实现。 由于网络开销延迟,即算redis server端有很强的处理能力,也由于收到的client消息少,而造成吞吐量小。当client 使用pipelining 发送命令时,redis server必须部分请求放到队列中(使用内存)执行完毕后一次性发送结果;如果发送的命名很多的话,建议对返回的结果加标签,当然这也会增加使用的内存;

Pipeline在某些场景下非常有用,比如有多个command需要被“及时的”提交,而且他们对相应结果没有互相依赖,而且对结果响应也无需立即获得,那么pipeline就可以充当这种“批处理”的工具;而且在一定程度上,可以较大的提升性能,性能提升的原因主要是TCP链接中较少了“交互往返”的时间。不过在编码时请注意,pipeline期间将“独占”链接,此期间将不能进行非“管道”类型的其他操作,直到pipeline关闭;如果你的pipeline的指令集很庞大,为了不干扰链接中的其他操作,你可以为pipeline操作新建Client链接,让pipeline和其他正常操作分离在2个client中。不过pipeline事实上所能容忍的操作个数,和socket-output缓冲区大小/返回结果的数据尺寸都有很大的关系;同时也意味着每个redis-server同时所能支撑的pipeline链接的个数,也是有限的,这将受限于server的物理内存或网络接口的缓冲能力。

下面给大家普及redis为什么要提供pipeline功能。

通常我们用redis做接口缓存后,查询接口的性能就能提升到ms级别;
但是redis是纯内存操作啊,总不至于要到ms吧,根据官方的 benchmark 单实例也是能抗 7w+ qps 也就是说单个redis 操作在redis-server上耗时大概是 0.014ms,那时间是消耗到哪里去了?

redis是 client-server 模型,client客户端将 command 通过tcp网络连接发送到 server服务端,服务端执行完 command 后将响应再通过 tcp 连接发送给client;

对于应用服务来说,我们所关注的性能其实是客户端时间,即前面的整个执行过程,虽然 redis-server 命令执行的非常快,但每次命令执行都需要在网络上走一遭,按照我们公司redis客户端中间件统计的rt,一次命令的执行平均是1ms 左右,那么网络耗时占比: 1-0.014 / 1 = 0.98(98%!!! ) 可见,大部分时间都耗在网络io上

所以,减少网络io次数就能大大提供 redis-client 所感知的耗时,提升应用服务性能,redis提供的 pipeline 功能,让我们可以提交一个命令后,不用等这个返回结果就可以继续执行下一个命令,也就是说,可以执行多个命令后,一次性获取所有结果; 这样就大大减少了在网络上的消耗

比如

Client: INCR X
Client: INCR X
Client: INCR X
Client: INCR X

Server: 1
Server: 2
Server: 3
Server: 4

除此之外,减少了网络读写次数的同时,也减少了 redis-server 内核态和用户态的上下文切换,进一步提高了性能

性能提升了多少?

redis官方声称pipeline可带来10倍的性能提升

测试机Intel(R) Xeon(R) CPU E5520 @ 2.27GHz, 用pipeline比没用pipeline性能提升了将近7倍

// 用pipeline
$ ./redis-benchmark -r 1000000 -n 2000000 -t get,set,lpush,lpop -P 16 -q
SET: 552028.75 requests per second
GET: 707463.75 requests per second
LPUSH: 767459.75 requests per second
LPOP: 770119.38 requests per second

// 没用pipeline
SET: 122556.53 requests per second
GET: 123601.76 requests per second
LPUSH: 136752.14 requests per second
LPOP: 132424.03 requests per second

注意,使用pipeline的时候,多个命令的响应是缓存在server端的,所以在 pipeline 里一批命令的数量不要过多,以免服务端内存压力过大

其实,减少网络io次数的处理技巧还是比较常见的,如

  • CSS Sprites,将很多小图标合并成一张图片
  • jdbc batch api批量提交sql

参考:

https://redis.io/topics/pipelining

https://redis.io/topics/benchmarks

以上就是redis为什么要提供pipeline功能的详细内容,更多关于redis pipeline的资料请关注我们其它相关文章!

(0)

相关推荐

  • 详解redis大幅性能提升之使用管道(PipeLine)和批量(Batch)操作

    前段时间在做用户画像的时候,遇到了这样的一个问题,记录某一个商品的用户购买群,刚好这种需求就可以用到Redis中的Set,key作为productID,value就是具体的customerid集合,后续的话,我就可以通过productid来查看该customerid是否买了此商品,如果购买了,就可以有相关的关联推荐,当然这只是系统中的一个小业务条件,这时候我就可以用到SADD操作方法,代码如下: static void Main(string[] args) { ConnectionMultip

  • redis通过pipeline提升吞吐量的方法

    案例目标 简单介绍 redis pipeline 的机制,结合一段实例说明pipeline 在提升吞吐量方面发生的效用. 案例背景 应用系统在数据推送或事件处理过程中,往往出现数据流经过多个网元: 然而在某些服务中,数据操作对redis 是强依赖的,在最近的一次分析中发现: 一次数据推送会对 redis 产生近30次读写操作! 在数据推送业务中的性能压测中,以数据上报 -> 下发应答为一次事务:而对于这样的读写模型,redis 的操作过于频繁,很快便导致系统延时过高,吞吐量低下,无法满足目标:

  • 在Redis集群中使用pipeline批量插入的实现方法

    由于项目中需要使用批量插入功能, 所以在网上查找到了Redis 批量插入可以使用pipeline来高效的插入, 示例代码如下: String key = "key"; Jedis jedis = new Jedis("xx.xx.xx.xx"); Pipeline p = jedis.pipelined(); List<String> myData = .... //要插入的数据列表 for(String data: myData){ p.hset(ke

  • Redis利用Pipeline加速查询速度的方法

    1. RTT Redis 是一种基于客户端-服务端模型以及请求/响应协议的TCP服务.这意味着通常情况下 Redis 客户端执行一条命令分为如下四个过程: 发送命令 命令排队 命令执行 返回结果 客户端向服务端发送一个查询请求,并监听Socket返回,通常是以阻塞模式,等待服务端响应.服务端处理命令,并将结果返回给客户端.客户端和服务端通过网络进行连接.这个连接可以很快,也可能很慢.无论网络如何延迟,数据包总是能从客户端到达服务端,服务端返回数据给客户端. 这个时间被称为 RTT (Round

  • python使用pipeline批量读写redis的方法

    用了很久的redis了.随着业务的要求越来越高.对redis的读写速度要求也越来越高.正好最近有个需求(需要在秒级取值1000+的数据),如果对于传统的单词取值,循环取值,消耗实在是大,有小伙伴可能考虑到多线程,但这并不是最好的解决方案,这里考虑到了redis特有的功能pipeline管道功能. 下面就更大家演示一下pipeline在python环境下的使用情况. 1.插入数据 >>> import redis >>> conn = redis.Redis(host='

  • 详解Java使用Pipeline对Redis批量读写(hmset&hgetall)

    一般情况下,Redis Client端发出一个请求后,通常会阻塞并等待Redis服务端处理,Redis服务端处理完后请求命令后会将结果通过响应报文返回给Client. 感觉这有点类似于HBase的Scan,通常是Client端获取每一条记录都是一次RPC调用服务端. 在Redis中,有没有类似HBase Scanner Caching的东西呢,一次请求,返回多条记录呢? 有,这就是Pipline.官方介绍 http://redis.io/topics/pipelining 通过pipeline方

  • 你真的了解redis为什么要提供pipeline功能

    Redis本身是一个cs模式的tcp server, client可以通过一个socket连续发起多个请求命令. 每个请求命令发出后client通常会阻塞并等待redis服务端处理,redis服务端处理完后将结果返回给client. redis的pipeline(管道)功能在命令行中没有,但redis是支持pipeline的,而且在各个语言版的client中都有相应的实现. 由于网络开销延迟,即算redis server端有很强的处理能力,也由于收到的client消息少,而造成吞吐量小.当cli

  • 深入理解redis中multi与pipeline

    背景 由于对redis缓存中数据有批量操作,例如预热缓存数据,或者在列表页批量去获取缓存数据,在使用了multi批量提交事务后,发现redis压力高居不下,而使用了pipeline之后压力回落了平常,也因为这个案例,特在此写个分析与笔记. multi 简介 标记一个事务块的开始. 事务块内的多条命令会按照先后顺序被放进一个队列当中,最后由 EXEC 命令原子性(atomic)地执行. 实现原理 我用php扩展调起redis服务,执行,代码如下: $redis = new redis(); $re

  • Redis 实现“附近的人”功能

    针对"附近的人"这一位置服务领域的应用场景,常见的可使用PG.MySQL和MongoDB等多种DB的空间索引进行实现.而Redis另辟蹊径,结合其有序队列zset以及geohash编码,实现了空间搜索功能,且拥有极高的运行效率.本文将从源码角度对其算法原理进行解析,并推算查询时间复杂度. 操作命令 自Redis 3.2开始,Redis基于geohash和有序集合提供了地理位置相关功能. Redis Geo模块包含了以下6个命令: GEOADD: 将给定的位置对象(纬度.经度.名字)添加

  • Redis实现订单自动过期功能的示例代码

    前言 用户下单后,规定XX分钟后自动设置为"已过期",不能再发起支付.项目类似此类"过期"的需求,笔者提供一种使用Redis的解决思路,结合Redis的订阅.发布和键空间通知机制(Keyspace Notifications)进行实现. 配置redis.confg notify-keyspace-events选项默认是不启用,改为notify-keyspace-events "Ex".重启生效,索引位i的库,每当有过期的元素被删除时,向**key

  • 基于Redis位图实现用户签到功能

    场景需求 适用场景如签到送积分.签到领取奖励等,大致需求如下: 签到1天送1积分,连续签到2天送2积分,3天送3积分,3天以上均送3积分等. 如果连续签到中断,则重置计数,每月初重置计数. 当月签到满3天领取奖励1,满5天领取奖励2,满7天领取奖励3--等等. 显示用户某个月的签到次数和首次签到时间. 在日历控件上展示用户每月签到情况,可以切换年月显示--等等. 设计思路 对于用户签到数据,如果每条数据都用K/V的方式存储,当用户量大的时候内存开销是非常大的.而位图(BitMap)是由一组bit

  • javascript中不提供sleep功能如何实现这个功能

    javascript中不提供sleep功能,而我们时长会用到这个功能. 有一种思路是跑一段循环体,让程序空耗CPU的时间来实现延时.这有一个不足,不同的机器CPU的执行速度是不一样的,这很容易导致的慢的机器会SLEEP很久. 笔者从别的论坛看到一种机智的解决方法,在不同的机器上的执行速度是一致的.在此与大家共享. 复制代码 代码如下: function sleep(n) { var start=new Date().getTime(); while(true) if(new Date().get

  • PHP实现的redis主从数据库状态检测功能示例

    本文实例讲述了PHP实现的redis主从数据库状态检测功能.分享给大家供大家参考,具体如下: 实例: <?php /** * 检测多个主从redis数据库是否挂掉 * 建立从数据库$redis_db的二维数组,内容包含每个从服务器的配置数据 */ header("Content-Type: text/html; charset=utf-8"); set_time_limit(0); $redis_db = array( 'db1'=>array( 'hostname' =&

  • Java操作redis实现增删查改功能的方法示例

    本文实例讲述了Java操作redis实现增删查改功能的方法.分享给大家供大家参考,具体如下: 首先,我们需要在windows下配置一个redis环境,具体配置教程请看:http://www.jb51.net/article/96230.htm 然后需要导入:jedis-2.7.3.jar这个包,看如下代码: package redis.main; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; imp

  • java web response提供文件下载功能的实例讲解

    webapp项目的结构如下图: download.html文件的内容如下: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <h1>资源下载:</h1> <p> 单纯地使用a标签时,只有浏览器不能解析的文

  • PHP使用redis位图bitMap 实现签到功能

    一.需求 记录用户签到,查询用户签到 二.技术方案 1.使用mysql(max_time字段为连续签到天数) 思路: (1)用户签到,插入一条记录,根据create_time查询昨日是否签到,有签到则max_time在原基础+1,否则,max_time=0 (2)检测签到,根据user_id.create_time查询记录是否存在,不存在则表示未签到 2.使用redis位图功能 思路: (1)每个用户每个月单独一条redis记录,如00101010101010,从左往右代表01-31天(每月有几

随机推荐