summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2020-05-14 10:41:28 +0200
committerantirez <antirez@gmail.com>2020-05-14 11:17:04 +0200
commita4d0720fa105b5bc8bd4a5607864862185b78105 (patch)
treefe6bcaf11e9517b997f52f36919f39c8cb58919d
parentb726d64229a58e0683925c8e8f89ab6257dddfd7 (diff)
downloadredis-a4d0720fa105b5bc8bd4a5607864862185b78105.tar.gz
Tracking: send eviction messages when evicting entries.
A fix for #7249.
-rw-r--r--src/server.c6
-rw-r--r--src/tracking.c35
2 files changed, 29 insertions, 12 deletions
diff --git a/src/server.c b/src/server.c
index e2b4b6f3d..847a6a95a 100644
--- a/src/server.c
+++ b/src/server.c
@@ -2053,6 +2053,12 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
/* Stop the I/O threads if we don't have enough pending work. */
stopThreadedIOIfNeeded();
+ /* Resize tracking keys table if needed. This is also done at every
+ * command execution, but we want to be sure that if the last command
+ * executed changes the value via CONFIG SET, the server will perform
+ * the operation even if completely idle. */
+ if (server.tracking_clients) trackingLimitUsedSlots();
+
/* Start a scheduled BGSAVE if the corresponding flag is set. This is
* useful when we are forced to postpone a BGSAVE because an AOF
* rewrite is in progress.
diff --git a/src/tracking.c b/src/tracking.c
index a995817e2..cfde26fc9 100644
--- a/src/tracking.c
+++ b/src/tracking.c
@@ -279,15 +279,22 @@ void trackingRememberKeyToBroadcast(client *c, char *keyname, size_t keylen) {
*
* Note that 'c' may be NULL in case the operation was performed outside the
* context of a client modifying the database (for instance when we delete a
- * key because of expire). */
-void trackingInvalidateKey(client *c, robj *keyobj) {
+ * key because of expire).
+ *
+ * The last argument 'bcast' tells the function if it should also schedule
+ * the key for broadcasting to clients in BCAST mode. This is the case when
+ * the function is called from the Redis core once a key is modified, however
+ * we also call the function in order to evict keys in the key table in case
+ * of memory pressure: in that case the key didn't really change, so we want
+ * just to notify the clients that are in the table for this key, that would
+ * otherwise miss the fact we are no longer tracking the key for them. */
+void trackingInvalidateKeyRaw(client *c, char *key, size_t keylen, int bcast) {
if (TrackingTable == NULL) return;
- sds sdskey = keyobj->ptr;
- if (raxSize(PrefixTable) > 0)
- trackingRememberKeyToBroadcast(c,sdskey,sdslen(sdskey));
+ if (bcast && raxSize(PrefixTable) > 0)
+ trackingRememberKeyToBroadcast(c,key,keylen);
- rax *ids = raxFind(TrackingTable,(unsigned char*)sdskey,sdslen(sdskey));
+ rax *ids = raxFind(TrackingTable,(unsigned char*)key,keylen);
if (ids == raxNotFound) return;
raxIterator ri;
@@ -317,7 +324,7 @@ void trackingInvalidateKey(client *c, robj *keyobj) {
continue;
}
- sendTrackingMessage(target,sdskey,sdslen(sdskey),0);
+ sendTrackingMessage(target,key,keylen,0);
}
raxStop(&ri);
@@ -325,7 +332,13 @@ void trackingInvalidateKey(client *c, robj *keyobj) {
* again if more keys will be modified in this caching slot. */
TrackingTableTotalItems -= raxSize(ids);
raxFree(ids);
- raxRemove(TrackingTable,(unsigned char*)sdskey,sdslen(sdskey),NULL);
+ raxRemove(TrackingTable,(unsigned char*)key,keylen,NULL);
+}
+
+/* Wrapper (the one actually called across the core) to pass the key
+ * as object. */
+void trackingInvalidateKey(client *c, robj *keyobj) {
+ trackingInvalidateKeyRaw(c,keyobj->ptr,sdslen(keyobj->ptr),1);
}
/* This function is called when one or all the Redis databases are flushed
@@ -392,10 +405,8 @@ void trackingLimitUsedSlots(void) {
effort--;
raxSeek(&ri,"^",NULL,0);
raxRandomWalk(&ri,0);
- rax *ids = ri.data;
- TrackingTableTotalItems -= raxSize(ids);
- raxFree(ids);
- raxRemove(TrackingTable,ri.key,ri.key_len,NULL);
+ if (raxEOF(&ri)) break;
+ trackingInvalidateKeyRaw(NULL,(char*)ri.key,ri.key_len,0);
if (raxSize(TrackingTable) <= max_keys) {
timeout_counter = 0;
raxStop(&ri);