Unverified Commit fa48fb2d authored by uriyage's avatar uriyage Committed by GitHub
Browse files

Do not watch keys for dirty client (#9829)



Currently, the watching clients are marked as dirty when a watched
key is touched, but we continue watching the keys for no reason.
Then, when the same key is touched again, we iterate again on the
watching clients list and mark all clients as dirty again.
Only when the exec/unwatch command is issued will the client be
removed from the key->watching_clients list. The same applies when
a dirty client calls the WATCH command. The key will be added to be
watched by the client even if it has no effect.

In the field, no performance degradation was observed as a result of the
current implementation; it is merely a cleanup with possible memory and
performance gains in some situations.
Co-authored-by: default avatarOran Agra <oran@redislabs.com>
parent 9630ded3
...@@ -397,6 +397,10 @@ void touchWatchedKey(redisDb *db, robj *key) { ...@@ -397,6 +397,10 @@ void touchWatchedKey(redisDb *db, robj *key) {
client *c = listNodeValue(ln); client *c = listNodeValue(ln);
c->flags |= CLIENT_DIRTY_CAS; c->flags |= CLIENT_DIRTY_CAS;
/* As the client is marked as dirty, there is no point in getting here
* again in case that key (or others) are modified again (or keep the
* memory overhead till EXEC). */
unwatchAllKeys(c);
} }
} }
...@@ -426,6 +430,9 @@ void touchAllWatchedKeysInDb(redisDb *emptied, redisDb *replaced_with) { ...@@ -426,6 +430,9 @@ void touchAllWatchedKeysInDb(redisDb *emptied, redisDb *replaced_with) {
while((ln = listNext(&li))) { while((ln = listNext(&li))) {
client *c = listNodeValue(ln); client *c = listNodeValue(ln);
c->flags |= CLIENT_DIRTY_CAS; c->flags |= CLIENT_DIRTY_CAS;
/* As the client is marked as dirty, there is no point in getting here
* again for others keys (or keep the memory overhead till EXEC). */
unwatchAllKeys(c);
} }
} }
} }
...@@ -439,6 +446,11 @@ void watchCommand(client *c) { ...@@ -439,6 +446,11 @@ void watchCommand(client *c) {
addReplyError(c,"WATCH inside MULTI is not allowed"); addReplyError(c,"WATCH inside MULTI is not allowed");
return; return;
} }
/* No point in watching if the client is already dirty. */
if (c->flags & CLIENT_DIRTY_CAS) {
addReply(c,shared.ok);
return;
}
for (j = 1; j < c->argc; j++) for (j = 1; j < c->argc; j++)
watchForKey(c,c->argv[j]); watchForKey(c,c->argv[j]);
addReply(c,shared.ok); addReply(c,shared.ok);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment