Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions commands/delifeq.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
Deletes the key if its value matches the given string.

This command is typically used to safely release locks in distributed systems, ensuring that only the owner of the lock (as identified by the value) can delete it.

If the key exists and the stored value is a string that exactly matches the provided value, the key is removed and `1` is returned. Otherwise, the key is left unchanged and `0` is returned.

## Examples

Basic usage:

```
127.0.0.1:6379> SET mykey abc123
OK
127.0.0.1:6379> DELIFEQ mykey abc123
(integer) 1
127.0.0.1:6379> DELIFEQ mykey abc123
(integer) 0
```

Wrong value:

```
127.0.0.1:6379> SET mykey xyz789
OK
127.0.0.1:6379> DELIFEQ mykey abc123
(integer) 0
```

Wrong type:

```
127.0.0.1:6379> SADD mykey somevalue
(integer) 1
127.0.0.1:6379> DELIFEQ mykey somevalue
(error) WRONGTYPE Operation against a key holding the wrong kind of value
```

## Use case: Safe lock release

`DELIFEQ` enables an atomic check-and-delete operation to safely release a lock only if the process still holds it. This avoids race conditions where a lock might expire and be claimed by another process before the original owner tries to delete it.

This pattern is commonly used as part of distributed locking systems like [Redlock](../topics/distlock.md), which previously relied on Lua scripting to implement this logic. With `DELIFEQ`, such a use case becomes more robust and idiomatic.

Instead of:

```
EVAL "if redis.call('GET',KEYS[1]) == ARGV[1] then return redis.call('DEL',KEYS[1]) else return 0 end" 1 mykey abc123
```

You can now use:

```
DELIFEQ mykey abc123
```

## See also

* [`SET IFEQ`](set.md) - Sets the key only if it matches the given value.
4 changes: 4 additions & 0 deletions commands/set.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,7 @@ An example of unlock script would be similar to the following:
end

The script should be called with `EVAL ...script... 1 resource-name token-value`

## See also

* [`DELIFEQ`](delifeq.md) - Deletes the key if its value matches the given string.
5 changes: 5 additions & 0 deletions resp2_replies.json
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,11 @@
"DEL": [
"[Integer reply](../topics/protocol.md#integers): the number of keys that were removed."
],
"DELIFEQ": [
"One of the following:",
"* [Integer reply](../topics/protocol.md#integers): `1` if the key was deleted.",
"* [Integer reply](../topics/protocol.md#integers): `0` if the key was not deleted because it did not exist or the value was not equal to the provided value."
],
"DISCARD": [
"[Simple string reply](../topics/protocol.md#simple-strings): `OK`."
],
Expand Down
5 changes: 5 additions & 0 deletions resp3_replies.json
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,11 @@
"DEL": [
"[Integer reply](../topics/protocol.md#integers): the number of keys that were removed."
],
"DELIFEQ": [
"One of the following:",
"* [Integer reply](../topics/protocol.md#integers): `1` if the key was deleted.",
"* [Integer reply](../topics/protocol.md#integers): `0` if the key was not deleted because it did not exist or the value was not equal to the provided value."
],
"DISCARD": [
"[Simple string reply](../topics/protocol.md#simple-strings): `OK`."
],
Expand Down
8 changes: 7 additions & 1 deletion topics/distlock.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,13 @@ To acquire the lock, the way to go is the following:
The command will set the key only if it does not already exist (`NX` option), with an expire of 30000 milliseconds (`PX` option).
The key is set to a value “my\_random\_value”. This value must be unique across all clients and all lock requests.

Basically the random value is used in order to release the lock in a safe way, with a script that tells Valkey: remove the key only if it exists and the value stored at the key is exactly the one I expect to be. This is accomplished by the following Lua script:
Basically the random value is used in order to release the lock in a safe way, with a script that tells Valkey: remove the key only if it exists and the value stored at the key is exactly the one I expect to be.

In Valkey 9.0.0 and later, this can be done atomically using the built-in DELIFEQ command:

DELIFEQ resource_name my_random_value

In earlier versions of Valkey, the same behavior can be achieved using a Lua script:

if server.call("get",KEYS[1]) == ARGV[1] then
return server.call("del",KEYS[1])
Expand Down