Which Redis commands make sense inside of Multi - Exec?

396 views
Skip to first unread message

phpguru

unread,
Mar 11, 2011, 11:37:53 AM3/11/11
to Redis DB
I'm writing a PHP 5 wrapper class to the Owlient PhpRedis PHP C
extension, because, for example some commands in my application record
statistical information to syslog and I can handle it transparently in
the wrapper. First, is this a bad idea to begin with? Can syslog keep
up with Redis?

https://github.com/owlient/phpredis

What I'm curious about at the moment is the common commands used
inside of a multi exec block.

The docs for phpredis say:

"multi() returns the Redis instance and enters multi-mode. Once in
multi-mode, all subsequent method calls return the same object until
exec() is called."

So, that makes sense for chaining methods, but clearly some functions
are rarely if ever used inside the multi, like ping, exists or ssize
because you need to act on the return value (if exists, if ssize > 0
etc) immediately.

My thought was to do only functions that actually set, get or delete,
but I'm not sure I'm thinking of all the use cases I may run into. Any
suggestions?

Didier Spezia

unread,
Mar 11, 2011, 12:11:43 PM3/11/11
to Redis DB
Hi,

you may want to include all functions providing data retrieval,
data modification (set,add,insert,append,incr, etc ...),
data deletion, plus functions altering the TTL,
and functions renaming keys.

You should also exclude functions that may block.
For instance, BLPOP, BRPOP, BRPOPLPUSH are delete functions,
but you should not use them in a MULTI/EXEC block.

Actually, the list of commands not meant to be used in a
MULTI/EXEC block is probably way shorter than the list of
commands that people may use.

Regards,
Didier.

phpguru

unread,
Mar 11, 2011, 12:35:17 PM3/11/11
to Redis DB
Thanks Didier,

On Mar 11, 10:11 am, Didier Spezia <didier...@gmail.com> wrote:
> Hi,
>
> you may want to include all functions providing data retrieval,
> data modification (set,add,insert,append,incr, etc ...),
> data deletion, plus functions altering the TTL,
> and functions renaming keys.


Makes sense.


> You should also exclude functions that may block.
> For instance, BLPOP, BRPOP, BRPOPLPUSH are delete functions,
> but you should not use them in a MULTI/EXEC block.


Interesting. I can skip those, but if in multimode, what do those
functions return?
Should I discard the transaction and return FALSE?


> Actually, the list of commands not meant to be used in a
> MULTI/EXEC block is probably way shorter than the list of
> commands that people may use.


Exactly what I'm realizing. For my current case I probably need only a
handful but I was trying to make the wrapper as complete as possible.

phpguru

unread,
Mar 11, 2011, 1:14:05 PM3/11/11
to Redis DB


On Mar 11, 10:35 am, phpguru <geoffrey.hoff...@gmail.com> wrote:
> Thanks Didier,
>
> On Mar 11, 10:11 am, Didier Spezia <didier...@gmail.com> wrote:
>
> > Hi,
>
> > you may want to include all functions providing data retrieval,
> > data modification (set,add,insert,append,incr, etc ...),
> > data deletion, plus functions altering the TTL,
> > and functions renaming keys.
>
> Makes sense.
>
> > You should also exclude functions that may block.
> > For instance, BLPOP, BRPOP, BRPOPLPUSH are delete functions,
> > but you should not use them in a MULTI/EXEC block.
>
> Interesting. I can skip those, but if in multimode, what do those
> functions return?
> Should I discard the transaction and return FALSE?
>
> > Actually, the list of commands not meant to be used in a
> > MULTI/EXEC block is probably way shorter than the list of
> > commands that people may use.
>
> Exactly what I'm realizing. For my current case I probably need only a
> handful but I was trying to make the wrapper as complete as possible.


Now another thought occurs to me. I'm guessing EXEC is like commit
transaction in SQL. It doesn't do anything except it does [everything]
or [nothing]. So if the last command in a multi is a GET I'm assuming
you get the data. But what if you call GET in the middle or at the top
of a multi block?

I'm thinking of just returning $this and doing nothing (basically fail
silently) but if Redis does something different, e.g. throw an error
about `$command doesn't work in multimode` my class should handle
those cases the same way.


Didier Spezia

unread,
Mar 11, 2011, 6:45:45 PM3/11/11
to Redis DB

In a MULTI/EXEC sequence, BLPOP, BRPOP, and BRPOPLPUSH never
block, and they return nil when there is nothing to dequeue.

Regarding the semantic of MULTI/EXEC, I think comparing it
to a classical database transaction is a mistake. EXEC is not
similar to a commit, and discard is not a rollback.

Once the MULTI command is executed, all the following commands
are queued. They are not executed. They are just pending
(contrary to the behavior of a RDBMS). In case of DISCARD,
this queue of commands is simply discarded. In case of EXEC,
all the queued commands are executed at once in a single
atomic operation.

It does not matter if you have one or several get operations
in the middle of a MULTI/EXEC block. All results will be
pipelined back to the client.

For instance:

redis> set toto 1
OK
redis> set titi 2
OK
redis> set tutu 3
OK
redis> multi
OK
redis> get toto
QUEUED
redis> get titi
QUEUED
redis> get tutu
QUEUED
redis>
exec
1)
"1"
2)
"2"
3)
"3"

If one of the intermediate commands is in error,
you will get all the results in the command order,
including the error.

For instance:

redis> multi
OK
redis> get toto
QUEUED
redis> rpop toto
QUEUED
redis> get tutu
QUEUED
redis> exec
1) "1"
2) (error) ERR Operation against a key holding the wrong kind of value
3) "3"

More information here:
http://redis.io/topics/transactions

Regards,
Didier.

Jeremy Zawodny

unread,
Mar 12, 2011, 11:11:11 AM3/12/11
to redi...@googlegroups.com, phpguru
Don't laugh, but I recently had a need to do this:

MULTI
SAVE
SHUTDOWN
EXEC

And... *it worked* as I hoped. :-)

Why did I need this? Because our serves are configured w/out persistence by default (no save directives in the config file) but I had to make a config change that required a restart and didn't want to lose data. And I wanted to make sure that nothing "got in" between the SAVE and SHUTDOWN calls.

Jeremy


--
You received this message because you are subscribed to the Google Groups "Redis DB" group.
To post to this group, send email to redi...@googlegroups.com.
To unsubscribe from this group, send email to redis-db+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/redis-db?hl=en.


Dvir Volk

unread,
Mar 12, 2011, 11:19:06 AM3/12/11
to redi...@googlegroups.com, Jeremy Zawodny
that's actually very clever and useful, I'll keep it in mind, cool!
--
Dvir Volk
System Architect, Do@, http://doat.com

Geoffrey Hoffman

unread,
Mar 12, 2011, 11:31:31 AM3/12/11
to redi...@googlegroups.com


Thanks a lot for the replies -

This is making a lot more sense to me now. It changes the way I have
to handle multi mode in my wrapper class, but knowing that all GET
operations inside a MULTI return in order is much more useful than I
originally thought. (Not surprising at all considering how Redis is
designed :-) I'm hoping now I will get a PHP array back from PhpRedis,
trying your example above.

Reply all
Reply to author
Forward
0 new messages