diff --git a/content/commands/bless-clear.md b/content/commands/bless-clear.md new file mode 100644 index 0000000000..970fd7ca05 --- /dev/null +++ b/content/commands/bless-clear.md @@ -0,0 +1,120 @@ +--- +acl_categories: +- '@keyspace' +- '@write' +- '@fast' +arguments: +- display_text: key + key_spec_index: 0 + name: key + type: key +- display_text: no-evict + name: no-evict + token: NO-EVICT + type: pure-token +arity: 4 +categories: +- docs +- develop +- stack +- oss +- rs +- rc +- oss +- kubernetes +- clients +command_flags: +- write +- fast +complexity: O(1) +description: Removes protection flags from a key. +group: generic +hidden: false +key_specs: +- RW: true + begin_search: + spec: + index: 2 + type: index + find_keys: + spec: + keystep: 1 + lastkey: 0 + limit: 0 + type: range +linkTitle: BLESS CLEAR +railroad_diagram: /images/railroad/bless-clear.svg +since: 8.12.0 +summary: Removes protection flags from a key. +syntax_fmt: BLESS CLEAR key NO-EVICT +title: BLESS CLEAR +--- +`BLESS CLEAR` removes a protection flag from a key, making it eligible again for eviction. The key must already exist. + +## Required arguments + +
key + +The name of the key to unprotect. The key must already exist, or the command returns an error. + +
+ +
NO-EVICT + +The protection flag to remove. `NO-EVICT` is currently the only supported flag. + +
+ +## Details + +### Behavior + +- `BLESS CLEAR` is idempotent: it returns `1` the first time the flag is removed from a key, and `0` on later calls if the key didn't carry that flag. +- Unlike [`BLESS SET`]({{< relref "/commands/bless-set" >}}), `BLESS CLEAR` isn't blocked when the server is out of memory, so protection can always be removed to free up eviction candidates. +- `BLESS CLEAR` generates an `unbless` [keyspace notification]({{< relref "/develop/pubsub/keyspace-notifications" >}}) event. +- Clearing the flag persists across restarts and replicates like any other write. + +## Examples + +{{% redis-cli %}} +redis> BLESS SET session:42 NO-EVICT +(integer) 1 +redis> BLESS CLEAR session:42 NO-EVICT +(integer) 1 +redis> BLESS CLEAR session:42 NO-EVICT +(integer) 0 +redis> BLESS CLEAR missing-key NO-EVICT +(error) ERR no such key +{{% /redis-cli %}} + +## Redis Software and Redis Cloud compatibility + +| Redis
Software | Redis
Cloud | Notes | +|:----------------------|:-----------------|:------| +| ❌ Standard
❌ Active-Active | ❌ Standard
❌ Active-Active | | + +## Return information + +{{< multitabs id="return-info" + tab1="RESP2" + tab2="RESP3" >}} + +One of the following: +* [Integer reply]({{< relref "/develop/reference/protocol-spec#integers" >}}): `1` if the flag was removed, `0` if the key didn't have it. +* [Simple error reply]({{< relref "/develop/reference/protocol-spec#simple-errors" >}}) if the key doesn't exist. + +-tab-sep- + +One of the following: +* [Integer reply]({{< relref "/develop/reference/protocol-spec#integers" >}}): `1` if the flag was removed, `0` if the key didn't have it. +* [Simple error reply]({{< relref "/develop/reference/protocol-spec#simple-errors" >}}) if the key doesn't exist. + +{{< /multitabs >}} + +## See also + +[`BLESS SET`]({{< relref "/commands/bless-set" >}}) | [`BLESS GET`]({{< relref "/commands/bless-get" >}}) | [`BLESS SCAN`]({{< relref "/commands/bless-scan" >}}) + +## Related topics + +- [Key eviction]({{< relref "/develop/reference/eviction" >}}) diff --git a/content/commands/bless-get.md b/content/commands/bless-get.md new file mode 100644 index 0000000000..d328c66a0f --- /dev/null +++ b/content/commands/bless-get.md @@ -0,0 +1,105 @@ +--- +acl_categories: +- '@keyspace' +- '@fast' +arguments: +- display_text: key + key_spec_index: 0 + name: key + type: key +arity: 3 +categories: +- docs +- develop +- stack +- oss +- rs +- rc +- oss +- kubernetes +- clients +command_flags: +- fast +complexity: O(1). +description: Returns the active protection flags of a key. +group: generic +hidden: false +key_specs: +- RO: true + begin_search: + spec: + index: 2 + type: index + find_keys: + spec: + keystep: 1 + lastkey: 0 + limit: 0 + type: range +linkTitle: BLESS GET +railroad_diagram: /images/railroad/bless-get.svg +since: 8.12.0 +summary: Returns the active protection flags of a key. +syntax_fmt: BLESS GET key +title: BLESS GET +--- +`BLESS GET` returns the eviction-protection flags currently set on a key. The key must already exist. + +## Required arguments + +
key + +The name of the key to inspect. The key must already exist, or the command returns an error. + +
+ +## Details + +`BLESS GET` returns an empty array if the key exists but has no protection flags. `NO-EVICT` is currently the only flag `BLESS` defines. + +## Examples + +{{% redis-cli %}} +redis> SET session:42 "some value" +OK +redis> BLESS GET session:42 +(empty array) +redis> BLESS SET session:42 NO-EVICT +(integer) 1 +redis> BLESS GET session:42 +1) "NO-EVICT" +redis> BLESS GET missing-key +(error) ERR no such key +{{% /redis-cli %}} + +## Redis Software and Redis Cloud compatibility + +| Redis
Software | Redis
Cloud | Notes | +|:----------------------|:-----------------|:------| +| ❌ Standard
❌ Active-Active | ❌ Standard
❌ Active-Active | | + +## Return information + +{{< multitabs id="return-info" + tab1="RESP2" + tab2="RESP3" >}} + +One of the following: +* [Array reply]({{< relref "/develop/reference/protocol-spec#arrays" >}}) of the key's active protection flags, empty if none are set. +* [Simple error reply]({{< relref "/develop/reference/protocol-spec#simple-errors" >}}) if the key doesn't exist. + +-tab-sep- + +One of the following: +* [Array reply]({{< relref "/develop/reference/protocol-spec#arrays" >}}) of the key's active protection flags, empty if none are set. +* [Simple error reply]({{< relref "/develop/reference/protocol-spec#simple-errors" >}}) if the key doesn't exist. + +{{< /multitabs >}} + +## See also + +[`BLESS SET`]({{< relref "/commands/bless-set" >}}) | [`BLESS CLEAR`]({{< relref "/commands/bless-clear" >}}) | [`BLESS SCAN`]({{< relref "/commands/bless-scan" >}}) + +## Related topics + +- [Key eviction]({{< relref "/develop/reference/eviction" >}}) diff --git a/content/commands/bless-scan.md b/content/commands/bless-scan.md new file mode 100644 index 0000000000..ece9c11116 --- /dev/null +++ b/content/commands/bless-scan.md @@ -0,0 +1,122 @@ +--- +acl_categories: +- '@keyspace' +- '@slow' +arguments: +- display_text: cursor + name: cursor + type: integer +- display_text: no-evict + name: no-evict + token: NO-EVICT + type: pure-token +- display_text: count + name: count + optional: true + token: COUNT + type: integer +arity: -4 +categories: +- docs +- develop +- stack +- oss +- rs +- rc +- oss +- kubernetes +- clients +complexity: O(1) for every call. O(N) for a complete iteration, where N is the number + of blessed keys. +description: Incrementally iterates the blessed keys of the current database that + carry the given flag. +group: generic +hidden: false +hints: +- nondeterministic_output +- request_policy:special +- response_policy:special +linkTitle: BLESS SCAN +railroad_diagram: /images/railroad/bless-scan.svg +since: 8.12.0 +summary: Incrementally iterates the blessed keys of the current database that carry + the given flag. +syntax_fmt: "BLESS SCAN cursor NO-EVICT [COUNT\_count]" +title: BLESS SCAN +--- +`BLESS SCAN` incrementally iterates the blessed keys of the current database that carry the given protection flag, using the same cursor-based protocol as [`SCAN`]({{< relref "/commands/scan" >}}). + +## Required arguments + +
cursor + +The cursor value. Start an iteration with `0`, then use the cursor returned by each call as the argument to the next call. + +
+ +
NO-EVICT + +The protection flag to filter by. `NO-EVICT` is currently the only supported flag, and this argument is required. + +
+ +## Optional arguments + +
COUNT count + +A hint for the number of keys to visit per iteration. The default is 1024. + +
+ +## Details + +`BLESS SCAN` follows the same cursor semantics and iteration guarantees as [`SCAN`]({{< relref "/commands/scan" >}}): a full iteration, from cursor `0` until the returned cursor is `0` again, is guaranteed to return every key that carried the given flag for the entire duration of the iteration. `COUNT` is only a hint, and a key may be returned more than once during a full iteration. + +## Examples + +{{% redis-cli %}} +redis> SET session:42 "some value" +OK +redis> SET cache:100 "some value" +OK +redis> BLESS SET session:42 NO-EVICT +(integer) 1 +redis> BLESS SET cache:100 NO-EVICT +(integer) 1 +redis> BLESS SCAN 0 NO-EVICT +1) "0" +2) 1) "cache:100" + 2) "session:42" +{{% /redis-cli %}} + +## Redis Software and Redis Cloud compatibility + +| Redis
Software | Redis
Cloud | Notes | +|:----------------------|:-----------------|:------| +| ❌ Standard
❌ Active-Active | ❌ Standard
❌ Active-Active | | + +## Return information + +{{< multitabs id="return-info" + tab1="RESP2" + tab2="RESP3" >}} + +[Array reply]({{< relref "/develop/reference/protocol-spec#arrays" >}}): specifically, an array with two elements. +* The first element is a [Bulk string reply]({{< relref "/develop/reference/protocol-spec#bulk-strings" >}}) that represents an unsigned 64-bit number, the cursor. +* The second element is an [Array reply]({{< relref "/develop/reference/protocol-spec#arrays" >}}) with the names of the scanned keys. + +-tab-sep- + +[Array reply]({{< relref "/develop/reference/protocol-spec#arrays" >}}): specifically, an array with two elements. +* The first element is a [Bulk string reply]({{< relref "/develop/reference/protocol-spec#bulk-strings" >}}) that represents an unsigned 64-bit number, the cursor. +* The second element is an [Array reply]({{< relref "/develop/reference/protocol-spec#arrays" >}}) with the names of the scanned keys. + +{{< /multitabs >}} + +## See also + +[`BLESS SET`]({{< relref "/commands/bless-set" >}}) | [`BLESS CLEAR`]({{< relref "/commands/bless-clear" >}}) | [`BLESS GET`]({{< relref "/commands/bless-get" >}}) + +## Related topics + +- [Key eviction]({{< relref "/develop/reference/eviction" >}}) diff --git a/content/commands/bless-set.md b/content/commands/bless-set.md new file mode 100644 index 0000000000..1fe48da9df --- /dev/null +++ b/content/commands/bless-set.md @@ -0,0 +1,123 @@ +--- +acl_categories: +- '@keyspace' +- '@write' +- '@fast' +arguments: +- display_text: key + key_spec_index: 0 + name: key + type: key +- display_text: no-evict + name: no-evict + token: NO-EVICT + type: pure-token +arity: 4 +categories: +- docs +- develop +- stack +- oss +- rs +- rc +- oss +- kubernetes +- clients +command_flags: +- write +- denyoom +- fast +complexity: O(1) +description: Adds protection flags to a key against memory pressure. +group: generic +hidden: false +key_specs: +- RW: true + begin_search: + spec: + index: 2 + type: index + find_keys: + spec: + keystep: 1 + lastkey: 0 + limit: 0 + type: range +linkTitle: BLESS SET +railroad_diagram: /images/railroad/bless-set.svg +since: 8.12.0 +summary: Adds protection flags to a key against memory pressure. +syntax_fmt: BLESS SET key NO-EVICT +title: BLESS SET +--- +`BLESS SET` marks a key so that Redis skips it when choosing candidates for eviction under memory pressure. The key must already exist. + +## Required arguments + +
key + +The name of the key to protect. The key must already exist, or the command returns an error. + +
+ +
NO-EVICT + +The protection flag to add. `NO-EVICT` is currently the only supported flag. + +
+ +## Details + +### Behavior + +- `BLESS SET` is idempotent: it returns `1` the first time the flag is added to a key, and `0` on later calls if the key already carries that flag. +- A blessed key is skipped as an eviction candidate under every `maxmemory-policy` value. See [Protecting keys from eviction]({{< relref "/develop/reference/eviction#bless" >}}) for how this interacts with the `maxmemory` limit. +- `BLESS SET` generates a `bless` [keyspace notification]({{< relref "/develop/pubsub/keyspace-notifications" >}}) event. +- `BLESS SET` can itself be blocked with an out-of-memory error under the same conditions as any other write command. [`BLESS CLEAR`]({{< relref "/commands/bless-clear" >}}) isn't subject to this, so you can always remove protection to free up eviction candidates. +- The flag isn't included in [`DUMP`]({{< relref "/commands/dump" >}}) output, and [`RESTORE`]({{< relref "/commands/restore" >}}) doesn't set it on the restored key. If `RESTORE` targets a key that's already blessed and uses `REPLACE`, the destination key keeps its existing protection. +- The flag persists across restarts and replicates like any other write. + +## Examples + +{{% redis-cli %}} +redis> SET session:42 "some value" +OK +redis> BLESS SET session:42 NO-EVICT +(integer) 1 +redis> BLESS SET session:42 NO-EVICT +(integer) 0 +redis> BLESS SET missing-key NO-EVICT +(error) ERR no such key +{{% /redis-cli %}} + +## Redis Software and Redis Cloud compatibility + +| Redis
Software | Redis
Cloud | Notes | +|:----------------------|:-----------------|:------| +| ❌ Standard
❌ Active-Active | ❌ Standard
❌ Active-Active | | + +## Return information + +{{< multitabs id="return-info" + tab1="RESP2" + tab2="RESP3" >}} + +One of the following: +* [Integer reply]({{< relref "/develop/reference/protocol-spec#integers" >}}): `1` if the flag was added, `0` if the key already had it. +* [Simple error reply]({{< relref "/develop/reference/protocol-spec#simple-errors" >}}) if the key doesn't exist. + +-tab-sep- + +One of the following: +* [Integer reply]({{< relref "/develop/reference/protocol-spec#integers" >}}): `1` if the flag was added, `0` if the key already had it. +* [Simple error reply]({{< relref "/develop/reference/protocol-spec#simple-errors" >}}) if the key doesn't exist. + +{{< /multitabs >}} + +## See also + +[`BLESS CLEAR`]({{< relref "/commands/bless-clear" >}}) | [`BLESS GET`]({{< relref "/commands/bless-get" >}}) | [`BLESS SCAN`]({{< relref "/commands/bless-scan" >}}) + +## Related topics + +- [Key eviction]({{< relref "/develop/reference/eviction" >}}) diff --git a/content/commands/bless.md b/content/commands/bless.md new file mode 100644 index 0000000000..7ac95a9085 --- /dev/null +++ b/content/commands/bless.md @@ -0,0 +1,33 @@ +--- +acl_categories: +- '@slow' +arity: -2 +categories: +- docs +- develop +- stack +- oss +- rs +- rc +- oss +- kubernetes +- clients +complexity: Depends on subcommand. +description: A container for key-blessing commands. +group: generic +hidden: true +linkTitle: BLESS +railroad_diagram: /images/railroad/bless.svg +since: 8.12.0 +summary: A container for key-blessing commands. +syntax_fmt: BLESS +title: BLESS +--- +This is a container command for commands that protect keys from eviction. + +The `BLESS` command has the following subcommands: + +* [`BLESS SET`]({{< relref "/commands/bless-set" >}}) protects a key from eviction. +* [`BLESS CLEAR`]({{< relref "/commands/bless-clear" >}}) removes eviction protection from a key. +* [`BLESS GET`]({{< relref "/commands/bless-get" >}}) returns a key's active protection flags. +* [`BLESS SCAN`]({{< relref "/commands/bless-scan" >}}) iterates the keys that carry a given protection flag. diff --git a/content/commands/info.md b/content/commands/info.md index dfc8c100a3..0798aace22 100644 --- a/content/commands/info.md +++ b/content/commands/info.md @@ -341,6 +341,7 @@ Here is the meaning of all fields in the **stats** section: * `expired_time_cap_reached_count`: The count of times that active expiry cycles have stopped early * `expire_cycle_cpu_milliseconds`: The cumulative amount of time spent on active expiry cycles * `evicted_keys`: Number of evicted keys due to `maxmemory` limit +* `blessed_keys`: Number of keys currently protected from eviction, see [`BLESS`]({{< relref "/commands/bless" >}}). Added in Redis 8.12. * `evicted_clients`: Number of evicted clients due to `maxmemory-clients` limit. Added in Redis 7.0. * `evicted_scripts`: Number of evicted EVAL scripts due to LRU policy, see [`EVAL`]({{< relref "/commands/eval" >}}) for more details. Added in Redis 7.4. * `total_eviction_exceeded_time`: Total time `used_memory` was greater than `maxmemory` since server startup, in milliseconds diff --git a/content/commands/memory-stats.md b/content/commands/memory-stats.md index f042ca6698..3b4ff07e8a 100644 --- a/content/commands/memory-stats.md +++ b/content/commands/memory-stats.md @@ -52,9 +52,11 @@ values. The following metrics are reported: * `functions.caches`: the summed size in bytes of the overheads of the Function scripts' caches * `hash.templates`: Total memory in bytes used by all compact hash templates (see [`INFO`]({{< relref "/commands/info" >}})'s `used_memory_hash_templates`). Added in Redis 8.10. -* `dbXXX`: For each of the server's databases, the overheads of the main and - expiry dictionaries (`overhead.hashtable.main` and - `overhead.hashtable.expires`, respectively) are reported in bytes +* `dbXXX`: For each of the server's databases, the overheads of the main, + expiry, and [blessed-key]({{< relref "/commands/bless" >}}) dictionaries + (`overhead.hashtable.main`, `overhead.hashtable.expires`, and + `overhead.hashtable.blessed`, respectively) are reported in bytes. + `overhead.hashtable.blessed` was added in Redis 8.12. * `overhead.db.hashtable.lut`: Total overhead of dictionary buckets in databases (Added in Redis 7.4) * `overhead.db.hashtable.rehashing`: Temporary memory overhead of database dictionaries currently being rehashed (Added in Redis 7.4) * `overhead.total`: The sum of all overheads, i.e. `startup.allocated`, diff --git a/content/develop/reference/eviction/index.md b/content/develop/reference/eviction/index.md index 12e391462a..8f37589fe6 100644 --- a/content/develop/reference/eviction/index.md +++ b/content/develop/reference/eviction/index.md @@ -190,6 +190,8 @@ Other useful pieces of information returned by `INFO` include: is the amount by which `maxmemory` has been exceeded. - `current_eviction_exceeded_time`: (`stats` section) The time since the cache last started to exceed `maxmemory`. +- `blessed_keys`: (`stats` section) The number of keys currently + [protected from eviction](#bless). - `commandstats` section: Among other things, this reports the number of times each command issued to the server has been rejected. If you are using `noeviction` or one of the `volatile_xxx` policies, you can use @@ -320,3 +322,37 @@ To configure LRM eviction, the following policies are available: * `allkeys-lrm` Evict any key using LRM. Like LRU, LRM uses an approximation algorithm that samples a small number of keys at random and evicts the ones with the longest time since last modification. The same `maxmemory-samples` configuration directive that affects LRU performance also applies to LRM. + +## Protecting keys from eviction {#bless} + +Starting with Redis 8.12, you can protect individual keys from eviction with the +[`BLESS SET`]({{< relref "/commands/bless-set" >}}) and +[`BLESS CLEAR`]({{< relref "/commands/bless-clear" >}}) commands, regardless of the +configured `maxmemory-policy`. Use [`BLESS GET`]({{< relref "/commands/bless-get" >}}) +to check a key's protection status, and [`BLESS SCAN`]({{< relref "/commands/bless-scan" >}}) +to iterate the protected keys in the current database. + +``` +> SET session:42 "some value" +OK +> BLESS SET session:42 NO-EVICT +(integer) 1 +``` + +A protected key is never chosen as an eviction candidate, whichever eviction policy +is active (`allkeys-lru`, `allkeys-lfu`, `allkeys-random`, or any `volatile-xxx` +variant). This means it's possible to protect enough keys that Redis can't free +enough memory to satisfy `maxmemory` through eviction alone. When that happens, Redis +tolerates some overshoot: writes keep succeeding until `used_memory` would exceed +1.25 times `maxmemory`, and only then start failing with the usual out-of-memory +error. This overshoot tolerance applies uniformly across every `maxmemory-policy` +value. + +The [`INFO`]({{< relref "/commands/info" >}}) command reports the total number of +protected keys as `blessed_keys` in the `stats` section, and +[`MEMORY STATS`]({{< relref "/commands/memory-stats" >}}) reports the per-database +dictionary overhead of tracking them as `overhead.hashtable.blessed`. + +See [`BLESS SET`]({{< relref "/commands/bless-set" >}}) for how protection persists +across restarts and interacts with [`DUMP`]({{< relref "/commands/dump" >}}) and +[`RESTORE`]({{< relref "/commands/restore" >}}). diff --git a/content/operate/rs/references/compatibility/commands/generic.md b/content/operate/rs/references/compatibility/commands/generic.md index 3f50301b3a..40f9f67067 100644 --- a/content/operate/rs/references/compatibility/commands/generic.md +++ b/content/operate/rs/references/compatibility/commands/generic.md @@ -15,6 +15,10 @@ The following table shows which Redis Open Source [key (generic) commands]({{< r | Command | Redis
Software | Redis
Cloud | Notes | |:--------|:----------------------|:-----------------|:------| +| [BLESS CLEAR]({{< relref "/commands/bless-clear" >}}) | ❌ Standard
❌ Active-Active | ❌ Standard
❌ Active-Active | | +| [BLESS GET]({{< relref "/commands/bless-get" >}}) | ❌ Standard
❌ Active-Active | ❌ Standard
❌ Active-Active | | +| [BLESS SCAN]({{< relref "/commands/bless-scan" >}}) | ❌ Standard
❌ Active-Active | ❌ Standard
❌ Active-Active | | +| [BLESS SET]({{< relref "/commands/bless-set" >}}) | ❌ Standard
❌ Active-Active | ❌ Standard
❌ Active-Active | | | [COPY]({{< relref "/commands/copy" >}}) | ✅ Standard
✅ Active-Active\* | ✅ Standard
✅ Active-Active\* | For Active-Active or clustered databases, the source and destination keys must be in the same hash slot.

\*Not supported for stream consumer group info. | | [DEL]({{< relref "/commands/del" >}}) | ✅ Standard
✅ Active-Active | ✅ Standard
✅ Active-Active | | | [DUMP]({{< relref "/commands/dump" >}}) | ✅ Standard
✅ Active-Active | ✅ Standard
✅ Active-Active | | diff --git a/static/images/railroad/bless-clear.svg b/static/images/railroad/bless-clear.svg new file mode 100644 index 0000000000..acfdf3b8ed --- /dev/null +++ b/static/images/railroad/bless-clear.svg @@ -0,0 +1,50 @@ + + + + + + + + +BLESS CLEAR +key +NO-EVICT \ No newline at end of file diff --git a/static/images/railroad/bless-get.svg b/static/images/railroad/bless-get.svg new file mode 100644 index 0000000000..7b460ed56b --- /dev/null +++ b/static/images/railroad/bless-get.svg @@ -0,0 +1,49 @@ + + + + + + + + +BLESS GET +key \ No newline at end of file diff --git a/static/images/railroad/bless-scan.svg b/static/images/railroad/bless-scan.svg new file mode 100644 index 0000000000..dcf655fa8a --- /dev/null +++ b/static/images/railroad/bless-scan.svg @@ -0,0 +1,55 @@ + + + + + + + + +BLESS SCAN +cursor +NO-EVICT + + + +COUNT +count \ No newline at end of file diff --git a/static/images/railroad/bless-set.svg b/static/images/railroad/bless-set.svg new file mode 100644 index 0000000000..3278e20dae --- /dev/null +++ b/static/images/railroad/bless-set.svg @@ -0,0 +1,50 @@ + + + + + + + + +BLESS SET +key +NO-EVICT \ No newline at end of file diff --git a/static/images/railroad/bless.svg b/static/images/railroad/bless.svg new file mode 100644 index 0000000000..7cfacb819c --- /dev/null +++ b/static/images/railroad/bless.svg @@ -0,0 +1,47 @@ + + + + + + + +BLESS \ No newline at end of file