Commit Graph

32 Commits

Author SHA1 Message Date
antirez
317f8b9d38 RESP3: most null replies converted. 2019-01-09 17:00:29 +01:00
antirez
f07f3d729f RESP3: Use new aggregate reply API in slowlog.c. 2019-01-09 17:00:29 +01:00
zhaozhao.zz
6100be7d82 fix typo 2018-12-11 19:53:54 +08:00
zhaozhao.zz
1530c0a7dd multi: ignore multiState's cmd_flags when loading AOF 2018-12-11 19:47:36 +08:00
antirez
274531396c Reject EXEC containing write commands against RO replica.
Thanks to @soloestoy for discovering this issue in #5667.
This is an alternative fix in order to avoid both cycling the clients
and also disconnecting clients just having valid read-only transactions
pending.
2018-12-11 11:39:21 +01:00
zhaozhao.zz
eb87da6127 AOF: discard if we lost EXEC when loading aof 2018-08-03 23:30:34 +08:00
antirez
e74f0aa6d1 Fix replication of SLAVEOF inside transaction.
In Redis 4.0 replication, with the introduction of PSYNC2, masters and
slaves replicate commands to cascading slaves and to the replication
backlog itself in a different way compared to the past.

Masters actually replicate the effects of client commands.
Slaves just propagate what they receive from masters.

This mechanism can cause problems when the configuration of an instance
is changed from master to slave inside a transaction. For instance
we could send to a master instance the following sequence:

    MULTI
    SLAVEOF 127.0.0.1 0
    EXEC
    SLAVEOF NO ONE

Before the fixes in this commit, the MULTI command used to be propagated
into the replication backlog, however after the SLAVEOF command the
instance is a slave, so the EXEC implementation failed to also propagate
the EXEC command. When the slaves of the above instance reconnected,
they were incrementally synchronized just sending a "MULTI". This put
the master client (in the slaves) into MULTI state, breaking the
replication.

Notably even Redis Sentinel uses the above approach in order to guarantee
that configuration changes are always performed together with rewrites
of the configuration and with clients disconnection. Sentiel does:

    MULTI
    SLAVEOF ...
    CONFIG REWRITE
    CLIENT KILL TYPE normal
    EXEC

So this was a really problematic issue. However even with the fix in
this commit, that will add the final EXEC to the replication stream in
case the instance was switched from master to slave during the
transaction, the result would be to increment the slave replication
offset, so a successive reconnection with the new master, will not
permit a successful partial resynchronization: no way the new master can
provide us with the backlog needed, we incremented our offset to a value
that the new master cannot have.

However the EXEC implementation waits to emit the MULTI, so that if the
commands inside the transaction actually do not need to be replicated,
no commands propagation happens at all. From multi.c:

    if (!must_propagate && !(c->cmd->flags & (CMD_READONLY|CMD_ADMIN))) {
	execCommandPropagateMulti(c);
	must_propagate = 1;
    }

The above code is already modified by this commit you are reading.
Now also ADMIN commands do not trigger the emission of MULTI. It is actually
not clear why we do not just check for CMD_WRITE... Probably I wrote it this
way in order to make the code more reliable: better to over-emit MULTI
than not emitting it in time.

So this commit should indeed fix issue #3836 (verified), however it looks
like some reconsideration of this code path is needed in the long term.

BONUS POINT: The reverse bug.

Even in a read only slave "B", in a replication setup like:

	A -> B -> C

There are commands without the READONLY nor the ADMIN flag, that are also
not flagged as WRITE commands. An example is just the PING command.

So if we send B the following sequence:

    MULTI
    PING
    SLAVEOF NO ONE
    EXEC

The result will be the reverse bug, where only EXEC is emitted, but not the
previous MULTI. However this apparently does not create problems in practice
but it is yet another acknowledge of the fact some work is needed here
in order to make this code path less surprising.

Note that there are many different approaches we could follow. For instance
MULTI/EXEC blocks containing administrative commands may be allowed ONLY
if all the commands are administrative ones, otherwise they could be
denined. When allowed, the commands could simply never be replicated at all.
2017-07-12 11:07:28 +02:00
antirez
32f80e2f1b RDMF: More consistent define names. 2015-07-27 14:37:58 +02:00
antirez
2d9e3eb107 RDMF: redisAssert -> serverAssert. 2015-07-26 15:29:53 +02:00
antirez
554bd0e7bd RDMF: use client instead of redisClient, like Disque. 2015-07-26 15:20:52 +02:00
antirez
cef054e868 RDMF (Redis/Disque merge friendlyness) refactoring WIP 1. 2015-07-26 15:17:18 +02:00
Matt Stancliff
da0132638f Cleanup double semicolons
Closes #1161
2014-08-08 14:54:02 +02:00
antirez
95b1979c32 No more trailing spaces in Redis source code. 2014-06-26 18:48:40 +02:00
antirez
71f3e74317 Transactions: propagate MULTI/EXEC only when needed.
MULTI/EXEC is now propagated to the AOF / Slaves only once we encounter
the first command that is not a read-only one inside the transaction.

The old behavior was to always propagate an empty MULTI/EXEC block when
the transaction was composed just of read only commands, or even
completely empty. This created two problems:

1) It's a bandwidth waste in the replication link and a space waste
   inside the AOF file.

2) We used to always increment server.dirty to force the propagation of
   the EXEC command, resulting into triggering RDB saves more often
   than needed.

Note: even read-only commands may also trigger writes that will be
propagated, when we access a key that is found expired and Redis will
synthesize a DEL operation. However there is no need for this to stay
inside the transaction itself, but only to be ordered.

So for instance something like:

    MULTI
    GET foo
    SET key zap
    EXEC

May be propagated into:

    DEL foo
    MULTI
    SET key zap
    EXEC

While the DEL is outside the transaction, the commands are delivered in
the right order and it is not possible for other commands to be inserted
between DEL and MULTI.
2013-03-26 10:58:10 +01:00
antirez
02c269e27e Transactions: use discardTransaction() in EXEC implementation. 2013-03-26 10:48:15 +01:00
antirez
2f49734029 Transactions: use the propagate() API to propagate MULTI.
The behavior is the same, but the code is now cleaner and uses the
proper interface instead of dealing directly with AOF/replication
functions.
2013-03-26 10:27:45 +01:00
antirez
078882025e PSYNC: work in progress, preview #2, rebased to unstable. 2013-02-12 12:52:21 +01:00
guiquanz
9d09ce3981 Fixed many typos. 2013-01-19 10:59:44 +01:00
antirez
3d1391272a Safer handling of MULTI/EXEC on errors.
After the transcation starts with a MULIT, the previous behavior was to
return an error on problems such as maxmemory limit reached. But still
to execute the transaction with the subset of queued commands on EXEC.

While it is true that the client was able to check for errors
distinguish QUEUED by an error reply, MULTI/EXEC in most client
implementations uses pipelining for speed, so all the commands and EXEC
are sent without caring about replies.

With this change:

1) EXEC fails if at least one command was not queued because of an
error. The EXECABORT error is used.
2) A generic error is always reported on EXEC.
3) The client DISCARDs the MULTI state after a failed EXEC, otherwise
pipelining multiple transactions would be basically impossible:
After a failed EXEC the next transaction would be simply queued as
the tail of the previous transaction.
2012-11-22 10:32:07 +01:00
antirez
4365e5b2d3 BSD license added to every C source and header file. 2012-11-08 18:31:32 +01:00
antirez
a1b1c1ea3a Fix MULTI / EXEC rendering in MONITOR output.
Before of this commit it used to be like this:

MULTI
EXEC
... actual commands of the transaction ...

Because after all that is the natural order of things. Transaction
commands are queued and executed *only after* EXEC is called.

However this makes debugging with MONITOR a mess, so the code was
modified to provide a coherent output.

What happens is that MULTI is rendered in the MONITOR output as far as
possible, instead EXEC is propagated only after the transaction is
executed, or even in the case it fails because of WATCH, so in this case
you'll simply see:

MULTI
EXEC

An empty transaction.
2012-10-16 17:35:50 +02:00
antirez
f3fd419fc9 Support for read-only slaves. Semantical fixes.
This commit introduces support for read only slaves via redis.conf and CONFIG GET/SET commands. Also various semantical fixes are implemented here:

1) MULTI/EXEC with only read commands now work where the server is into a state where writes (or commands increasing memory usage) are not allowed. Before this patch everything inside a transaction would fail in this conditions.

2) Scripts just calling read-only commands will work against read only
slaves, when the server is out of memory, or when persistence is into an
error condition. Before the patch EVAL always failed in this condition.
2012-03-20 17:32:48 +01:00
antirez
ce8b772be7 Now Lua scripts dispatch Redis commands properly calling the call() function. In order to make this possible call() was improved with a new flags argument that controls how the Redis command is executed. 2012-02-02 16:30:52 +01:00
antirez
e394114d95 AOF refactoring, now with three states: ON, OFF, WAIT_REWRITE. 2011-12-21 10:31:34 +01:00
woowenjie
f371e721fa clean REDIS_DIRTY_CAS when discard Command runs. otherwise the next MULTI/EXEC may fail in the same RedisClient 2011-11-25 10:34:05 +08:00
antirez
eab0e26e03 replaced redisAssert() with redisAssertWithInfo() in a shitload of places. 2011-10-04 18:43:03 +02:00
antirez
09e2d9eeba Take a pointer to the relevant entry of the command table in the client structure. This is generally a more sounding design, simplifies a few functions prototype, and as a side effect fixes a bug related to the conversion of EXPIRE -1 to DEL: before of this fix Redis tried to convert it into an EXPIREAT in the AOF code, regardless of our rewrite of the command. 2011-07-08 12:59:30 +02:00
Pieter Noordhuis
6c682e559c Restore argc/argv in EXEC after command is executed 2011-02-23 14:37:22 +01:00
antirez
1b1f47c915 command lookup process turned into a much more flexible and probably faster hash table 2010-11-03 11:23:59 +01:00
Pieter Noordhuis
3ab203762f Use specialized function to add status and error replies 2010-09-02 23:33:06 +02:00
Pieter Noordhuis
0537e7bf80 Use specialized function to add multi bulk reply length 2010-09-02 12:51:14 +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