mirror of
https://github.com/fluencelabs/redis
synced 2025-07-11 23:01:33 +00:00
client-libraries
deps
design-documents
doc
AppendCommand.html
AppendOnlyFileHowto.html
AuthCommand.html
Benchmarks.html
BgrewriteaofCommand.html
BgsaveCommand.html
BlpopCommand.html
BrpoplpushCommand.html
CommandReference.html
Comparisons.html
ConfigCommand.html
Configuration.html
ConnectionHandlingSidebar.html
ControlCommandsSidebar.html
Credits.html
DbsizeCommand.html
DelCommand.html
DesignPatterns.html
EventLibray.html
ExistsCommand.html
ExpireCommand.html
FAQ.html
Features.html
FlushallCommand.html
FlushdbCommand.html
FromSqlToDataStructures.html
GenericCommandsSidebar.html
GetCommand.html
GetbitCommand.html
GetsetCommand.html
HackingStrings.html
HashCommandsSidebar.html
Hashes.html
HdelCommand.html
HexistsCommand.html
HgetCommand.html
HgetallCommand.html
HincrbyCommand.html
HlenCommand.html
HmgetCommand.html
HmsetCommand.html
HsetCommand.html
HsetnxCommand.html
IncrCommand.html
InfoCommand.html
IntroductionToRedisDataTypes.html
KeysCommand.html
LastsaveCommand.html
LindexCommand.html
ListCommandsSidebar.html
Lists.html
LlenCommand.html
LpopCommand.html
LrangeCommand.html
LremCommand.html
LsetCommand.html
LtrimCommand.html
MgetCommand.html
MonitorCommand.html
MoveCommand.html
MsetCommand.html
MultiExecCommand.html
NonexistentCommands.html
ObjectHashMappers.html
Pipelining.html
ProgrammingExamples.html
ProtocolSpecification.html
PublishSubscribe.html
QuickStart.html
QuitCommand.html
README.html
RandomkeyCommand.html
Redis0100ChangeLog.html
Redis0900ChangeLog.html
RedisBigData.html
RedisCLI.html
RedisEventLibrary.html
RedisGuides.html
RedisInternals.html
RedisPipelining.html
RedisStatus.html
Redis_1_2_0_Changelog.html
Redis_2_0_0_Changelog.html
Redis_2_0_Whats_new.html
RenameCommand.html
RenamenxCommand.html
ReplicationHowto.html
ReplyTypes.html
RoadMap.html
RpoplpushCommand.html
RpushCommand.html
SaddCommand.html
SaveCommand.html
ScardCommand.html
SdiffCommand.html
SdiffstoreCommand.html
SelectCommand.html
SetCommand.html
SetCommandsSidebar.html
SetbitCommand.html
SetexCommand.html
SetnxCommand.html
SetrangeCommand.html
Sets.html
ShutdownCommand.html
SideBar.html
SinterCommand.html
SinterstoreCommand.html
SismemberCommand.html
SlaveofCommand.html
SmembersCommand.html
SmoveCommand.html
SortCommand.html
SortedSetCommandsSidebar.html
SortedSets.html
Speed.html
SponsorshipHistory.html
SpopCommand.html
SrandmemberCommand.html
SremCommand.html
StringCommandsSidebar.html
Strings.html
StrlenCommand.html
SubstrCommand.html
SunionCommand.html
SunionstoreCommand.html
SupportedLanguages.html
SupportedPlatforms.html
TemplateCommand.html
TtlCommand.html
TwitterAlikeExample.html
TypeCommand.html
UnstableSource.html
VirtualMemorySpecification.html
VirtualMemoryUserGuide.html
ZaddCommand.html
ZcardCommand.html
ZincrbyCommand.html
ZrangeCommand.html
ZrangebyscoreCommand.html
ZrankCommand.html
ZremCommand.html
ZremrangebyrankCommand.html
ZremrangebyscoreCommand.html
ZscoreCommand.html
ZunionCommand.html
ZunionstoreCommand.html
index.html
redis.png
style.css
src
tests
utils
.gitignore
00-RELEASENOTES
BUGS
CONTRIBUTING
COPYING
Changelog
INSTALL
Makefile
README
TODO
redis.conf
94 lines
6.7 KiB
HTML
94 lines
6.7 KiB
HTML
![]() |
|
||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
|
||
|
<html>
|
||
|
<head>
|
||
|
<link type="text/css" rel="stylesheet" href="style.css" />
|
||
|
</head>
|
||
|
<body>
|
||
|
<div id="page">
|
||
|
|
||
|
<div id='header'>
|
||
|
<a href="index.html">
|
||
|
<img style="border:none" alt="Redis Documentation" src="redis.png">
|
||
|
</a>
|
||
|
</div>
|
||
|
|
||
|
<div id="pagecontent">
|
||
|
<div class="index">
|
||
|
<!-- This is a (PRE) block. Make sure it's left aligned or your toc title will be off. -->
|
||
|
<b>RedisPipelining: Contents</b><br> <a href="#Request/Response protocols and RTT">Request/Response protocols and RTT</a><br> <a href="#Redis Pipelining">Redis Pipelining</a><br> <a href="#Some benchmark">Some benchmark</a><br> <a href="#Pipelining VS other multi-commands">Pipelining VS other multi-commands</a>
|
||
|
</div>
|
||
|
|
||
|
<h1 class="wikiname">RedisPipelining</h1>
|
||
|
|
||
|
<div class="summary">
|
||
|
|
||
|
</div>
|
||
|
|
||
|
<div class="narrow">
|
||
|
<h1><a name="Request/Response protocols and RTT">Request/Response protocols and RTT</a></h1>
|
||
|
Redis is a TCP server using the client-server model and what is called a <b>Request/Response</b> protocol.<br/><br/>This means that usually a request is accomplished with the following steps:
|
||
|
<ul><li> The client sends a query to the server, and reads from the socket, usually in a blocking way, for the server response.</li><li> The server processes the command and sends the response back to the server.</li></ul>So for instance a four commands sequence is something like this:
|
||
|
<ul><li> <b>Client:</b> INCR X</li><li> <b>Server:</b> 1</li><li> <b>Client:</b> INCR X</li><li> <b>Server:</b> 2</li><li> <b>Client:</b> INCR X</li><li> <b>Server:</b> 3</li><li> <b>Client:</b> INCR X</li><li> <b>Server:</b> 4</li></ul>Clients and Servers are connected via a networking link. Such a link can be very fast (a loopback interface) or very slow (a connection established over the internet with many hops between the two hosts). Whatever the network latency is, there is a time for the packets to travel from the client to the server, and back from the server to the client to carry the reply.<br/><br/>This time is called RTT (Round Trip Time). It is very easy to see how this can affect the performances when a client needs to perform many requests in a row (for instance adding many elements to the same list, or populating a database with many keys). For instance if the RTT time is 250 milliseconds (in the case of a very slow link over the internet), even if the server is able to process 100k requests per second, we'll be able to process at max four requests per second.<br/><br/>If the interface used is a loopback interface, the RTT is much shorter (for instance my host reports 0,044 milliseconds pinging 127.0.0.1), but it is still a lot if you need to perform many writes in a row.<br/><br/>Fortunately there is a way to improve this use cases.
|
||
|
<h1><a name="Redis Pipelining">Redis Pipelining</a></h1>
|
||
|
A Request/Response server can be implemented so that it is able to process new requests even if the client didn't already read the old responses. This way it is possible to send <b>multiple commands</b> to the server without waiting for the replies at all, and finally read the replies in a single step.<br/><br/>This is called pipelining, and is a technique widely in use since many decades. For instance many POP3 protocol implementations already supported this feature, dramatically speeding up the process of downloading new emails from the server.<br/><br/>Redis supports pipelining since the very early days, so whatever version you are running, you can use pipelining with Redis. This is an example using the raw netcat utility:
|
||
|
<pre class="codeblock python" name="code">
|
||
|
$ (echo -en "PING\r\nPING\r\nPING\r\n"; sleep 1) | nc localhost 6379
|
||
|
+PONG
|
||
|
+PONG
|
||
|
+PONG
|
||
|
</pre>
|
||
|
This time we are not paying the cost of RTT for every call, but just one time for the three commands.<br/><br/>To be very explicit, with pipelining the order of operations of our very first example will be the following:
|
||
|
<ul><li> <b>Client:</b> INCR X</li><li> <b>Client:</b> INCR X</li><li> <b>Client:</b> INCR X</li><li> <b>Client:</b> INCR X</li><li> <b>Server:</b> 1</li><li> <b>Server:</b> 2</li><li> <b>Server:</b> 3</li><li> <b>Server:</b> 4</li></ul><b>IMPORTANT NOTE</b>: while the client sends commands using pipelining, the server will be forced to queue the replies, using memory. So if you need to send many many commands with pipelining it's better to send this commands up to a given reasonable number, for instance 10k commands, read the replies, and send again other 10k commands and so forth. The speed will be nearly the same, but the additional memory used will be at max the amount needed to queue the replies for this 10k commands.
|
||
|
<h1><a name="Some benchmark">Some benchmark</a></h1>
|
||
|
In the following benchmark we'll use the Redis Ruby client, supporting pipelining, to test the speed improvement due to pipelining:
|
||
|
<pre class="codeblock python python" name="code">
|
||
|
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
|
||
|
}
|
||
|
</pre>
|
||
|
Running the above simple script will provide this figures in my Mac OS X system, running over the loopback interface, where pipelining will provide the smallest improvement as the RTT is already pretty low:
|
||
|
<pre class="codeblock python python python" name="code">
|
||
|
without pipelining 1.185238 seconds
|
||
|
with pipelining 0.250783 seconds
|
||
|
</pre>
|
||
|
As you can see using pipelining we improved the transfer by a factor of five.
|
||
|
<h1><a name="Pipelining VS other multi-commands">Pipelining VS other multi-commands</a></h1>
|
||
|
Often we get requests about adding new commands performing multiple operations in a single pass.
|
||
|
For instance there is no command to add multiple elements in a set. You need calling many times SADD.<br/><br/>With pipelining you can have performances near to an MSADD command, but at the same time we'll avoid bloating the Redis command set with too many commands. An additional advantage is that the version written using just SADD will be ready for a distributed environment (for instance Redis Cluster, that is in the process of being developed) just dropping the pipelining code.
|
||
|
</div>
|
||
|
|
||
|
</div>
|
||
|
</div>
|
||
|
</body>
|
||
|
</html>
|
||
|
|