Skip to content

Commit f8ae991

Browse files
authored
EXISTS should not alter LRU, OBJECT should not reveal expired keys on replica (#8016)
The bug was introduced by #5021 which only attempted avoid EXIST on an already expired key from returning 1 on a replica. Before that commit, dbExists was used instead of lookupKeyRead (which had an undesired effect to "touch" the LRU/LFU) Other than that, this commit fixes OBJECT to also come empty handed on expired keys in replica. And DEBUG DIGEST-VALUE to behave like DEBUG OBJECT (get the data from the key regardless of it's expired state)
1 parent d87a0d0 commit f8ae991

5 files changed

Lines changed: 21 additions & 19 deletions

File tree

src/db.c

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,8 @@ robj *lookupKeyReadWithFlags(redisDb *db, robj *key, int flags) {
102102
/* Key expired. If we are in the context of a master, expireIfNeeded()
103103
* returns 0 only when the key does not exist at all, so it's safe
104104
* to return NULL ASAP. */
105-
if (server.masterhost == NULL) {
106-
server.stat_keyspace_misses++;
107-
notifyKeyspaceEvent(NOTIFY_KEY_MISS, "keymiss", key, db->id);
108-
return NULL;
109-
}
105+
if (server.masterhost == NULL)
106+
goto keymiss;
110107

111108
/* However if we are in the context of a slave, expireIfNeeded() will
112109
* not really try to expire the key, it only returns information
@@ -125,19 +122,21 @@ robj *lookupKeyReadWithFlags(redisDb *db, robj *key, int flags) {
125122
server.current_client->cmd &&
126123
server.current_client->cmd->flags & CMD_READONLY)
127124
{
128-
server.stat_keyspace_misses++;
129-
notifyKeyspaceEvent(NOTIFY_KEY_MISS, "keymiss", key, db->id);
130-
return NULL;
125+
goto keymiss;
131126
}
132127
}
133128
val = lookupKey(db,key,flags);
134-
if (val == NULL) {
129+
if (val == NULL)
130+
goto keymiss;
131+
server.stat_keyspace_hits++;
132+
return val;
133+
134+
keymiss:
135+
if (!(flags & LOOKUP_NONOTIFY)) {
135136
server.stat_keyspace_misses++;
136137
notifyKeyspaceEvent(NOTIFY_KEY_MISS, "keymiss", key, db->id);
137138
}
138-
else
139-
server.stat_keyspace_hits++;
140-
return val;
139+
return NULL;
141140
}
142141

143142
/* Like lookupKeyReadWithFlags(), but does not use any flag, which is the
@@ -592,7 +591,7 @@ void existsCommand(client *c) {
592591
int j;
593592

594593
for (j = 1; j < c->argc; j++) {
595-
if (lookupKeyRead(c->db,c->argv[j])) count++;
594+
if (lookupKeyReadWithFlags(c->db,c->argv[j],LOOKUP_NOTOUCH)) count++;
596595
}
597596
addReplyLongLong(c,count);
598597
}

src/debug.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -644,7 +644,11 @@ NULL
644644
for (int j = 2; j < c->argc; j++) {
645645
unsigned char digest[20];
646646
memset(digest,0,20); /* Start with a clean result */
647-
robj *o = lookupKeyReadWithFlags(c->db,c->argv[j],LOOKUP_NOTOUCH);
647+
648+
/* We don't use lookupKey because a debug command should
649+
* work on logically expired keys */
650+
dictEntry *de;
651+
robj *o = ((de = dictFind(c->db->dict,c->argv[j]->ptr)) == NULL) ? NULL : dictGetVal(de);
648652
if (o) xorObjectDigest(c->db,c->argv[j],digest,o);
649653

650654
sds d = sdsempty();

src/object.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1229,10 +1229,7 @@ int objectSetLRUOrLFU(robj *val, long long lfu_freq, long long lru_idle,
12291229
/* This is a helper function for the OBJECT command. We need to lookup keys
12301230
* without any modification of LRU or other parameters. */
12311231
robj *objectCommandLookup(client *c, robj *key) {
1232-
dictEntry *de;
1233-
1234-
if ((de = dictFind(c->db->dict,key->ptr)) == NULL) return NULL;
1235-
return (robj*) dictGetVal(de);
1232+
return lookupKeyReadWithFlags(c->db,key,LOOKUP_NOTOUCH|LOOKUP_NONOTIFY);
12361233
}
12371234

12381235
robj *objectCommandLookupOrReply(client *c, robj *key, robj *reply) {

src/server.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2179,6 +2179,7 @@ int objectSetLRUOrLFU(robj *val, long long lfu_freq, long long lru_idle,
21792179
long long lru_clock, int lru_multiplier);
21802180
#define LOOKUP_NONE 0
21812181
#define LOOKUP_NOTOUCH (1<<0)
2182+
#define LOOKUP_NONOTIFY (1<<1)
21822183
void dbAdd(redisDb *db, robj *key, robj *val);
21832184
int dbAddRDBLoad(redisDb *db, sds key, robj *val);
21842185
void dbOverwrite(redisDb *db, robj *key, robj *val);

tests/unit/introspection-2.tcl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@ proc cmdstat {cmd} {
33
}
44

55
start_server {tags {"introspection"}} {
6-
test {TTL and TYPYE do not alter the last access time of a key} {
6+
test {TTL, TYPE and EXISTS do not alter the last access time of a key} {
77
r set foo bar
88
after 3000
99
r ttl foo
1010
r type foo
11+
r exists foo
1112
assert {[r object idletime foo] >= 2}
1213
}
1314

0 commit comments

Comments
 (0)