Combination of Redis MULTI\EXEC && EVAL. is this valid?

797 views
Skip to first unread message

Maxim Ternovenko

unread,
Mar 21, 2014, 8:32:19 AM3/21/14
to redi...@googlegroups.com
Hi!

I'm saving my objects (for example Users) in redis by LUA script in an atomic way with EVAL command ( in "user" example I'm checking that username is unique && than save user);

Now I need to save few users in a batch and be sure that all users a saved in transaction ( eg if I need to save user1 && user2 in a batch and if I have redis crash between user1 and user2 save operation ( sure this can happen with redis only if server os is killed ;) )  none of the users will be saved;

So is it a good idea to combine MULTI\EXEC && EVAL commands together to achieve this behavior? 
I have test this scenario and looks like it works as expected but I have never see that someone use this...

To test this I use the following: 
to start redis:
redis-server --appendfsync always --appendonly yes

var script1 = 'redis.call("set",1,1);';
var script2 = 'return redis.call("set",1,2);';
multi.EVAL(script1,0);
multi.DEBUG("SEGFAULT");
multi.EVAL(script2,0);
multi.EXEC();


Many thanks for your time && help!
--
Max

Josiah Carlson

unread,
Mar 23, 2014, 2:08:33 AM3/23/14
to redi...@googlegroups.com
I don't believe there is anything necessarily wrong with MULTI + EVAL + EXEC, as the group will be sent to the AOF or to slaves in one chunk.

But what are you gaining in this situation by sending a group of account creates in that way? Why not just write a single Lua script that can handle bulk additions?

 - Josiah

--
You received this message because you are subscribed to the Google Groups "Redis DB" group.
To unsubscribe from this group and stop receiving emails from it, send an email to redis-db+u...@googlegroups.com.
To post to this group, send email to redi...@googlegroups.com.
Visit this group at http://groups.google.com/group/redis-db.
For more options, visit https://groups.google.com/d/optout.

Maxim Ternovenko

unread,
Mar 23, 2014, 5:00:08 AM3/23/14
to redi...@googlegroups.com
Thanks for reply Josiah!

it was a simple example with users and not make a lot of sence... in real life - I use redis as primary db and have one generic Lua script ( some sort of very simple ORM or OM) that handle update\create of all my objects\classes in redis.
Now I need to save \ update few of classes in transaction. My users for posting Some Actions gaine "score"  and if they gain some score I should also create an 'achievement' object - it is important to be sure that Action & Score & Achievement goes in transaction so if server goes down none of them will be saved; 

It is possible to create additional script for this case but it will be code duplication that I want to avoid.
With MULTI + EXEC looks like I can reuse my script as function multiple in atomic way;

Josiah Carlson

unread,
Mar 23, 2014, 10:04:32 PM3/23/14
to redi...@googlegroups.com
While it's not documented, you can call existing Lua scripts from other scripts. The issue you run into is that if you want to pass custom arguments to the function, you either have to use the standard Redis keyspace to communicate between the functions, or you need to mangle your KEYS and ARGV, as they are globals and not passed as part of the function.

127.0.0.1:6379> script load "return {KEYS[1], ARGV[1]}"
"d006f1a90249474274c76f5be725b8f5804a346b"
127.0.0.1:6379> eval "return f_d006f1a90249474274c76f5be725b8f5804a346b()" 1 "hello" "world"
1) "hello"
2) "world"

I've got more information on a StackExchange thread I just updated with the same answer: http://stackoverflow.com/a/22599862/490681 .


In your situation, it feels like the right answer to just execute multiple Lua scripts inside a MULTI/EXEC transaction.

Regards,
 - Josiah

tw-bert

unread,
Mar 23, 2014, 10:47:19 PM3/23/14
to redi...@googlegroups.com
Hi Josiah,

Great news, I'm the poster of the original wrong answer at the SO thread which you refer to.
Any chance of getting this documented? So it won't break with future versions of Redis? It makes things a lot easier for our uses.
Even with Redis Cluster, if you make sure all Lua scripts are loaded at server startup (which we do already btw), I can't immediately see anything wrong with your approach.

Kind regards, TW

Maxim Ternovenko

unread,
Mar 24, 2014, 5:39:56 AM3/24/14
to redi...@googlegroups.com
Nice tip, Josiah!

Probably not helpful for me now (as u mention);
But it is definitely nice to know that this option is there!

I will stick with MULTI&EVAL pattern and if I will face some issue will update this;

Thank you for help!

Maxim Ternovenko

unread,
Mar 24, 2014, 5:36:18 AM3/24/14
to redi...@googlegroups.com
Nice tip, Josiah!

Probably not helpful for me now (as u mention);
But it is definitely nice to know that this option is there!

I will stick with MULTI&EVAL pattern and if I will face some issue will update this;

Thank you for help!
You received this message because you are subscribed to a topic in the Google Groups "Redis DB" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/redis-db/XDfEVnJuGYc/unsubscribe.
To unsubscribe from this group and all its topics, send an email to redis-db+u...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages