java redis 流水线,Redis系列(1) —— 流水线

写在前面

去年下半年,出于学习Redis的目的,在看完《Redis in Action》一书后,开始尝试翻译Redis官方文档。尽管Redis中文官方网站有了译本,但是看别人翻译好的和自己翻译英文原文毕竟还是有很大的不同。这一系列文章之前发布在GitBook上,为了方便管理,跟其他文章一起放在同一个平台,遂全部迁移至简书。由于本人学习Redis时间不长,认识有限,同时也缺少实战经验,翻译中有任何不恰当之处,欢迎各位及时斧正,本人将不胜感激。对英文官方文档感兴趣的朋友也可以直接访问https://redis.io/ 进行获取。

使用流水线来提升redis的查询速度

请求/响应协议和RTT

Redis是一个使用客户端-服务端模型和请求/响应协议的TCP服务。这意味着完成一次请求通常需要经过以下步骤:

客户端向服务端发起一次查询请求并读取socket,这通常是以阻塞方式来等待服务端响应。

服务端处理命令并将响应发回给客户端。

例如下面是一个4条命令序列的执行情况:

客户端:INCR x

服务端:1

客户端:INCR x

服务端:2

客户端:INCR x

服务端:3

客户端:INCR x

服务端:4

客户端和服务端通过网络来连接。这样的连接可以很快(loopback接口)也可以很慢(两台主机之间建立的是一个经过了多次跳转的网络连接)。不管网络延迟如何,数据包从客户端发往服务端,然后携带响应从服务端发往客户端总是会消耗时间的。

这个时间被称为RTT(Round Trip Time)。当客户端需要一次性处理很多请求时很容易看到这是如何影响到性能的(比如说向一个列表中添加很多元素,或者用很多键值填充数据库)。例如假设RTT时间为250毫秒(在网络连接很慢的网络条件下),那么即使服务端每秒可以处理100000个请求,我们每秒最多也只能处理4个请求。

如果使用loopback接口,RTT时间就会短很多(例如在我的机器上ping127.0.0.1只需要0.044毫秒),但是如果我们需要批量处理很多写请求,这个时间仍然是很大的一笔开销。

好在我们还有一种方式可以来改善这种状况。

Redis流水线

即使客户端旧的请求还没有得到响应,一个请求/响应服务器也可以处理新的请求。这样一来我们就可以一次向服务端发送多条命令而根本不用等待响应,最后在一个步骤中读取所有回复。

这就是流水线,这是一种几十年来被广泛采用的技术。例如很多POP3协议的实现已经支持了这种特性,它极大地加快了从服务器下载新邮件的过程。

Redis很早就支持了流水线功能,所以无论你正在使用的是哪个版本,你都可以使用Redis的流水线技术。下面是一个使用这种原生能力的例子:

$ (printf "PING\r\nPING\r\nPING\r\n"; sleep 1) | nc localhost 6379

+PONG

+PONG

+PONG

这一次我们没有为每次调用都消耗RTT,而是4个命令只消耗一次时间。

更明确地说,通过使用流水线技术,我们第一个例子的操作顺序将会是下面这个样子:

客户端: INCR x

客户端: INCR x

客户端: INCR x

客户端: INCR x

服务端:1

服务端:2

服务端:3

服务端:4

重要提示:当客户端使用流水线技术来发送命令时,服务端将不得不使用内存来排队答复。所以如果你需要使用流水线来发送很多命令,最好是将他们按照合理的数量来分批处理,比如先发送10000条命令,读取响应,再发送另外10000条命令等等。速度几乎是一样的,但是将需要大量额外的内存来存储这10000条命令的答复。

这不仅仅关乎RTT

流水线不仅仅是一种用来减少RTT延迟成本的方式,实际上对于一台给定的Redis服务器,它极大地提高了每秒钟你所能处理的操作数量。一个事实是,当不采用流水线技术时,从访问数据结构并且产生响应的角度来看,每一条命令的时间消耗都是很少的,但是从处理socket IO的角度来看,这个时间消耗确是很大的。它涉及到调用read()和write()这些系统调用,这意味着要从用户侧到内核侧。而上下文切换是一个巨大的时间开销,会严重影响响应速度。

当使用流水线时,一个简单的read()系统调用就可以读取很多命令,同样的,一个简单的write()系统调用就可以将很多回复传送出去。正因为如此,每秒钟可以处理的查询命令的数量几乎随着管道长度的增加而呈线性增长,最终可以达到不使用流水线这种基本情况时的10倍,正如你从下图看到的那样:

a8325675a1c8

image.png

一些真实世界的代码样例

在下面这个基准测试中,我们将会使用基于Ruby的redis客户端,支持流水线操作,来测试流水线对于速度的提升效果:

require 'rubygems'

require 'redis'

def bench(descr)

start = Time.now

yield

puts "#{descr} #{Time.now-start} seconds"

end

def without_pipelining

r = Redis.new

10000.times {

r.ping

}

end

def with_pipelining

r = Redis.new

r.pipelined {

10000.times {

r.ping

}

}

end

bench("without pipelining") {

without_pipelining

}

bench("with pipelining") {

with_pipelining

}

在我的Mac OS X系统上执行上面这个简单的脚本将会得到如下的数据,开启流水线功能后,RTT已经被改善得相当低。

without pipelining 1.185238 seconds

with pipelining 0.250783 seconds

如你所见,开启流水线后,我们把传输速度提升了5倍。

流水线 VS 脚本

使用Redis脚本(2.6及以上版本的redis可用),很多使用流水线的场景可以获得更高效的处理,因为使用脚本可以在服务端执行大量工作。脚本的一大优势是它可以使读写数据只需要很小的时延,使得读、计算和写操作变得很快(流水线在这种场景下做不到这一点,因为客户端在调用写命令之前需要读命令的返回结果)

有时候应用也会需要向流水线发送EVAL或者EVALSHA命令。这完全是有可能的并且Redis已经通过SCRIPT LOAD命令明确支持了这一点(它保证EVALSHA命令会调用成功)。

附录:为什么即使在loopback接口上一个忙碌的循环也很慢

即使在这个页面的背景之下,你还是会想知道为什么即使在loopback接口上执行并且服务端和客户端运行在同一台物理机上时,一个一个像下面的Redis基准测试(伪代码)还是会很慢:

FOR-ONE-SECOND:

Redis.SET("foo","bar")

END

毕竟如果Redis过程和基准测试运行在一起时,难道它不是仅仅将信息在内存上从一个地方复制到另一个地方,中间没有任何真正的延时和网络参与进来吗?

原因在于系统上的过程不是一直在运行,实际上是内核调度器才让过程运行起来,所以基准测试开始运行时,从Redis服务端读取返回数据(跟最后一条执行的命令相关),并且写了一条新命令。现在命令存在于loopback接口的缓存里,但是为了能够被服务端读取到,内核会通过调度让服务端的过程(当前被阻塞在系统调用里)运行起来,等等。所以在实际场景下,因为内核调度器的工作机制,loopback接口还是涉及到了类网络延时。

基本上在网络服务器中测量性能时,一个忙碌的循环基准测试是最愚蠢的事情。明智的做法是避免使用这种方法进行基准测试。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/440464.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【HDU - 6187】Destroy Walls(思维,最大生成树)

题干: Long times ago, there are beautiful historic walls in the city. These walls divide the city into many parts of area. Since it was not convenient, the new king wants to destroy some of these walls, so he can arrive anywhere from his castl…

mseq matlab,Matlab生成M序列

版权声明:本文为CSDN博主「laomai」的原创文章原文链接:https://blog.csdn.net/laomai/article/details/24342493找了好多代码,这个步骤详细可以傻瓜操作,存着备用~实验环境为matlab2013b1、首先编写一个mseq.m文件,内容为:functi…

【HDU - 6185】Covering(矩阵快速幂优化二维dp,高斯消元,轮廓线dp打表)

题干: Bobs school has a big playground, boys and girls always play games here after school. To protect boys and girls from getting hurt when playing happily on the playground, rich boy Bob decided to cover the playground using his carpets. Me…

Java工厂构造函数参数,javascript 面向对象之构造函数、工厂方式、字面量

什么是面向对象编程面向对象的英文全称:Object Oriented Programming , 简称OOP首先我们要先了解面向过程的编程思想, 就是代码从上到下都没有封装的意思,某写代码裸露在外、没有模块化、代码杂乱无章的写法. 并且还不好维护,也不便于后期二次修改面向对…

【HDU - 6186】CS Course(按位与,按位或,按位异或的区间统计,二进制拆位)

题干: Little A has come to college and majored in Computer and Science. Today he has learned bit-operations in Algorithm Lessons, and he got a problem as homework. Here is the problem: You are giving n non-negative integers a1,a2,⋯,ana1,a2,…

mysql不能存字母,使用不常見的字母/符號時,MySql數據庫不能正確存儲數據

I have a simple form that sends (via php) some variables to a mySql database.我有一個簡單的表單,通過PHP發送一些變量到mySql數據庫。The problem is that its focused to Portuguese audience, and we use several unusual letters, like "" and ""…

【HDU - 6184】Counting Stars(三元环计数,二分,优化暴力,O(m*sqrt(m)),图论)

题干: Little A is an astronomy lover, and he has found that the sky was so beautiful! So he is counting stars now! There are n stars in the sky, and little A has connected them by m non-directional edges. It is guranteed that no edges connec…

php 取oracle图片,在PHP中将图片存放ORACLE中_php

我这里提供一个用php操纵blob字段的例子给你,希望能有所帮助!这个例子是把用户上传的图片文件存放到BLOB中。假设有一个表,结构如下:CREATE TABLE PICTURES (ID NUMBER,http://www.gaodaima.com/44856.html在PHP中将图片存放oracl…

【HDU - 6183】Color it(CDQ分治 或 动态开点线段树)

题干: Do you like painting? Little D doesnt like painting, especially messy color paintings. Now Little B is painting. To prevent him from drawing messy painting, Little D asks you to write a program to maintain following operations. The speci…

php create()方法,ThinkPHP中create()方法自动验证实例

ThinkPHP中create()方法自动验证实例2020-06-16 04:24:32自动验证是ThinkPHP模型层提供的一种数据验证方法,可以在使用create创建数据对象的时候自动进行数据验证。原理:create()方法收集表单($_POST)信息并返回,同时触发表单自动验证&#x…

【蓝桥杯官网试题 - 历届试题】格子刷油漆(dp)

题干: 问题描述 X国的一段古城墙的顶端可以看成 2*N个格子组成的矩形(如下图所示),现需要把这些格子刷上保护漆。   你可以从任意一个格子刷起,刷完一格,可以移动到和它相邻的格子(对角相邻也…

php 解析 ini文件,php解析.ini文件

1.myphp.ini文件autostart false font_size 12font_color red$string[access] 进入;$string[accesshelp] 进入帮助;$string[accesskey] 进入验证 {$a};$string[accessstatement] 进入声明;$string[activitynext] 下一个活动;$string[activityprev] 前一个活动;$string…

【CSU - 1004】Xi and Bo(并查集,裸题)

题干: Bo has been in Changsha for four years. However he spends most of his time staying his small dormitory. One day he decides to get out of the dormitory and see the beautiful city. So he asks to Xi to know whether he can get to another bus …

oracle软件静默安装程序,【oracle】静默安装 oracle 11gr2

【序言】oracle 提供了静默安装方法在不适用图形界面的情况下安装 oracle 软件 ,创建db,配置netca,快速完成oracle 的部署。在以下情形中可以使用静默安装a OUI 的 GUI 界面远程交互比较慢 .b 数据库服务器无法使用图形界面访问.c 批量部署oracle (标准环境统一情况下可以使用o…

【2050 Programming Competition - 2050 一万人码 】非官方部分题解(HDU)

1001 开场白 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 12147 Accepted Submission(s): 3502 Problem Description 来自世界各地的年青人在 https://2050.org.cn 握手团聚, 他们是航空…

oracle数据库建表视频,Oracle数据库的创建表全

CREATE TABLE "库名"."表名" ("FEE_ID" VARCHAR2(10 BYTE) constraint ABS_FEE_ID primary key,--主键,必须要有序列"BANK_GROUP_ID" VARCHAR2(5 BYTE),"ABS_PRODUCT_ID" VARCHAR2(30 BYTE))TABLESPACE "表…

oracle的脚本语言是什么意思,Oracle中的sql脚本语言中的循环语句介绍

--sql脚本语言的循环介绍&#xff1a;--1.goto循环点。declarex number;beginx:0;--变量初始化&#xff1b;<>--设置循环点。x:x1;dbms_output.put_line(x);--循环体if x<9 then --进入循环的条件。goto repeat_loop; --用goto关键字引导进入循环。end i…

【poj题集整理】【存下来并不会看】

主要是整理起来自己用的。网上有多个版本。 初级: 一.基本算法: (1)枚举. (poj1753,poj2965) (2)贪心(poj1328,poj2109,poj2586) (3)递归和分治法. (4)递推. (5)构造法.(poj3295) (6)模拟法.(poj1068,poj2632,poj1573,poj2993,poj2996) 二.图算…

oracle排名怎么去除空值影响,Oracle排序中null值处理方法讲解

1、缺省处理oracle在order by 时缺省认为null是最大值&#xff0c;所以如果是asc升序则排在最后&#xff0c;desc降序则排在最前2、使用nvl函数nvl函数可以将输入参数为空时转换为一特定值&#xff0c;如nvl(employee_name,’张三’)表示当employee_name为空时则返回’张三’&a…

【ZOJ - 3870】Team Formation(异或,思维)

题干&#xff1a; For an upcoming programming contest, Edward, the headmaster of Marjar University, is forming a two-man team from N students of his university. Edward knows the skill level of each student. He has found that if two students with skill lev…