Commit Graph

143 Commits

Author SHA1 Message Date
antirez
dcc48a8143 replicationFeedSlave() reworked for correctness and speed.
The previous code using a static buffer as an optimization was lame:

1) Premature optimization, actually it was *slower* than naive code
   because resulted into the creation / destruction of the object
   encapsulating the output buffer.
2) The code was very hard to test, since it was needed to have specific
   tests for command lines exceeding the size of the static buffer.
3) As a result of "2" the code was bugged as the current tests were not
   able to stress specific corner cases.

It was replaced with easy to understand code that is safer and faster.
2013-08-12 12:50:29 +02:00
antirez
aa05128f51 Fix a PSYNC bug caused by a variable name typo. 2013-08-12 11:51:35 +02:00
antirez
89ffba9133 Replication: better way to send a preamble before RDB payload.
During the replication full resynchronization process, the RDB file is
transfered from the master to the slave. However there is a short
preamble to send, that is currently just the bulk payload length of the
file in the usual Redis form $..length..<CR><LF>.

This preamble used to be sent with a direct write call, assuming that
there was alway room in the socket output buffer to hold the few bytes
needed, however this does not scale in case we'll need to send more
stuff, and is not very robust code in general.

This commit introduces a more general mechanism to send a preamble up to
2GB in size (the max length of an sds string) in a non blocking way.
2013-08-12 10:29:14 +02:00
antirez
c151eb6d92 Fix replicationFeedSlaves() off-by-one bug.
This fixes issue #1221.
2013-07-28 12:49:34 +02:00
antirez
a31693417d Fix replicationFeedSlaves() to use sdsEncodedObject() macro. 2013-07-22 10:36:27 +02:00
Ted Nyman
f39a0bdb77 Make sure the log standardizes on 'timeout' 2013-07-12 14:06:27 -07:00
antirez
d1cbad6d14 Use getClientPeerId() for MONITOR implementation. 2013-07-09 16:21:21 +02:00
antirez
90038906f4 Fix old anetPeerToString() API call in replication.c 2013-07-08 16:11:52 +02:00
Geoff Garside
ee5a6df101 Update calls to anetPeerToString to include ip_len. 2013-07-08 15:57:22 +02:00
antirez
8ca265cdb7 Don't disconnect pre PSYNC replication clients for timeout.
Clients using SYNC to replicate are older implementations, such as
redis-cli --slave, and are not designed to acknowledge the master with
REPLCONF ACK commands, so we don't have any feedback and should not
disconnect them on timeout.
2013-06-26 10:11:20 +02:00
antirez
f0bf5fd8c7 Use the RSC to replicate EVALSHA unmodified.
This commit uses the Replication Script Cache in order to avoid
translating EVALSHA into EVAL whenever possible for both the AOF and
slaves.
2013-06-24 18:57:31 +02:00
antirez
94ec7db470 Replication of scripts as EVALSHA: sha1 caching implemented.
This code is only responsible to take an LRU-evicted fixed length cache
of SHA1 that we are sure all the slaves received.

In this commit only the implementation is provided, but the Redis core
does not use it to actually send EVALSHA to slaves when possible.
2013-06-24 10:26:04 +02:00
antirez
1a54d5963e Refresh good slaves count when setting slave state as online. 2013-05-30 12:13:25 +02:00
antirez
ed599d3aca min-slaves-to-write: don't accept writes with less than N replicas.
This feature allows the user to specify the minimum number of
connected replicas having a lag less or equal than the specified
amount of seconds for writes to be accepted.
2013-05-30 11:30:04 +02:00
antirez
3c82c85fcf Close connection with timedout slaves.
Now masters, using the time at which the last REPLCONF ACK was received,
are able to explicitly disconnect slaves that are no longer responding.

Previously the only chance was to see a very long output buffer, that
was highly suboptimal.
2013-05-27 11:42:42 +02:00
antirez
e06a560466 Send ACK to master once every second.
ACKs can be also used as a base for synchronous replication. However in
that case they'll be explicitly requested by the master when the client
sends a request that needs to be replicated synchronously.
2013-05-27 11:42:38 +02:00
antirez
efd87031d0 Don't ACK the master after every command.
Sending an ACK is now moved into the replicationSendAck() function.
2013-05-27 11:42:35 +02:00
antirez
dd0adbb777 Make sure that REPLCONF ACK really has no return value. 2013-05-27 11:42:30 +02:00
antirez
6b4635f4f5 REPLCONF ACK command.
This special command is used by the slave to inform the master the
amount of replication stream it currently consumed.

it does not return anything so that we not need to consume additional
bandwidth needed by the master to reply something.

The master can do a number of things knowing the amount of stream
processed, such as understanding the "lag" in bytes of the slave, verify
if a given command was already processed by the slave, and so forth.
2013-05-27 11:42:17 +02:00
antirez
b7d085fc0d Cluster: SLAVEOF command not allowed in cluster mode. 2013-03-05 12:39:41 +01:00
antirez
3be893123f Make sure replicationSetMaster() works when ip argument is not an sds. 2013-03-04 15:39:55 +01:00
antirez
7bead003e2 SLAVEOF command refactored into a proper API.
We now have replicationSetMaster() and replicationUnsetMaster() that can
be called in other contexts (for instance Redis Cluster).
2013-03-04 13:22:21 +01:00
antirez
f9b5ca29fd Use GCC printf format attribute for redisLog().
This commit also fixes redisLog() statements producing warnings.
2013-02-27 12:27:15 +01:00
antirez
072c91fe13 PSYNC: another change to unexpected reply from PSYNC. 2013-02-13 18:43:40 +01:00
antirez
0e1be5347b PSYNC: More robust handling of unexpected reply to PSYNC. 2013-02-13 18:33:33 +01:00
antirez
3419c8ce70 Replication: more strict error checking for master PING reply. 2013-02-12 16:53:27 +01:00
antirez
24f258360b Replication: added new stats counting full and partial resynchronizations. 2013-02-12 15:33:54 +01:00
antirez
3af478e9ef PSYNC: debugging printf() calls are now logs at DEBUG level. 2013-02-12 12:52:22 +01:00
antirez
89b48f0825 Remove harmless warning in slaveTryPartialResynchronization(). 2013-02-12 12:52:21 +01:00
antirez
0ed6daa48b PSYNC: don't use the client buffer to send +CONTINUE and +FULLRESYNC.
When we are preparing an handshake with the slave we can't touch the
connection buffer as it'll be used to accumulate differences between
the sent RDB file and what arrives next from clients.

So in short we can't use addReply() family functions.

However we just use write(2) because we know that the socket buffer is
empty, since a prerequisite for SYNC to work is that the static buffer
and the output list are empty, and in general it is not expected that a
client SYNCs after doing some heavy I/O with the master.

However a short write connection is explicitly handled to avoid
fragility (we simply close the connection and the slave will retry).
2013-02-12 12:52:21 +01:00
antirez
d2a0348a49 SYNC not allowed with pending data on the static output buffer. 2013-02-12 12:52:21 +01:00
antirez
da315d3325 Log the unexpected string received in place of the SYNC payload length. 2013-02-12 12:52:21 +01:00
antirez
41d64a7516 After SLAVEOF <newslave> don't allow chained slaves to PSYNC. 2013-02-12 12:52:21 +01:00
antirez
078882025e PSYNC: work in progress, preview #2, rebased to unstable. 2013-02-12 12:52:21 +01:00
antirez
e34a35a511 Use the new unified protocol to send SELECT to slaves.
SELECT was still transmitted to slaves using the inline protocol, that
is conceived mostly for humans to type into telnet sessions, and is
notably not understood by redis-cli --slave.

Now the new protocol is used instead.
2013-02-12 12:50:28 +01:00
antirez
4b83ad4e1f Use replicationFeedSlaves() to send PING to slaves.
A Redis master sends PING commands to slaves from time to time: doing
this ensures that even if absence of writes, the master->slave channel
remains active and the slave can feel the master presence, instead of
closing the connection for timeout.

This commit changes the way PINGs are sent to slaves in order to use the
standard interface used to replicate all the other commands, that is,
the function replicationFeedSlaves().

With this change the stream of commands sent to every slave is exactly
the same regardless of their exact state (Transferring RDB for first
synchronization or slave already online). With the previous
implementation the PING was only sent to online slaves, with the result
that the output stream from master to slaves was not identical for all
the slaves: this is a problem if we want to implement partial resyncs in
the future using a global replication stream offset.

TL;DR: this commit should not change the behaviour in practical terms,
but is just something in preparation for partial resynchronization
support.
2013-02-12 12:50:28 +01:00
antirez
7465ac7ab1 Emit SELECT to slaves in a centralized way.
Before this commit every Redis slave had its own selected database ID
state. This was not actually useful as the emitted stream of commands
is identical for all the slaves.

Now the the currently selected database is a global state that is set to
-1 when a new slave is attached, in order to force the SELECT command to
be re-emitted for all the slaves.

This change is useful in order to implement replication partial
resynchronization in the future, as makes sure that the stream of
commands received by slaves, including SELECT commands, are exactly the
same for every slave connected, at any time.

In this way we could have a global offset that can identify a specific
piece of the master -> slaves stream of commands.
2013-02-12 12:50:28 +01:00
antirez
a6c2f9012f Make all WATCHers dirty when the slave reloads the DB. 2013-02-08 10:26:19 +01:00
antirez
b70b459b0e TCP_NODELAY after SYNC: changes to the implementation. 2013-02-05 12:04:30 +01:00
charsyam
c85647f354 Turn off TCP_NODELAY on the slave socket after SYNC.
Further details from @antirez:

It was reported by @StopForumSpam on Twitter that the Redis replication
link was strangely using multiple TCP packets for multiple commands.
This wastes a lot of bandwidth and is due to the TCP_NODELAY option we
enable on the socket after accepting a new connection.

However the master -> slave channel is a one-way channel since Redis
replication is asynchronous, so there is no point in trying to reduce
the latency, we should aim to reduce the bandwidth. For this reason this
commit introduces the ability to disable the nagle algorithm on the
socket after a successful SYNC.

This feature is off by default because the delay can be up to 40
milliseconds with normally configured Linux kernels.
2013-02-05 12:04:25 +01:00
guiquanz
9d09ce3981 Fixed many typos. 2013-01-19 10:59:44 +01:00
antirez
ef99e146a8 Undo slave-master handshake when SLAVEOF sets a new slave.
Issue #828 shows how Redis was not correctly undoing a non-blocking
connection attempt with the previous master when the master was set to a
new address using the SLAVEOF command.

This was also a result of lack of refactoring, so now there is a
function to cancel the non blocking handshake with the master.
The new function is now used when SLAVEOF NO ONE is called or when
SLAVEOF is used to set the master to a different address.
2013-01-15 13:33:24 +01:00
antirez
d7740fc8f3 Better error reporting when fd event creation fails. 2013-01-03 14:29:34 +01:00
antirez
f1481d4a03 serverCron() frequency is now a runtime parameter (was REDIS_HZ).
REDIS_HZ is the frequency our serverCron() function is called with.
A more frequent call to this function results into less latency when the
server is trying to handle very expansive background operations like
mass expires of a lot of keys at the same time.

Redis 2.4 used to have an HZ of 10. This was good enough with almost
every setup, but the incremental key expiration algorithm was working a
bit better under *extreme* pressure when HZ was set to 100 for Redis
2.6.

However for most users a latency spike of 30 milliseconds when million
of keys are expiring at the same time is acceptable, on the other hand a
default HZ of 100 in Redis 2.6 was causing idle instances to use some
CPU time compared to Redis 2.4. The CPU usage was in the order of 0.3%
for an idle instance, however this is a shame as more energy is consumed
by the server, if not important resources.

This commit introduces HZ as a runtime parameter, that can be queried by
INFO or CONFIG GET, and can be modified with CONFIG SET. At the same
time the default frequency is set back to 10.

In this way we default to a sane value of 10, but allows users to
easily switch to values up to 500 for near real-time applications if
needed and if they are willing to pay this small CPU usage penalty.
2012-12-14 17:10:40 +01:00
antirez
4365e5b2d3 BSD license added to every C source and header file. 2012-11-08 18:31:32 +01:00
antirez
2ea41242f6 Unix socket clients properly displayed in MONITOR and CLIENT LIST.
This also fixes issue #745.
2012-11-01 22:10:45 +01:00
antirez
f0b9f80345 "Timeout receiving bulk data" error message modified.
The new message now contains an hint about modifying the repl-timeout
configuration directive if the problem persists.

This should normally not be needed, because while the master generates
the RDB file it makes sure to send newlines to the replication channel
to prevent timeouts. However there are times when masters running on
very slow systems can completely stop for seconds during the RDB saving
process. In such a case enlarging the timeout value can fix the problem.

See issue #695 for an example of this problem in an EC2 deployment.
2012-10-04 11:52:16 +02:00
antirez
d310fbedab Fix compilation on FreeBSD. Thanks to @koobs on twitter. 2012-09-17 12:46:06 +02:00
Salvatore Sanfilippo
24bc807b5c Merge pull request #576 from saj/fix-slave-ping-period
Bug fix: slaves being pinged every second
2012-09-05 06:59:37 -07:00
antirez
bb66fc3120 Send an async PING before starting replication with master.
During the first synchronization step of the replication process, a Redis
slave connects with the master in a non blocking way. However once the
connection is established the replication continues sending the REPLCONF
command, and sometimes the AUTH command if needed. Those commands are
send in a partially blocking way (blocking with timeout in the order of
seconds).

Because it is common for a blocked master to accept connections even if
it is actually not able to reply to the slave requests, it was easy for
a slave to block if the master had serious issues, but was still able to
accept connections in the listening socket.

For this reason we now send an asynchronous PING request just after the
non blocking connection ended in a successful way, and wait for the
reply before to continue with the replication process. It is very
unlikely that a master replying to PING can't reply to the other
commands.

This solution was proposed by Didier Spezia (Thanks!) so that we don't
need to turn all the replication process into a non blocking affair, but
still the probability of a slave blocked is minimal even in the event of
a failing master.

Also we now use getsockopt(SO_ERROR) in order to check errors ASAP
in the event handler, instead of waiting for actual I/O to return an
error.

This commit fixes issue #632.
2012-09-02 12:24:38 +02:00
antirez
784b93087c Incrementally flush RDB on disk while loading it from a master.
This fixes issue #539.

Basically if there is enough free memory the OS may buffer the RDB file
that the slave transfers on disk from the master. The file may
actually be flused on disk at once by the operating system when it gets
closed by Redis, causing the close system call to block for a long time.

This patch is a modified version of one provided by yoav-steinberg of
@garantiadata (the original version was posted in the issue #539
comments), and tries to flush the OS buffers incrementally (every 8 MB
of loaded data).
2012-08-28 12:47:33 +02:00
Saj Goonatilleke
9edfe63553 Bug fix: slaves being pinged every second
REDIS_REPL_PING_SLAVE_PERIOD controls how often the master should
transmit a heartbeat (PING) to its slaves.  This period, which defaults
to 10, is measured in seconds.

Redis 2.4 masters used to ping their slaves every ten seconds, just like
it says on the tin.

The Redis 2.6 masters I have been experimenting with, on the other hand,
ping their slaves *every second*.  (master_last_io_seconds_ago never
approaches 10.)  I think the ping period was inadvertently slashed to
one-tenth of its nominal value around the time REDIS_HZ was introduced.
This commit reintroduces correct ping schedule behaviour.
2012-07-05 14:29:27 +10:00
antirez
36def8fd9a Typo in comment. 2012-06-27 11:26:44 +02:00
antirez
3a32897856 REPLCONF internal command introduced.
The REPLCONF command is an internal command (not designed to be directly
used by normal clients) that allows a slave to set some replication
related state in the master before issuing SYNC to start the
replication.

The initial motivation for this command, and the only reason currently
it is used by the implementation, is to let the slave instance
communicate its listening port to the slave, so that the master can
show all the slaves with their listening ports in the "replication"
section of the INFO output.

This allows clients to auto discover and query all the slaves attached
into a master.

Currently only a single option of the REPLCONF command is supported, and
it is called "listening-port", so the slave now starts the replication
process with something like the following chat:

    REPLCONF listening-prot 6380
    SYNC

Note that this works even if the master is an older version of Redis and
does not understand REPLCONF, because the slave ignores the REPLCONF
error.

In the future REPLCONF can be used for partial replication and other
replication related features where there is the need to exchange
information between master and slave.

NOTE: This commit also fixes a bug: the INFO outout already carried
information about slaves, but the port was broken, and was obtained
with getpeername(2), so it was actually just the ephemeral port used
by the slave to connect to the master as a client.
2012-06-27 09:43:57 +02:00
antirez
ef37997608 Dead code removed from replication.c.
The user @jokea noticed that the following line of code into
replication.c made little sense:

    addReplySds(slave,sdsempty());

Investigating a bit I found that this was introduced by commit 6208b3a7
three years ago in the early stages of Redis. The code apparently is not
useful at all, so I'm removing it.

This change will not be backported into 2.4 so that in the rare case
this should introduce a bug, we'll have a chance to detect it into the
development branch. However following the code path it seems like the
code is not useful at all, so the risk is truly small.
2012-05-24 11:35:21 +02:00
antirez
299290d3a4 Remove useless trailing space in SYNC command sent to master. 2012-05-02 21:47:53 +02:00
David Tran
31788f50b7 Spelling: s/synchrnonization/synchronization 2012-04-25 12:21:56 -07:00
antirez
9157549fad syncio.c calls in replication.c fixed for the new millisecond timeout API. 2012-03-31 11:23:30 +02:00
antirez
c2672a06cd Purely aesthetic code change. 2012-03-30 10:39:34 +02:00
Joseph Jang
f892797e1b Fixed a memory leak with replication
occurs when two or more dbs are replicated and at least one of them is >db10
2012-03-30 10:34:29 +02:00
antirez
179e54d2a9 Fix for slaves chains. Force resync of slaves (simply disconnecting them) when SLAVEOF turns a master into a slave. 2012-03-29 09:24:02 +02:00
Premysl Hruby
d194905449 use server.unixtime instead of time(NULL) where possible (cluster.c not checked though) 2012-03-27 17:39:58 +02:00
antirez
e31b615e62 Better MONITOR output, now includes client ip:port or the lua string if the command was executed by the scripting engine. 2012-03-07 12:12:15 +01:00
antirez
a950a84303 Ping the slave using the standard protocol instead of the inline one. 2012-02-29 16:33:54 +01:00
antirez
ebdfad69dc Don't change the replication state if SLAVE OF is called with arguments specifying the same master we are already connected with. This fixes issues #290. 2012-01-16 11:29:47 +01:00
antirez
1824e3a3a3 Fixed replication when multiple slaves are attaching at the same time. The output buffer was not copied correctly between slaves. This fixes issue #141. 2011-12-30 19:40:43 +01:00
antirez
1844f9900f server.replstate -> server.repl_state 2011-12-21 12:23:18 +01:00
antirez
f48cd4b90c some RDB server struct fields renamed. 2011-12-21 12:22:13 +01:00
antirez
e394114d95 AOF refactoring, now with three states: ON, OFF, WAIT_REWRITE. 2011-12-21 10:31:34 +01:00
antirez
e7a2e7c1f7 AOF fixes in the context of replicaiton (when AOF is used by slave) and CONFIG SET appendonly yes/no. 2011-12-15 16:07:49 +01:00
antirez
27acd7aa89 Replication bug fixed: now non blocking connect is also forced to follow the configured replication timeout. 2011-11-30 15:35:16 +01:00
antirez
8996bf7720 7c6da73 2011-10-31 11:13:28 +01:00
antirez
76e772f39a Return from syncWithMaster() ASAP if the event fired but the instance is no longer a slave. This should fix Issue #145. 2011-10-18 11:15:11 +02:00
antirez
45029d37cb Two fixes for replication: Slave performs the AOF rewrite at the right point. Non blocking connect also uses readable handler as with old Linux kernels like 2.6.18 on connection refused the writable even is not fired (kernel bug). 2011-06-09 15:39:12 +02:00
Pieter Noordhuis
632e4c09ac Make replication faster (biggest gain for small number of slaves) 2011-05-30 12:45:07 +02:00
Pieter Noordhuis
890a2ed989 Configurable synchronous I/O timeout 2011-05-22 12:58:18 +02:00
Pieter Noordhuis
b075621fb7 Minor changes in non-blocking repl. connect 2011-05-22 12:51:09 +02:00
Pieter Noordhuis
a330913999 Non-blocking connect with master 2011-05-19 18:54:57 +02:00
antirez
f96a9f82d8 suppress a Linux warning, for 2.2 sake 2011-02-21 17:51:52 +01:00
antirez
89a1433e69 Fixed issue #435 and at the same time introduced explicit ping in the master-slave channel that will detect a blocked master or a broken even if apparently connected TCP link. 2011-01-20 13:18:23 +01:00
Pieter Noordhuis
2b2eca1f56 Zero-pad timestamps in MONITOR output
Original report and fix:
http://code.google.com/p/redis/issues/detail?id=404
2010-12-14 17:39:34 +01:00
antirez
9fd01051bf Fix for bug 374, thanks to Jeremy Zawodny for reporting and tracing why it was crashing. 2010-11-12 20:02:20 +01:00
antirez
f6433915fe more replication info in logs 2010-11-04 18:14:20 +01:00
antirez
26b3366993 non blocking slave replication is now more non blocking than the first implementation... 2010-11-04 18:09:35 +01:00
antirez
62ec599c36 typos and minor stuff fixed in the new non blocking replication code 2010-11-04 17:35:03 +01:00
antirez
f4aa600b99 first attempt to non blocking implementation of slave replication and SYNC bulk data download. Never compiled so far... 2010-11-04 17:29:53 +01:00
antirez
19e61097c5 synchronous I/O networking functions originally used just for replication refactored in a file as generally useful, they are used in the cluster branch for MIGRATE. 2010-10-24 16:22:52 +02:00
Pieter Noordhuis
3ab203762f Use specialized function to add status and error replies 2010-09-02 23:33:06 +02:00
antirez
09252fc4f3 Fixed another instace of the Issue 173 2010-08-27 12:46:10 +02:00
antirez
b91d605a35 slave now detect lost connection during SYNC, fixing Issue 173 2010-08-24 16:25:00 +02:00
antirez
778b2210a9 slave with attached slaves now close the conection to all the slaves when the connection to the master is lost. Now a slave without a connected link to the master will refuse SYNC from other slaves. Enhanced the replication error reporting. All this will fix Issue 156 2010-08-24 16:04:13 +02:00
antirez
d3b958c3fc Fixed MONITOR output for consistency: now integer encoded values are also formatted like this: "3932" 2010-07-01 20:22:46 +02:00
antirez
e2641e09cc redis.c split into many different C files.
networking related stuff moved into networking.c

moved more code

more work on layout of source code

SDS instantaneuos memory saving. By Pieter and Salvatore at VMware ;)

cleanly compiling again after the first split, now splitting it in more C files

moving more things around... work in progress

split replication code

splitting more

Sets split

Hash split

replication split

even more splitting

more splitting

minor change
2010-07-01 14:38:51 +02:00