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.
This commit is contained in:
antirez
2013-06-24 18:57:31 +02:00
parent 9d894b1b8c
commit 545fe0c318
5 changed files with 59 additions and 21 deletions

View File

@ -655,6 +655,10 @@ void scriptingInit(void) {
* to global variables. */
scriptingEnableGlobalsProtection(lua);
/* Initialize the Replication Script Cache for EVALSHA propagation to
* slaves and AOF. */
replicationScriptCacheInit();
server.lua = lua;
}
@ -931,23 +935,29 @@ void evalGenericCommand(redisClient *c, int evalsha) {
luaReplyToRedisReply(c,lua);
}
/* If we have slaves attached we want to replicate this command as
* EVAL instead of EVALSHA. We do this also in the AOF as currently there
* is no easy way to propagate a command in a different way in the AOF
* and in the replication link.
/* EVALSHA should be propagated to Slave and AOF file as full EVAL, unless
* we are sure that the script was already in the context of all the
* attached slaves *and* the current AOF file if enabled.
*
* IMPROVEMENT POSSIBLE:
* 1) Replicate this command as EVALSHA in the AOF.
* 2) Remember what slave already received a given script, and replicate
* the EVALSHA against this slaves when possible.
*/
* To do so we use a cache of SHA1s of scripts that we already propagated
* as full EVAL, that's called the Replication Script Cache.
*
* For repliation, everytime a new slave attaches to the master, we need to
* flush our cache of scripts that can be replicated as EVALSHA, while
* for AOF we need to do so every time we rewrite the AOF file. */
if (evalsha) {
robj *script = dictFetchValue(server.lua_scripts,c->argv[1]->ptr);
if (!replicationScriptCacheExists(c->argv[1]->ptr)) {
/* This script is not in our script cache, replicate it as
* EVAL, then add it into the script cache, as from now on
* slaves and AOF know about it. */
robj *script = dictFetchValue(server.lua_scripts,c->argv[1]->ptr);
redisAssertWithInfo(c,NULL,script != NULL);
rewriteClientCommandArgument(c,0,
resetRefCount(createStringObject("EVAL",4)));
rewriteClientCommandArgument(c,1,script);
replicationScriptCacheAdd(c->argv[1]->ptr);
redisAssertWithInfo(c,NULL,script != NULL);
rewriteClientCommandArgument(c,0,
resetRefCount(createStringObject("EVAL",4)));
rewriteClientCommandArgument(c,1,script);
}
}
}