diff options
author | Binbin <binloveplay1314@qq.com> | 2022-10-09 13:18:34 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-09 08:18:34 +0300 |
commit | 35b3fbd90c2ad2c503c9e3d28bfbffff13099925 (patch) | |
tree | 8ca44f6572095f44f29fcddcefb8bdac3490b806 /src/blocked.c | |
parent | d2ad01ab3e24ca537efdd1fc6ff1ae2c657f4a51 (diff) | |
download | redis-35b3fbd90c2ad2c503c9e3d28bfbffff13099925.tar.gz |
Freeze time sampling during command execution, and scripts (#10300)
Freeze time during execution of scripts and all other commands.
This means that a key is either expired or not, and doesn't change
state during a script execution. resolves #10182
This PR try to add a new `commandTimeSnapshot` function.
The function logic is extracted from `keyIsExpired`, but the related
calls to `fixed_time_expire` and `mstime()` are removed, see below.
In commands, we will avoid calling `mstime()` multiple times
and just use the one that sampled in call. The background is,
e.g. using `PEXPIRE 1` with valgrind sometimes result in the key
being deleted rather than expired. The reason is that both `PEXPIRE`
command and `checkAlreadyExpired` call `mstime()` separately.
There are other more important changes in this PR:
1. Eliminate `fixed_time_expire`, it is no longer needed.
When we want to sample time we should always use a time snapshot.
We will use `in_nested_call` instead to update the cached time in `call`.
2. Move the call for `updateCachedTime` from `serverCron` to `afterSleep`.
Now `commandTimeSnapshot` will always return the sample time, the
`lookupKeyReadWithFlags` call in `getNodeByQuery` will get a outdated
cached time (because `processCommand` is out of the `call` context).
We put the call to `updateCachedTime` in `aftersleep`.
3. Cache the time each time the module lock Redis.
Call `updateCachedTime` in `moduleGILAfterLock`, affecting `RM_ThreadSafeContextLock`
and `RM_ThreadSafeContextTryLock`
Currently the commandTimeSnapshot change affects the following TTL commands:
- SET EX / SET PX
- EXPIRE / PEXPIRE
- SETEX / PSETEX
- GETEX EX / GETEX PX
- TTL / PTTL
- EXPIRETIME / PEXPIRETIME
- RESTORE key TTL
And other commands just use the cached mstime (including TIME).
This is considered to be a breaking change since it can break a script
that uses a loop to wait for a key to expire.
Diffstat (limited to 'src/blocked.c')
-rw-r--r-- | src/blocked.c | 9 |
1 files changed, 0 insertions, 9 deletions
diff --git a/src/blocked.c b/src/blocked.c index 65b584213..c4aded0c5 100644 --- a/src/blocked.c +++ b/src/blocked.c @@ -642,14 +642,6 @@ void handleClientsBlockedOnKeys(void) { * we can safely call signalKeyAsReady() against this key. */ dictDelete(rl->db->ready_keys,rl->key); - /* Even if we are not inside call(), increment the call depth - * in order to make sure that keys are expired against a fixed - * reference time, and not against the wallclock time. This - * way we can lookup an object multiple times (BLMOVE does - * that) without the risk of it being freed in the second - * lookup, invalidating the first one. - * See https://github.com/redis/redis/pull/6554. */ - server.fixed_time_expire++; updateCachedTime(0); /* Serve clients blocked on the key. */ @@ -681,7 +673,6 @@ void handleClientsBlockedOnKeys(void) { if (server.also_propagate.numops > 0) propagatePendingCommands(); } - server.fixed_time_expire--; /* Free this item. */ decrRefCount(rl->key); |