title: CLUSTER MIGRATION

summary: Start, monitor, and cancel atomic slot migration tasks.

title: Overview

text: The `CLUSTER MIGRATION` command provides atomic slot migration functionality for Redis Cluster. This command allows you to import slots from other nodes, monitor the progress of migration tasks, and cancel ongoing migrations.

title: Required arguments

text:
subcommand

The subcommand specifies the operation to perform:

- `IMPORT <start-slot> <end-slot> [<start-slot> <end-slot> ...]`: Executes on the destination master. Accepts multiple slot ranges and triggers atomic migration for the specified ranges. Returns a task ID that you can use to monitor the status of the task.

- `CANCEL <ID <task-id> | ALL>`: Cancels an ongoing migration task by its ID or cancels all tasks if `ALL` is specified. Note: Cancelling a task on the source node does not stop the migration on the destination node, which will continue retrying until it is also cancelled there.

- `STATUS [ID <task-id> | ALL]`: Displays the status of current and completed atomic slot migration tasks. If a specific task ID is provided, it returns detailed information for that task only. If `ALL` is specified, it returns the status of all ongoing and completed tasks.

title: Examples

text:
Import slots 0-1000 and 2000-3000 to the current node:

[code example]

Check the status of all migration tasks:

[code example]

Check the status of a specific migration task:

[code example]

Cancel a specific migration task:

[code example]

Cancel all migration tasks:

[code example]

title: Return information

text:
**RESP2:**

For the `IMPORT` subcommand:
[Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): task ID on success, or error message on failure.

For the `CANCEL` subcommand:
[Integer reply](../../develop/reference/protocol-spec#integers): number of cancelled tasks.

For the `STATUS` subcommand:
[Array reply](../../develop/reference/protocol-spec#arrays): a list of migration task details. Each task is represented as an array containing field-value pairs:
- `id`: Task identifier
- `slots`: Slot range being imported or migrated
- `source`: Source node ID
- `dest`: Destination node ID
- `operation`: Operation type ("import" or "migrate")
- `state`: Current state ("completed", "in_progress", etc.)
- `last_error`: Last error message (empty if none)
- `retries`: Number of retry attempts
- `create_time`: Task creation timestamp
- `start_time`: Task start timestamp
- `end_time`: Task completion timestamp (if completed)
- `write_pause_ms`: Write pause duration in milliseconds

**RESP3:**

For the `IMPORT` subcommand:
[Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): task ID on success, or error message on failure.

For the `CANCEL` subcommand:
[Integer reply](../../develop/reference/protocol-spec#integers): number of cancelled tasks.

For the `STATUS` subcommand:
[Array reply](../../develop/reference/protocol-spec#arrays): a list of migration task details. Each task is represented as an array containing field-value pairs:
- `id`: Task identifier
- `slots`: Slot range being migrated
- `source`: Source node ID
- `dest`: Destination node ID
- `operation`: Operation type (typically "migrate")
- `state`: Current state ("completed", "in_progress", etc.)
- `last_error`: Last error message (empty if none)
- `retries`: Number of retry attempts
- `create_time`: Task creation timestamp
- `start_time`: Task start timestamp
- `end_time`: Task completion timestamp (if completed)
- `write_pause_ms`: Write pause duration in milliseconds

title: Notes

text:
- The atomic slot migration feature is available starting from Redis 8.4.0.
- Cancelling a task on the source node does not automatically stop the migration on the destination node.
- In `CLUSTER MIGRATION STATUS` output, the "state" field will show `completed` for successful operations.
- Tasks with empty "last_error" fields indicate no errors occurred during the migration process.

title: Key visibility during migration

text:
During atomic slot migration operations, keys in unowned slots may be filtered out from the following commands while importing or trimming is in progress:

- [`KEYS`]()
- [`SCAN`]()
- [`RANDOMKEY`]()
- [`CLUSTER GETKEYSINSLOT`]()
- [`DBSIZE`]()
- [`CLUSTER COUNTKEYSINSLOT`]()

The [`INFO KEYSPACE`]() command will continue to reflect the actual number of keys, including those being imported.

title: Related configuration

role: related

text:
- `cluster-slot-migration-handoff-max-lag-bytes`: After slot snapshot completion, if remaining replication stream size falls below this threshold, the source node pauses writes to hand off slot ownership. Higher values trigger handoff earlier but may cause longer write pauses. Lower values result in shorter write pauses but may be harder to reach with steady incoming writes (default: 1MB).
- `cluster-slot-migration-write-pause-timeout`: Maximum duration that the source node pauses writes during ASM handoff. If the destination fails to take over slots within this timeout, the source assumes migration failed and resumes writes (default: 10 seconds).

code: CLUSTER MIGRATION IMPORT 0 1000 2000 3000

code: CLUSTER MIGRATION STATUS ALL

code: CLUSTER MIGRATION STATUS ID 24cf41718b20f7f05901743dffc40bc9b15db339

code: CLUSTER MIGRATION CANCEL ID 24cf41718b20f7f05901743dffc40bc9b15db339

code: CLUSTER MIGRATION CANCEL ALL


title: CLUSTER MYID

summary: Returns the ID of a node.

page_type: content

title: Overview

role: overview

text:
Returns the node's id.

The `CLUSTER MYID` command returns the unique, auto-generated identifier that is associated with the connected cluster node.

title: Redis Software and Redis Cloud compatibility

role: content

text:
| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ❌ Standard
<nobr>❌ Active-Active</nobr> | ❌ Standard
<nobr>❌ Active-Active</nobr> |  |

title: Return information

role: returns

text:
**RESP2:**

[Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): the node ID.

**RESP3:**

[Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): the node ID.


title: CLUSTER MYSHARDID

summary: Returns the shard ID of a node.

title: Overview

text:
Returns the node's shard id.

The `CLUSTER MYSHARDID` command returns the unique, auto-generated identifier that is associated with the shard to which the connected cluster node belongs.

title: Return information

text:
**RESP2:**

[Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): the node's shard ID.

**RESP3:**

[Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): the node's shard ID.


title: CLUSTER NODES

summary: Returns the cluster configuration for a node.

title: Overview

text:
Each node in a Redis Cluster has its view of the current cluster configuration,
given by the set of known nodes, the state of the connection we have with such
nodes, their flags, properties and assigned slots, and so forth.

`CLUSTER NODES` provides all this information, that is, the current cluster
configuration of the node we are contacting, in a serialization format which
happens to be exactly the same as the one used by Redis Cluster itself in
order to store on disk the cluster state (however the on disk cluster state
has a few additional info appended at the end).

Note that normally clients willing to fetch the map between Cluster
hash slots and node addresses should use [`CLUSTER SHARDS`]() instead.
`CLUSTER NODES`, that provides more information, should be used for
administrative tasks, debugging, and configuration inspections.
It is also used by `redis-cli` in order to manage a cluster.

title: Serialization format

text:
The output of the command is just a space-separated CSV string, where
each line represents a node in the cluster. The following
is an example of output on Redis 7.2.0.

[code example]

Each line is composed of the following fields:

[code example]

The meaning of each field is the following:

1. `id`: The node ID, a 40-character globally unique string generated when a node is created and never changed again (unless `CLUSTER RESET HARD` is used).
2. `ip:port@cport`: The node address that clients should contact to run queries, along with the used cluster bus port.
   `:0@0` can be expected when the address is no longer known for this node ID, hence flagged with `noaddr`.
3. `hostname`: A human readable string that can be configured via the `cluster-annouce-hostname` setting. The max length of the string is 256 characters, excluding the null terminator. The name can contain ASCII alphanumeric characters, '-', and '.' only.
5. `flags`: A list of comma separated flags: `myself`, `master`, `slave`, `fail?`, `fail`, `handshake`, `noaddr`, `nofailover`, `noflags`. Flags are explained below.
6. `master`: If the node is a replica, and the primary is known, the primary node ID, otherwise the "-" character.
7. `ping-sent`: Unix time at which the currently active ping was sent, or zero if there are no pending pings, in milliseconds.
8. `pong-recv`: Unix time the last pong was received, in milliseconds.
9. `config-epoch`: The configuration epoch (or version) of the current node (or of the current primary if the node is a replica). Each time there is a failover, a new, unique, monotonically increasing configuration epoch is created. If multiple nodes claim to serve the same hash slots, the one with the higher configuration epoch wins.
10. `link-state`: The state of the link used for the node-to-node cluster bus. Use this link to communicate with the node. Can be `connected` or `disconnected`.
11. `slot`: A hash slot number or range. Starting from argument number 9, but there may be up to 16384 entries in total (limit never reached). This is the list of hash slots served by this node. If the entry is just a number, it is parsed as such.  If it is a range, it is in the form `start-end`, and means that the node is responsible for all the hash slots from `start` to `end` including the start and end values.

Flags are:

* `myself`: The node you are contacting.
* `master`: Node is a primary.
* `slave`: Node is a replica.
* `fail?`: Node is in `PFAIL` state. Not reachable for the node you are contacting, but still logically reachable (not in `FAIL` state).
* `fail`: Node is in `FAIL` state. It was not reachable for multiple nodes that promoted the `PFAIL` state to `FAIL`.
* `handshake`: Untrusted node, we are handshaking.
* `noaddr`: No address known for this node.
* `nofailover`: Replica will not try to failover.
* `noflags`: No flags at all.

title: Notes on published config epochs

text:
Replicas broadcast their primary's config epochs (in order to get an `UPDATE`
message if they are found to be stale), so the real config epoch of the
replica (which is meaningless more or less, since they don't serve hash slots)
can be only obtained checking the node flagged as `myself`, which is the entry
of the node we are asking to generate `CLUSTER NODES` output. The other
replicas epochs reflect what they publish in heartbeat packets, which is, the
configuration epoch of the primaries they are currently replicating.

title: Special slot entries

text:
Normally hash slots associated to a given node are in one of the following formats,
as already explained above:

1. Single number: 3894
2. Range: 3900-4000

However node hash slots can be in a special state, used in order to communicate errors after a node restart (mismatch between the keys in the AOF/RDB file, and the node hash slots configuration), or when there is a resharding operation in progress. This two states are **importing** and **migrating**.

The meaning of the two states is explained in the Redis Specification, however the gist of the two states is the following:

* **Importing** slots are yet not part of the nodes hash slot, there is a migration in progress. The node will accept queries about these slots only if the `ASK` command is used.
* **Migrating** slots are assigned to the node, but are being migrated to some other node. The node will accept queries if all the keys in the command exist already, otherwise it will emit what is called an **ASK redirection**, to force new keys creation directly in the importing node.

Importing and migrating slots are emitted in the `CLUSTER NODES` output as follows:

* **Importing slot:** `[slot_number-<-importing_from_node_id]`
* **Migrating slot:** `[slot_number->-migrating_to_node_id]`

The following are a few examples of importing and migrating slots:

* `[93-<-292f8b365bb7edb5e285caf0b7e6ddc7265d2f4f]`
* `[1002-<-67ed2db8d677e59ec4a4cefb06858cf2a1a89fa1]`
* `[77->-e7d1eecce10fd6bb5eb35b9f99a514335d9ba9ca]`
* `[16311->-292f8b365bb7edb5e285caf0b7e6ddc7265d2f4f]`

Note that the format does not have any space, so `CLUSTER NODES` output format is plain CSV with space as separator even when this special slots are emitted. However a complete parser for the format should be able to handle them.

Note that:

1. Migration and importing slots are only added to the node flagged as `myself`. This information is local to a node, for its own slots.
2. Importing and migrating slots are provided as **additional info**. If the node has a given hash slot assigned, it will be also a plain number in the list of hash slots, so clients that don't have a clue about hash slots migrations can just skip this special fields.

**A note about the word slave used in this man page and command name**: Starting with Redis 5, if not for backward compatibility, the Redis project no longer uses the word slave. Unfortunately in this command the word slave is part of the protocol, so we'll be able to remove such occurrences only when this API will be naturally deprecated.

text:
| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ✅ Standard
<nobr>✅ Active-Active</nobr> | ✅ Standard
<nobr>✅ Active-Active</nobr> | Only supported with the [OSS cluster API](). |

title: Return information

text:
**RESP2:**

[Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): the serialized cluster configuration.

**RESP3:**

[Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): the serialized cluster configuration.

section_id: serialization-format

code: <id> <ip:port@cport[,hostname]> <flags> <master> <ping-sent> <pong-recv> <config-epoch> <link-state> <slot> <slot> ... <slot>


title: CLUSTER REPLICAS

summary: Lists the replica nodes of a master node.

title: Overview

text:
The command provides a list of replica nodes replicating from the specified
master node. The list is provided in the same format used by [`CLUSTER NODES`]() (please refer to its documentation for the specification of the format).

The command will fail if the specified node is not known or if it is not
a master according to the node table of the node receiving the command.

Note that if a replica is added, moved, or removed from a given master node,
and we ask `CLUSTER REPLICAS` to a node that has not yet received the
configuration update, it may show stale information. However eventually
(in a matter of seconds if there are no network partitions) all the nodes
will agree about the set of nodes associated with a given master.

title: Return information

text:
**RESP2:**

[Array reply](../../develop/reference/protocol-spec#arrays): a list of replica nodes replicating from the specified master node provided in the same format used by `CLUSTER NODES`.

**RESP3:**

[Array reply](../../develop/reference/protocol-spec#arrays): a list of replica nodes replicating from the specified master node provided in the same format used by `CLUSTER NODES`.


title: CLUSTER REPLICATE

summary: Configure a node as replica of a master node.

title: Overview

text:
The command reconfigures a node as a replica of the specified master.
If the node receiving the command is an *empty master*, as a side effect
of the command, the node role is changed from master to replica.

Once a node is turned into the replica of another master node, there is no need
to inform the other cluster nodes about the change: heartbeat packets exchanged
between nodes will propagate the new configuration automatically.

A replica will always accept the command, assuming that:

1. The specified node ID exists in its nodes table.
2. The specified node ID does not identify the instance we are sending the command to.
3. The specified node ID is a master.

If the node receiving the command is not already a replica, but is a master,
the command will only succeed, and the node will be converted into a replica,
only if the following additional conditions are met:

1. The node is not serving any hash slots.
2. The node is empty, no keys are stored at all in the key space.

If the command succeeds the new replica will immediately try to contact its master in order to replicate from it.

title: Return information

text:
**RESP2:**

[Simple string reply](../../develop/reference/protocol-spec#simple-strings): `OK` if the command was successful. Otherwise an error is returned.

**RESP3:**

[Simple string reply](../../develop/reference/protocol-spec#simple-strings): `OK` if the command was successful. Otherwise an error is returned.


title: CLUSTER RESET

summary: Resets a node.

title: Overview

text:
Reset a Redis Cluster node, in a more or less drastic way depending on the
reset type, that can be **hard** or **soft**. Note that this command
**does not work for masters if they hold one or more keys**, in that case
to completely reset a master node keys must be removed first, e.g. by using [`FLUSHALL`]() first,
and then `CLUSTER RESET`.

Effects on the node:

1. All the other nodes in the cluster are forgotten.
2. All the assigned / open slots are reset, so the slots-to-nodes mapping is totally cleared.
3. If the node is a replica it is turned into an (empty) master. Its dataset is flushed, so at the end the node will be an empty master.
4. **Hard reset only**: a new Node ID is generated.
5. **Hard reset only**: `currentEpoch` and `configEpoch` vars are set to 0.
6. The new configuration is persisted on disk in the node cluster configuration file.

This command is mainly useful to re-provision a Redis Cluster node
in order to be used in the context of a new, different cluster. The command
is also extensively used by the Redis Cluster testing framework in order to
reset the state of the cluster every time a new test unit is executed.

If no reset type is specified, the default is **soft**.

title: Return information


title: CLUSTER SAVECONFIG

summary: Forces a node to save the cluster configuration to disk.

title: Overview

text:
Forces a node to save the `nodes.conf` configuration on disk. Before to return
the command calls `fsync(2)` in order to make sure the configuration is
flushed on the computer disk.

This command is mainly used in the event a `nodes.conf` node state file
gets lost / deleted for some reason, and we want to generate it again from
scratch. It can also be useful in case of mundane alterations of a node cluster
configuration via the [`CLUSTER`]() command in order to ensure the new configuration
is persisted on disk, however all the commands should normally be able to
auto schedule to persist the configuration on disk when it is important
to do so for the correctness of the system in the event of a restart.

title: Return information


title: CLUSTER SET-CONFIG-EPOCH

summary: Sets the configuration epoch for a new node.

title: Overview

text:
This command sets a specific *config epoch* in a fresh node. It only works when:

1. The nodes table of the node is empty.
2. The node current *config epoch* is zero.

These prerequisites are needed since usually, manually altering the
configuration epoch of a node is unsafe, we want to be sure that the node with
the higher configuration epoch value (that is the last that failed over) wins
over other nodes in claiming the hash slots ownership.

However there is an exception to this rule, and it is when a new
cluster is created from scratch. Redis Cluster *config epoch collision
resolution* algorithm can deal with new nodes all configured with the
same configuration at startup, but this process is slow and should be
the exception, only to make sure that whatever happens, two more
nodes eventually always move away from the state of having the same
configuration epoch.

So, using `CLUSTER SET-CONFIG-EPOCH`, when a new cluster is created, we can
assign a different progressive configuration epoch to each node before
joining the cluster together.


title: CLUSTER SETSLOT

summary: Binds a hash slot to a node.

title: Overview

text:
`CLUSTER SETSLOT` is responsible of changing the state of a hash slot in the receiving node in different ways. It can, depending on the subcommand used:

1. `MIGRATING` subcommand: Set a hash slot in *migrating* state.
2. `IMPORTING` subcommand: Set a hash slot in *importing* state.
3. `STABLE` subcommand: Clear any importing / migrating state from hash slot.
4. `NODE` subcommand: Bind the hash slot to a different node.

The command with its set of subcommands is useful in order to start and end cluster live resharding operations, which are accomplished by setting a hash slot in migrating state in the source node, and importing state in the destination node.

Each subcommand is documented below. At the end you'll find a description of
how live resharding is performed using this command and other related commands.

title: CLUSTER SETSLOT `<slot>` MIGRATING `<destination-node-id>`

text:
This subcommand sets a slot to *migrating* state. In order to set a slot
in this state, the node receiving the command must be the hash slot owner,
otherwise an error is returned.

When a slot is set in migrating state, the node changes behavior in the
following way:

1. If a command is received about an existing key, the command is processed as usually.
2. If a command is received about a key that does not exists, an `ASK` redirection is emitted by the node, asking the client to retry only that specific query into `destination-node`. In this case the client should not update its hash slot to node mapping.
3. If the command contains multiple keys, in case none exist, the behavior is the same as point 2, if all exist, it is the same as point 1, however if only a partial number of keys exist, the command emits a `TRYAGAIN` error in order for the keys interested to finish being migrated to the target node, so that the multi keys command can be executed.

title: CLUSTER SETSLOT `<slot>` IMPORTING `<source-node-id>`

text:
This subcommand is the reverse of `MIGRATING`, and prepares the destination
node to import keys from the specified source node. The command only works if
the node is not already owner of the specified hash slot.

When a slot is set in importing state, the node changes behavior in the following way:

1. Commands about this hash slot are refused and a `MOVED` redirection is generated as usually, but in the case the command follows an [`ASKING`]() command, in this case the command is executed.

In this way when a node in migrating state generates an `ASK` redirection, the client contacts the target node, sends [`ASKING`](), and immediately after sends the command. This way commands about non-existing keys in the old node or keys already migrated to the target node are executed in the target node, so that:

1. New keys are always created in the target node. During a hash slot migration we'll have to move only old keys, not new ones.
2. Commands about keys already migrated are correctly processed in the context of the node which is the target of the migration, the new hash slot owner, in order to guarantee consistency.
3. Without [`ASKING`]() the behavior is the same as usually. This guarantees that clients with a broken hash slots mapping will not write for error in the target node, creating a new version of a key that has yet to be migrated.

title: CLUSTER SETSLOT `<slot>` STABLE

text:
This subcommand just clears migrating / importing state from the slot. It is
mainly used to fix a cluster stuck in a wrong state by `redis-cli --cluster fix`.
Normally the two states are cleared automatically at the end of the migration
using the `SETSLOT ... NODE ...` subcommand as explained in the next section.

title: CLUSTER SETSLOT `<slot>` NODE `<node-id>`

text:
The `NODE` subcommand is the one with the most complex semantics. It
associates the hash slot with the specified node, however the command works
only in specific situations and has different side effects depending on the
slot state. The following is the set of pre-conditions and side effects of the
command:

1. If the current hash slot owner is the node receiving the command, but for effect of the command the slot would be assigned to a different node, the command will return an error if there are still keys for that hash slot in the node receiving the command.
2. If the slot is in *migrating* state, the state gets cleared when the slot is assigned to another node.
3. If the slot was in *importing* state in the node receiving the command, and the command assigns the slot to this node (which happens in the target node at the end of the resharding of a hash slot from one node to another), the command has the following side effects: A) the *importing* state is cleared. B) If the node config epoch is not already the greatest of the cluster, it generates a new one and assigns the new config epoch to itself. This way its new hash slot ownership will win over any past configuration created by previous failovers or slot migrations.

It is important to note that step 3 is the only time when a Redis Cluster node will create a new config epoch without agreement from other nodes. This only happens when a manual configuration is operated. However it is impossible that this creates a non-transient setup where two nodes have the same config epoch, since Redis Cluster uses a config epoch collision resolution algorithm.

title: Redis Cluster live resharding explained

text:
The `CLUSTER SETSLOT` command is an important piece used by Redis Cluster in order to migrate all the keys contained in one hash slot from one node to another. This is how the migration is orchestrated, with the help of other commands as well. We'll call the node that has the current ownership of the hash slot the `source` node, and the node where we want to migrate the `destination` node.

1. Set the destination node slot to *importing* state using `CLUSTER SETSLOT <slot> IMPORTING <source-node-id>`.
2. Set the source node slot to *migrating* state using `CLUSTER SETSLOT <slot> MIGRATING <destination-node-id>`.
3. Get keys from the source node with [`CLUSTER GETKEYSINSLOT`]() command and move them into the destination node using the [`MIGRATE`]() command.
4. Send `CLUSTER SETSLOT <slot> NODE <destination-node-id>` to the destination node.
5. Send `CLUSTER SETSLOT <slot> NODE <destination-node-id>` to the source node.
6. Send `CLUSTER SETSLOT <slot> NODE <destination-node-id>` to the other master nodes (optional).

Notes:

* The order of step 1 and 2 is important. We want the destination node to be ready to accept `ASK` redirections when the source node is configured to redirect.
* The order of step 4 and 5 is important.
  The destination node is responsible for propagating the change to the rest of the cluster.
  If the source node is informed before the destination node and the destination node crashes before it is set as new slot owner, the slot is left with no owner, even after a successful failover.
* Step 6, sending `SETSLOT` to the nodes not involved in the resharding, is not technically necessary since the configuration will eventually propagate itself.
  However, it is a good idea to do so in order to stop nodes from pointing to the wrong node for the hash slot moved as soon as possible, resulting in less redirections to find the right node.

text:
| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ❌ Standard
<nobr>❌ Active-Active</nobr> | ❌ Standard
<nobr>❌ Active-Active</nobr> |  |

title: Return information

text:
**RESP2:**

[Simple string reply](../../develop/reference/protocol-spec#simple-strings): all the sub-commands return `OK` if the command was successful. Otherwise an error is returned.

**RESP3:**

[Simple string reply](../../develop/reference/protocol-spec#simple-strings): all the sub-commands return `OK` if the command was successful. Otherwise an error is returned.


title: CLUSTER SHARDS

summary: Returns the mapping of cluster slots to shards.

title: Overview

text:
`CLUSTER SHARDS` returns details about the shards of the cluster.
A shard is defined as a collection of nodes that serve the same set of slots and that replicate from each other.
A shard may only have a single master at a given time, but may have multiple or no replicas.
It is possible for a shard to not be serving any slots while still having replicas.

This command replaces the [`CLUSTER SLOTS`]() command, by providing a more efficient and extensible representation of the cluster.

The command is suitable to be used by Redis Cluster client libraries in order to understand the topology of the cluster.
A client should issue this command on startup in order to retrieve the map associating cluster *hash slots* with actual node information.
This map should be used to direct commands to the node that is likely serving the slot associated with a given command.
In the event the command is sent to the wrong node, in that it received a '-MOVED' redirect, this command can then be used to update the topology of the cluster.

The command returns an array of shards, with each shard containing two fields, 'slots' and 'nodes'.

The 'slots' field is a list of slot ranges served by this shard, stored as pair of integers representing the inclusive start and end slots of the ranges.
For example, if a node owns the slots 1, 2, 3, 5, 7, 8 and 9, the slots ranges would be stored as [1-3], [5-5], [7-9].
The slots field would therefore be represented by the following list of integers.

[code example]

The 'nodes' field contains a list of all nodes within the shard.
Each individual node is a map of attributes that describe the node.
Some attributes are optional and more attributes may be added in the future.
The current list of attributes:

* id: The unique node id for this particular node.
* endpoint: The preferred endpoint to reach the node, see below for more information about the possible values of this field.
* ip: The IP address to send requests to for this node.
* hostname (optional): The announced hostname to send requests to for this node.
* port (optional): The TCP (non-TLS) port of the node. At least one of port or tls-port will be present.
* tls-port (optional): The TLS port of the node. At least one of port or tls-port will be present.
* role: The replication role of this node.
* replication-offset: The replication offset of this node. This information can be used to send commands to the most up to date replicas.
* health: Either `online`, `failed`, or `loading`. This information should be used to determine which nodes should be sent traffic. The `loading` health state should be used to know that a node is not currently eligible to serve traffic, but may be eligible in the future.

The endpoint, along with the port, defines the location that clients should use to send requests for a given slot.
A NULL value for the endpoint indicates the node has an unknown endpoint and the client should connect to the same endpoint it used to send the `CLUSTER SHARDS` command but with the port returned from the command.
This unknown endpoint configuration is useful when the Redis nodes are behind a load balancer that Redis doesn't know the endpoint of.
Which endpoint is set is determined by the `cluster-preferred-endpoint-type` config.
An empty string `""` is another abnormal value of the endpoint field, as well as for the ip field, which is returned if the node doesn't know its own IP address.
This can happen in a cluster that consists of only one node or the node has not yet been joined with the rest of the cluster.
The value `?` is displayed if the node is incorrectly configured to use announced hostnames but no hostname is configured using `cluster-announce-hostname`.
Clients may treat the empty string in the same way as NULL, that is the same endpoint it used to send the current command to, while `"?"` should be treated as an unknown node, not necessarily the same node as the one serving the current command.

title: Examples

role: example

text: [code example]

text:
| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ✅ Standard
<nobr>✅ Active-Active</nobr> | ✅ Standard
<nobr>✅ Active-Active</nobr> | Only supported with the [OSS cluster API](). |

title: Return information

text:
**RESP2:**

[Array reply](../../develop/reference/protocol-spec#arrays): a nested list of a map of hash ranges and shard nodes describing individual shards.

**RESP3:**

[Array reply](../../develop/reference/protocol-spec#arrays): a nested list of [Map reply](../../develop/reference/protocol-spec#maps) of hash ranges and shard nodes describing individual shards.

code:
1) 1) "slots"
   2) 1) (integer) 1
      2) (integer) 3
      3) (integer) 5
      4) (integer) 5
      5) (integer) 7
      6) (integer) 9

section_id: overview

section_id: examples


title: CLUSTER SLAVES

title: Overview

text:
**A note about the word slave used in this man page and command name**: starting with Redis version 5, if not for backward compatibility, the Redis project no longer uses the word slave. Please use the new command [`CLUSTER REPLICAS`](). The command `CLUSTER SLAVES` will continue to work for backward compatibility.

The command provides a list of replica nodes replicating from the specified
master node. The list is provided in the same format used by [`CLUSTER NODES`]() (please refer to its documentation for the specification of the format).

The command will fail if the specified node is not known or if it is not
a master according to the node table of the node receiving the command.

Note that if a replica is added, moved, or removed from a given master node,
and we ask `CLUSTER SLAVES` to a node that has not yet received the
configuration update, it may show stale information. However eventually
(in a matter of seconds if there are no network partitions) all the nodes
will agree about the set of nodes associated with a given master.

text:
| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ❌ Standard
<nobr>❌ Active-Active</nobr> | ❌ Standard
<nobr>❌ Active-Active</nobr> | Deprecated as of Redis v5.0.0. |

title: Return information

text:
**RESP2:**

[Array reply](../../develop/reference/protocol-spec#arrays): a list of replica nodes replicating from the specified master node provided in the same format used by `CLUSTER NODES`.

**RESP3:**

[Array reply](../../develop/reference/protocol-spec#arrays): a list of replica nodes replicating from the specified master node provided in the same format used by `CLUSTER NODES`.


title: CLUSTER SLOT-STATS

summary: Return an array of slot usage statistics for slots assigned to the current node.

title: Overview

text: Use this command to get an array of slot usage statistics for the slots assigned to the current shard. If you're working with a Redis cluster, this data helps you understand overall slot usage, spot hot or cold slots, plan slot migrations to balance load, or refine your application logic to better distribute keys.

title: Options

role: parameters

text:
`CLUSTER SLOT-STATS` has two mutually exclusive options:

* `ORDERBY`: Sorts the slot statistics by the specified metric. Use ASC or DESC to sort in ascending or descending order. If multiple slots have the same value, the command uses the slot number as a tiebreaker, sorted in ascending order.

* `SLOTSRANGE`: Limits the results to a specific, inclusive range of slots. Results are always sorted by slot number in ascending order.

The command reports on the following statistics:

* `KEY-COUNT`: Number of keys stored in the slot.
* `CPU-USEC`: CPU time (in microseconds) spent handling the slot.
* `MEMORY-BYTES`: Number of bytes allocated by the slot.
* `NETWORK-BYTES-IN`: Total inbound network traffic (in bytes) received by the slot.
* `NETWORK-BYTES-OUT`: Total outbound network traffic (in bytes) sent from the slot.

All metrics except `KEY-COUNT` require that `cluster-slot-stats-enabled` is set to `yes` in the `redis.conf` file.

title: Return information

text:
**RESP2:**

One of the following:

* [Array reply](): a nested list of slot usage statistics.
* [Simple error]() otherwise.

**RESP3:**

One of the following:

* [Array reply](): a nested list of slot usage statistics.
* [Simple error]() otherwise.


title: CLUSTER SLOTS

summary: Returns the mapping of cluster slots to nodes.

title: Overview

text:
`CLUSTER SLOTS` returns details about which cluster slots map to which Redis instances.
The command is suitable to be used by Redis Cluster client libraries implementations in order to retrieve (or update when a redirection is received) the map associating cluster *hash slots* with actual nodes network information, so that when a command is received, it can be sent to what is likely the right instance for the keys specified in the command.

The networking information for each node is an array containing the following elements:

* Preferred endpoint (Either an IP address, hostname, or NULL)
* Port number
* The node ID
* A map of additional networking metadata

The preferred endpoint, along with the port, defines the location that clients should use to send requests for a given slot.
A NULL value for the endpoint indicates the node has an unknown endpoint and the client should connect to the same endpoint it used to send the `CLUSTER SLOTS` command but with the port returned from the command.
This unknown endpoint configuration is useful when the Redis nodes are behind a load balancer that Redis doesn't know the endpoint of.
Which endpoint is set as preferred is determined by the `cluster-preferred-endpoint-type` config.
An empty string `""` is another abnormal value of the endpoint field, as well as for the ip field, which is returned if the node doesn't know its own IP address.
This can happen in a cluster that consists of only one node or the node has not yet been joined with the rest of the cluster.
The value `?` is displayed if the node is incorrectly configured to use announced hostnames but no hostname is configured using `cluster-announce-hostname`.
Clients may treat the empty string in the same way as NULL, that is the same endpoint it used to send the current command to, while `"?"` should be treated as an unknown node, not necessarily the same node as the one serving the current command.

Additional networking metadata is provided as a map on the fourth argument for each node.
The following networking metadata may be returned:

* IP: When the preferred endpoint is not set to IP.
* Hostname: When a node has an announced hostname but the primary endpoint is not set to hostname.

title: Nested Result Array

text:
Each nested result is:

  - Start slot range
  - End slot range
  - Master for slot range represented as nested networking information
  - First replica of master for slot range
  - Second replica
  - ...continues until all replicas for this master are returned.

Each result includes all active replicas of the master instance
for the listed slot range.  Failed replicas are not returned.

The third nested reply is guaranteed to be the networking information of the master instance for the slot range.
All networking information after the third nested reply are replicas of the master.

If a cluster instance has non-contiguous slots (e.g. 1-400,900,1800-6000) then master and replica networking information results will be duplicated for each top-level slot range reply.

[code example]

**Warning:** In future versions there could be more elements describing the node better.
In general a client implementation should just rely on the fact that certain parameters are at fixed positions as specified, but more parameters may follow and should be ignored.
Similarly a client library should try if possible to cope with the fact that older versions may just have the primary endpoint and port parameter.

title: Behavior change history

text: *   `>= 7.0.0`: Added support for hostnames and unknown endpoints in first field of node response.

text:
| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ✅ Standard
<nobr>✅ Active-Active</nobr> | ✅ Standard
<nobr>✅ Active-Active</nobr> | Only supported with the [OSS cluster API](). Deprecated as of Redis v7.0.0. |

title: Return information

text:
**RESP2:**

[Array reply](../../develop/reference/protocol-spec#arrays): nested list of slot ranges with networking information.

**RESP3:**

[Array reply](../../develop/reference/protocol-spec#arrays): nested list of slot ranges with networking information.

section_id: nested-result-array


title: CMS.INCRBY

summary: Increases the count of one or more items by increment

title: Overview

text: Increases the count of item by increment. Multiple items can be increased with one call.

title: Parameters:

text:
* **key**: The name of the sketch.
* **item**: The item which counter is to be increased.
* **increment**: Amount by which the item counter is to be increased.

title: Examples

text: [code example]

text:
| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ✅ Supported
 | <nobr>✅ Flexible & Annual</nobr>
✅ Free & Fixed</nobr> |  |

title: Return information

text:
**RESP2:**

One of the following:

* [Array]() of [integer replies]() representing updated min-counts of each of the provided items in the sketch.
* [Simple error reply]() in these cases: invalid arguments, missing key, overflow, or wrong key type.

**RESP3:**

One of the following:

* [Array]() of [integer replies]() representing updated min-counts of each of the provided items in the sketch.
* [Simple error reply]() in these cases: invalid arguments, missing key, overflow, or wrong key type.

code:
redis> CMS.INCRBY test foo 10 bar 42
1) (integer) 10
2) (integer) 42


title: CMS.INFO

summary: Returns information about a sketch

title: Overview

text: Returns width, depth and total count of the sketch.

title: Parameters:

text: * **key**: The name of the sketch.

title: Examples

text: [code example]

text:
| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ✅ Supported
 | ✅ Flexible & Annual
✅ Free & Fixed</nobr> |  |

title: Return information

text:
**RESP2:**

One of the following:

* [Array reply]() of [simple string reply]() and [integer reply]() pairs containing sketch information.
* [Simple error reply]() in these cases: invalid arguments, missing key, or wrong key type.

**RESP3:**

One of the following:

* [Map reply]() of [simple string reply]() and [integer reply]() pairs containing sketch information.
* [Simple error reply]() in these cases: invalid arguments, missing key, or wrong key type.

code:
redis> CMS.INFO test
 1) width
 2) (integer) 2000
 3) depth
 4) (integer) 7
 5) count
 6) (integer) 0


title: CMS.INITBYDIM

title: Overview

text: Initializes a Count-Min Sketch to dimensions specified by user.

title: Parameters:

text:
* **key**: The name of the sketch.
* **width**: Number of counters in each array. Reduces the error size.
* **depth**: Number of counter-arrays. Reduces the probability for an
    error of a certain size (percentage of total count).

title: Examples

text: [code example]

title: Return information

text:
**RESP2:**

One of the following:

* [Simple string reply]() `OK` if executed correctly.
* [Simple error reply]() if the given key already exists.

**RESP3:**

One of the following:

* [Simple string reply]() `OK` if executed correctly.
* [Simple error reply]() if the given key already exists.

code:
redis> CMS.INITBYDIM test 2000 5
OK


title: CMS.INITBYPROB

summary: Initializes a Count-Min Sketch to accommodate requested tolerances.

title: Overview

title: Parameters:

text:
* **key**: The name of the sketch.
* **error**: Estimate size of error. The error is a percent of total counted
    items. This effects the width of the sketch.
* **probability**: The desired probability for inflated count. This should
    be a decimal value between 0 and 1. This effects the depth of the sketch.
    For example, for a desired false positive rate of 0.1% (1 in 1000),
    error_rate should be set to 0.001. The closer this number is to zero, the
    greater the memory consumption per item and the more CPU usage per operation.

title: Examples

text: [code example]

title: Return information

code:
redis> CMS.INITBYPROB test 0.001 0.01
OK


title: CMS.MERGE

summary: Merges several sketches into one sketch

title: Overview

text:
This command's behavior varies in clustered Redis environments. See the [multi-key operations]() page for more information.

Merges several sketches into one sketch. All sketches must have identical width and depth. Weights can be used to multiply certain sketches. Default weight is 1.

title: Parameters:

text:
* **dest**: The name of destination sketch. Must be initialized.
* **numKeys**: Number of sketches to be merged.
* **src**: Names of source sketches to be merged.
* **weight**: Multiple of each sketch. Default =1.

title: Examples

text: [code example]

title: Return information

text:
**RESP2:**

One of the following:

* [Simple string reply]() `OK` if executed correctly.
* [Simple error reply]() in these cases: non-existent key or destination key is not of the same width and/or depth.

**RESP3:**

One of the following:

* [Simple string reply]() `OK` if executed correctly.
* [Simple error reply]() in these cases: non-existent key or destination key is not of the same width and/or depth.

code:
redis> CMS.MERGE dest 2 test1 test2 WEIGHTS 1 3
OK


title: CMS.QUERY

title: Overview

text: Returns the count for one or more items in a sketch.

title: Parameters:

text:
* **key**: The name of the sketch.
* **item**: One or more items for which to return the count.

title: Examples

text: [code example]

title: Return information

text:
**RESP2:**

One of the following:

* [Array]() of [integer replies]()  representing the min-counts of each of the provided items in the sketch.
* [Simple error reply]() in these cases: invalid arguments, missing key, or wrong key type.

**RESP3:**

One of the following:

* [Array]() of [integer replies]() representing the min-counts of each of the provided items in the sketch.
* [Simple error reply]() in these cases: invalid arguments, missing key, or wrong key type.

code:
redis> CMS.QUERY test foo bar
1) (integer) 10
2) (integer) 42


title: COMMAND

summary: Returns detailed information about all commands.

title: Overview

text:
Return an array with details about every Redis command.

The `COMMAND` command is introspective.
Its reply describes all commands that the server can process.
Redis clients can call it to obtain the server's runtime capabilities during the handshake.

`COMMAND` also has several subcommands.
Please refer to its subcommands for further details.

**Cluster note:**
this command is especially beneficial for cluster-aware clients.
Such clients must identify the names of keys in commands to route requests to the correct shard.
Although most commands accept a single key as their first argument, there are many exceptions to this rule.
You can call `COMMAND` and then keep the mapping between commands and their respective key specification rules cached in the client.

The reply it returns is an array with an element per command.
Each element that describes a Redis command is represented as an array by itself.

The command's array consists of a fixed number of elements.
The exact number of elements in the array depends on the server's version.

1. Name
1. Arity
1. Flags
1. First key
1. Last key
1. Step
1. [ACL categories][ta] (as of Redis 6.0)
1. [Tips][tb] (as of Redis 7.0)
1. [Key specifications][td] (as of Redis 7.0)
1. Subcommands (as of Redis 7.0)

title: Name

text:
This is the command's name in lowercase.

**Note:**
Redis command names are case-insensitive.

title: Arity

text:
Arity is the number of arguments a command expects.
It follows a simple pattern:

* A positive integer means a fixed number of arguments.
* A negative integer means a minimal number of arguments.

Command arity _always includes_ the command's name itself (and the subcommand when applicable).

Examples:

* [`GET`]()'s arity is _2_ since the command only accepts one argument and always has the format `GET _key_`.
* [`MGET`]()'s arity is _-2_ since the command accepts at least one argument, but possibly multiple ones: `MGET _key1_ [key2] [key3] ...`.

title: Flags

text:
Command flags are an array. It can contain the following simple strings (status reply):

* **admin:** the command is an administrative command.
* **asking:** the command is allowed even during hash slot migration.
  This flag is relevant in Redis Cluster deployments.
* **blocking:** the command may block the requesting client.
* **denyoom**: the command is rejected if the server's memory usage is too high (see the _maxmemory_ configuration directive).
* **fast:** the command operates in constant or log(N) time.
  This flag is used for monitoring latency with the [`LATENCY`]() command.
* **loading:** the command is allowed while the database is loading.
* **movablekeys:** the _first key_, _last key_, and _step_ values don't determine all key positions.
  Clients need to use [`COMMAND GETKEYS`]() or [key specifications][td] in this case.
  See below for more details.
* **no_auth:** executing the command doesn't require authentication.
* **no_async_loading:** the command is denied during asynchronous loading (that is when a replica uses disk-less `SWAPDB SYNC`, and allows access to the old dataset).
* **no_mandatory_keys:** the command may accept key name arguments, but these aren't mandatory.
* **no_multi:** the command isn't allowed inside the context of a [transaction]().
* **noscript:** the command can't be called from [scripts]() or [functions]().
* **pubsub:** the command is related to [Redis Pub/Sub]().
* **random**: the command returns random results, which is a concern with verbatim script replication.
  As of Redis 7.0, this flag is a [command tip][tb].
* **readonly:** the command doesn't modify data.
* **sort_for_script:** the command's output is sorted when called from a script.
* **skip_monitor:** the command is not shown in [`MONITOR`]()'s output.
* **skip_slowlog:** the command is not shown in [`SLOWLOG`]()'s output.
  As of Redis 7.0, this flag is a [command tip][tb].
* **stale:** the command is allowed while a replica has stale data.
* **write:** the command may modify data.

title: Movablekeys

text:
Consider [`SORT`]():

[code example]

Some Redis commands have no predetermined key locations or are not easy to find.
For those commands, the _movablekeys_ flag indicates that the _first key_, _last key_, and _step_ values are insufficient to find all the keys.

Here are several examples of commands that have the _movablekeys_ flag:

* [`SORT`](): the optional _STORE_, _BY_, and _GET_ modifiers are followed by names of keys.
* [`ZUNION`](): the _numkeys_ argument specifies the number key name arguments.
* [`MIGRATE`](): the keys appear _KEYS_ keyword and only when the second argument is the empty string.

Redis Cluster clients need to use other measures, as follows, to locate the keys for such commands.

You can use the [`COMMAND GETKEYS`]() command and have your Redis server report all keys of a given command's invocation.

As of Redis 7.0, clients can use the [key specifications](#key-specifications) to identify the positions of key names.
The only commands that require using [`COMMAND GETKEYS`]() are [`SORT`]() and [`MIGRATE`]() for clients that parse keys' specifications.

For more information, please refer to the [key specifications page][tr].

title: First key

text:
The position of the command's first key name argument.
For most commands, the first key's position is 1.
Position 0 is always the command name itself.

title: Last key

text:
The position of the command's last key name argument.
Redis commands usually accept one, two or multiple number of keys.

Commands that accept a single key have both _first key_ and _last key_ set to 1.

Commands that accept two key name arguments, e.g. [`BRPOPLPUSH`](), [`SMOVE`]() and [`RENAME`](), have this value set to the position of their second key.

Multi-key commands that accept an arbitrary number of keys, such as [`MSET`](), use the value -1.

title: Step

text:
The step, or increment, between the _first key_ and the position of the next key.

Consider the following two examples:

[code example]

[code example]

The step count allows us to find keys' positions.
For example [`MSET`](): Its syntax is `MSET _key1_ _val1_ [key2] [val2] [key3] [val3]...`, so the keys are at every other position (step value of _2_).
Unlike [`MGET`](), which uses a step value of _1_.

title: ACL categories

role: security

text:
This is an array of simple strings that are the ACL categories to which the command belongs.
Please refer to the [Access Control List][ta] page for more information.

title: Command tips

role: syntax

text:
Helpful information about the command.
To be used by clients/proxies.

Please check the [Command tips][tb] page for more information.

title: Key specifications

text:
This is an array consisting of the command's key specifications.
Each element in the array is a map describing a method for locating keys in the command's arguments.

For more information please check the [key specifications page][td].

title: Subcommands

text:
This is an array containing all of the command's subcommands, if any.
Some Redis commands have subcommands (e.g., the `REWRITE` subcommand of [`CONFIG`]()).
Each element in the array represents one subcommand and follows the same specifications as those of `COMMAND`'s reply.

[ta]: /operate/oss_and_stack/management/security/acl
[tb]: /develop/reference/command-tips.md
[td]: /develop/reference/key-specs.md
[tr]: /develop/reference/key-specs.md

title: Examples

text:
The following is `COMMAND`'s output for the [`GET`]() command:

[code example]

text:
| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ✅ Standard
<nobr>✅ Active-Active</nobr> | ✅ Standard
<nobr>✅ Active-Active</nobr> |  |

title: Return information

text:
**RESP2:**

[Array reply](../../develop/reference/protocol-spec#arrays): a nested list of command details. The order of the commands in the array is random.

**RESP3:**

[Array reply](../../develop/reference/protocol-spec#arrays): a nested list of command details. The order of the commands in the array is random.

code:
1) 1) "sort"
   2) (integer) -2
   3) 1) write
      2) denyoom
      3) movablekeys
   4) (integer) 1
   5) (integer) 1
   6) (integer) 1
   ...

section_id: movablekeys

code:
1) 1) "mset"
   2) (integer) -3
   3) 1) write
      2) denyoom
   4) (integer) 1
   5) (integer) -1
   6) (integer) 2
   ...

section_id: step

code:
1) 1) "mget"
   2) (integer) -2
   3) 1) readonly
      2) fast
   4) (integer) 1
   5) (integer) -1
   6) (integer) 1
   ...

code:
1)  1) "get"
    2) (integer) 2
    3) 1) readonly
       2) fast
    4) (integer) 1
    5) (integer) 1
    6) (integer) 1
    7) 1) @read
       2) @string
       3) @fast
    8) (empty array)
    9) 1) 1) "flags"
          2) 1) read
          3) "begin_search"
          4) 1) "type"
             2) "index"
             3) "spec"
             4) 1) "index"
                2) (integer) 1
          5) "find_keys"
          6) 1) "type"
             2) "range"
             3) "spec"
             4) 1) "lastkey"
                2) (integer) 0
                3) "keystep"
                4) (integer) 1
                5) "limit"
                6) (integer) 0
   10) (empty array)
...


title: COMMAND COUNT

summary: Returns a count of commands.

title: Overview

text: Returns [Integer reply]() of number of total commands in this Redis server.

title: Examples

text: COMMAND COUNT

title: Return information

text:
**RESP2:**

[Integer reply](../../develop/reference/protocol-spec#integers): the number of commands returned by `COMMAND`.

**RESP3:**

[Integer reply](../../develop/reference/protocol-spec#integers): the number of commands returned by `COMMAND`.


title: COMMAND DOCS

summary: Returns documentary information about one, multiple or all commands.

title: Overview

text:
Return documentary information about commands.

By default, the reply includes all of the server's commands.
You can use the optional _command-name_ argument to specify the names of one or more commands.

The reply includes a map for each returned command.
The following keys may be included in the mapped reply:

* **summary:** short command description.
* **since:** the Redis version that added the command (or for module commands, the module version).
* **group:** the functional group to which the command belongs.
  Possible values are:
  - _bitmap_
  - _cluster_
  - _connection_
  - _generic_
  - _geo_
  - _hash_
  - _hyperloglog_
  - _list_
  - _module_
  - _pubsub_
  - _scripting_
  - _sentinel_
  - _server_
  - _set_
  - _sorted-set_
  - _stream_
  - _string_
  - _transactions_
* **complexity:** a short explanation about the command's time complexity.
* **doc_flags:** an array of documentation flags.
  Possible values are:
  - _deprecated:_ the command is deprecated.
  - _syscmd:_ a system command that isn't meant to be called by users.
* **deprecated_since:** the Redis version that deprecated the command (or for module commands, the module version)..
* **replaced_by:** the alternative for a deprecated command.
* **history:** an array of historical notes describing changes to the command's output or arguments. It should not contain information about behavioral changes.
  Each entry is an array itself, made up of two elements:
  1. The Redis version that the entry applies to.
  2. The description of the change.
* **arguments:** an array of maps that describe the command's arguments.
  Please refer to the [Redis command arguments][td] page for more information.

[td]: /develop/reference/command-arguments

title: Examples

text: COMMAND DOCS SET

title: Return information

text:
**RESP2:**

[Array reply](../../develop/reference/protocol-spec#arrays): a map, as a flattened array, where each key is a command name, and each value is the documentary information.

**RESP3:**

[Map reply](../../develop/reference/protocol-spec#maps): a map where each key is a command name, and each value is the documentary information.


title: COMMAND GETKEYS

summary: Extracts the key names from an arbitrary command.

title: Overview

text:
Returns [Array reply]() of keys from a full Redis command.

`COMMAND GETKEYS` is a helper command to let you find the keys
from a full Redis command.

[`COMMAND`]() provides information on how to find the key names of each command (see `firstkey`, [key specifications](), and `movablekeys`),
but in some cases it's not possible to find keys of certain commands and then the entire command must be parsed to discover some / all key names.
You can use `COMMAND GETKEYS` or [`COMMAND GETKEYSANDFLAGS`]() to discover key names directly from how Redis parses the commands.

title: Examples

text:
COMMAND GETKEYS MSET a b c d e f
COMMAND GETKEYS EVAL "not consulted" 3 key1 key2 key3 arg1 arg2 arg3 argN
COMMAND GETKEYS SORT mylist ALPHA STORE outlist

title: Return information

text:
**RESP2:**

[Array reply](../../develop/reference/protocol-spec#arrays): list of keys from the given command.

**RESP3:**

[Array reply](../../develop/reference/protocol-spec#arrays): a list of keys from the given command.


title: COMMAND GETKEYSANDFLAGS

summary: Extracts the key names and access flags for an arbitrary command.

title: Overview

text:
Returns [Array reply]() of keys from a full Redis command and their usage flags.

`COMMAND GETKEYSANDFLAGS` is a helper command to let you find the keys from a full Redis command together with flags indicating what each key is used for.

[`COMMAND`]() provides information on how to find the key names of each command (see `firstkey`, [key specifications](), and `movablekeys`),
but in some cases it's not possible to find keys of certain commands and then the entire command must be parsed to discover some / all key names.
You can use [`COMMAND GETKEYS`]() or `COMMAND GETKEYSANDFLAGS` to discover key names directly from how Redis parses the commands.

Refer to [key specifications]() for information about the meaning of the key flags.

title: Examples

text:
COMMAND GETKEYS MSET a b c d e f
COMMAND GETKEYS EVAL "not consulted" 3 key1 key2 key3 arg1 arg2 arg3 argN
COMMAND GETKEYSANDFLAGS LMOVE mylist1 mylist2 left left

title: Return information

text:
**RESP2:**

[Array reply](../../develop/reference/protocol-spec#arrays): a list of keys from the given command and their usage flags.

**RESP3:**

[Array reply](../../develop/reference/protocol-spec#arrays): a list of keys from the given command and their usage flags.


title: COMMAND HELP

summary: Returns helpful text about the different subcommands.

title: Overview

text: The `COMMAND HELP` command returns a helpful text describing the different subcommands.

title: Return information

text:
**RESP2:**

[Array reply](../../develop/reference/protocol-spec#arrays): a list of sub-commands and their descriptions.

**RESP3:**

[Array reply](../../develop/reference/protocol-spec#arrays): a list of sub-commands and their descriptions.


title: COMMAND INFO

summary: Returns information about one, multiple or all commands.

title: Overview

text:
Returns [Array reply]() of details about multiple Redis commands.

Same result format as [`COMMAND`]() except you can specify which commands
get returned.

If you request details about non-existing commands, their return
position will be nil.

title: Examples

text:
COMMAND INFO get set eval
COMMAND INFO foo evalsha config bar

title: Return information

text:
**RESP2:**

[Array reply](../../develop/reference/protocol-spec#arrays): a nested list of command details.

**RESP3:**

[Array reply](../../develop/reference/protocol-spec#arrays): a nested list of command details.


title: COMMAND LIST

summary: Returns a list of command names.

title: Overview

text:
Return an array of the server's command names.

You can use the optional _FILTERBY_ modifier to apply one of the following filters:

 - **MODULE module-name**: get the commands that belong to the module specified by _module-name_.
 - **ACLCAT category**: get the commands in the [ACL category]() specified by _category_.
 - **PATTERN pattern**: get the commands that match the given glob-like _pattern_.

text:
| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ✅ Standard
<nobr>✅ Active-Active</nobr> | ✅ Standard
<nobr>✅ Active-Active</nobr> |  |

title: Return information

text:
**RESP2:**

[Array reply](../../develop/reference/protocol-spec#arrays): a list of command names.

**RESP3:**

[Array reply](../../develop/reference/protocol-spec#arrays): a list of command names.


title: CONFIG

summary: A container for server configuration commands.

title: Content

text:
This is a container command for runtime configuration commands.

To see the list of available commands you can call [`CONFIG HELP`]().


title: CONFIG GET

summary: Returns the effective values of configuration parameters.

title: Overview

text:
The `CONFIG GET` command is used to read the configuration parameters of a
running Redis server.
Not all the configuration parameters are supported in Redis 2.4, while Redis 2.6
can read the whole configuration of a server using this command.

The symmetric command used to alter the configuration at run time is `CONFIG
SET`.

`CONFIG GET` takes multiple arguments, which are glob-style patterns.
Any configuration parameter matching any of the patterns are reported as a list
of key-value pairs.
Example:

[code example]

You can obtain a list of all the supported configuration parameters by typing
`CONFIG GET *` in an open `redis-cli` prompt.

All the supported parameters have the same meaning of the equivalent
configuration parameter used in the [redis.conf][hgcarr22rc] file:

[hgcarr22rc]: http://github.com/redis/redis/raw/unstable/redis.conf

Note that you should look at the redis.conf file relevant to the version you're
working with as configuration options might change between versions. The link
above is to the latest development version.

text:
| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ✅ Standard
<nobr>✅ Active-Active</nobr> | ✅ Standard
<nobr>✅ Active-Active</nobr> | [Only supports a subset of configuration settings.]() |

title: Return information

text:
**RESP2:**

[Array reply](../../develop/reference/protocol-spec#arrays): a list of configuration parameters matching the provided arguments.

**RESP3:**

[Map reply](../../develop/reference/protocol-spec#maps): a list of configuration parameters matching the provided arguments.

code:
redis> config get *max-*-entries* maxmemory
 1) "maxmemory"
 2) "0"
 3) "hash-max-listpack-entries"
 4) "512"
 5) "hash-max-ziplist-entries"
 6) "512"
 7) "set-max-intset-entries"
 8) "512"
 9) "zset-max-listpack-entries"
10) "128"
11) "zset-max-ziplist-entries"
12) "128"


title: CONFIG HELP

title: Overview

text: The `CONFIG HELP` command returns a helpful text describing the different subcommands.

text:
| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ❌ Standard
<nobr>❌ Active-Active</nobr> | ❌ Standard
<nobr>❌ Active-Active</nobr> |  |

title: Return information


title: CONFIG RESETSTAT

summary: Resets the server's statistics.

title: Overview

text:
Resets the statistics reported by Redis using the [`INFO`]() and [`LATENCY HISTOGRAM`]() commands.

The following is a non-exhaustive list of values that are reset:

* Keyspace hits and misses
* Number of expired keys
* Command and error statistics
* Connections received, rejected and evicted
* Persistence statistics
* Active defragmentation statistics

title: Return information

text:
**RESP2:**

[Simple string reply](../../develop/reference/protocol-spec#simple-strings): `OK`.

**RESP3:**

[Simple string reply](../../develop/reference/protocol-spec#simple-strings): `OK`.


title: CONFIG REWRITE

summary: Persists the effective configuration to file.

title: Overview

text:
The `CONFIG REWRITE` command rewrites the `redis.conf` file the server was started with, applying the minimal changes needed to make it reflect the configuration currently used by the server, which may be different compared to the original one because of the use of the [`CONFIG SET`]() command.

The rewrite is performed in a very conservative way:

* Comments and the overall structure of the original redis.conf are preserved as much as possible.
* If an option already exists in the old redis.conf file, it will be rewritten at the same position (line number).
* If an option was not already present, but it is set to its default value, it is not added by the rewrite process.
* If an option was not already present, but it is set to a non-default value, it is appended at the end of the file.
* Non used lines are blanked. For instance if you used to have multiple `save` directives, but the current configuration has fewer or none as you disabled RDB persistence, all the lines will be blanked.

CONFIG REWRITE is also able to rewrite the configuration file from scratch if the original one no longer exists for some reason. However if the server was started without a configuration file at all, the CONFIG REWRITE will just return an error.

title: Atomic rewrite process

text: In order to make sure the redis.conf file is always consistent, that is, on errors or crashes you always end with the old file, or the new one, the rewrite is performed with a single `write(2)` call that has enough content to be at least as big as the old file. Sometimes additional padding in the form of comments is added in order to make sure the resulting file is big enough, and later the file gets truncated to remove the padding at the end.

title: Return information

text:
**RESP2:**

[Simple string reply](../../develop/reference/protocol-spec#simple-strings): `OK` when the configuration was rewritten properly. Otherwise an error is returned.

**RESP3:**

[Simple string reply](../../develop/reference/protocol-spec#simple-strings): `OK` when the configuration was rewritten properly. Otherwise an error is returned.


title: CONFIG SET

summary: Sets configuration parameters in-flight.

title: Overview

text:
The `CONFIG SET` command is used in order to reconfigure the server at run time
without the need to restart Redis.
You can change both trivial parameters or switch from one to another persistence
option using this command.

The list of configuration parameters supported by `CONFIG SET` can be obtained
issuing a `CONFIG GET *` command, that is the symmetrical command used to obtain
information about the configuration of a running Redis instance.

All the configuration parameters set using `CONFIG SET` are immediately loaded
by Redis and will take effect starting with the next command executed.

All the supported parameters have the same meaning of the equivalent
configuration parameter used in the [redis.conf][hgcarr22rc] file.

[hgcarr22rc]: http://github.com/redis/redis/raw/unstable/redis.conf

Note that you should look at the redis.conf file relevant to the version you're
working with as configuration options might change between versions. The link
above is to the latest development version.

It is possible to switch persistence from RDB snapshotting to append-only file
(and the other way around) using the `CONFIG SET` command.
See the [persistence page]() for more information.

[code example]

Setting the `appendonly` parameter as shown above will start a background process to save the initial append-only file
(obtained from the in memory data set), and will append all the subsequent
commands on the append-only file, thus obtaining exactly the same effect of a
Redis server that started with AOF turned on since the start.

You can have both the AOF enabled with RDB snapshotting if you want, the two
options are not mutually exclusive.

title: Return information

text:
**RESP2:**

[Simple string reply](../../develop/reference/protocol-spec#simple-strings): `OK` when the configuration was set properly. Otherwise an error is returned.

**RESP3:**

[Simple string reply](../../develop/reference/protocol-spec#simple-strings): `OK` when the configuration was set properly. Otherwise an error is returned.

code: CONFIG SET appendonly yes


title: COPY

summary: Copies the value of a key to a new key.

title: Overview

text:
This command's behavior varies in clustered Redis environments. See the [multi-key operations]() page for more information.

This command copies the value stored at the `source` key to the `destination`
key.

By default, the `destination` key is created in the logical database used by the
connection. The `DB` option allows specifying an alternative logical database
index for the destination key.

The command returns zero when the `destination` key already exists. The
`REPLACE` option removes the `destination` key before copying the value to it.

title: Examples

text: [code example]

text:
| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ✅ Standard
<nobr>✅ Active-Active\*</nobr> | ✅ Standard
<nobr>✅ Active-Active\*</nobr> | 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. |

title: Return information

text:
**RESP2:**

One of the following:
* [Integer reply](../../develop/reference/protocol-spec#integers): `1` if _source_ was copied.
* [Integer reply](../../develop/reference/protocol-spec#integers): `0` if _source_ was not copied.

**RESP3:**

One of the following:
* [Integer reply](../../develop/reference/protocol-spec#integers): `1` if _source_ was copied.
* [Integer reply](../../develop/reference/protocol-spec#integers): `0` if _source_ was not copied.

code:
SET dolly "sheep"
COPY dolly clone
GET clone


title: DBSIZE

summary: Returns the number of keys in the database.

title: Overview

text:
This command's behavior varies in clustered Redis environments. See the [multi-key operations]() page for more information.

Return the number of keys in the currently-selected database.

text:
| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ✅ Standard
<nobr>✅ Active-Active</nobr> | ✅ Standard
<nobr>✅ Active-Active</nobr> |  |

title: Return information

text:
**RESP2:**

[Integer reply](../../develop/reference/protocol-spec#integers): the number of keys in the currently-selected database.

**RESP3:**

[Integer reply](../../develop/reference/protocol-spec#integers): the number of keys in the currently-selected database.


title: DEBUG

summary: A container for debugging commands.

title: Overview

text:
The `DEBUG` command is an internal command.
It is meant to be used for developing and testing Redis.


title: DECR

summary: Decrements the integer value of a key by one. Uses 0 as initial value if the key doesn't exist.

title: Overview

text:
Decrements the number stored at `key` by one.
If the key does not exist, it is set to `0` before performing the operation.
An error is returned if the key contains a value of the wrong type or contains a
string that can not be represented as integer.
This operation is limited to **64 bit signed integers**.

See [`INCR`]() for extra information on increment/decrement operations.

title: Examples

text:
SET mykey "10"
DECR mykey
SET mykey "234293482390480948029348230948"
DECR mykey

title: Return information

text:
**RESP2:**

[Integer reply](../../develop/reference/protocol-spec#integers): the value of the key after decrementing it.

**RESP3:**

[Integer reply](../../develop/reference/protocol-spec#integers): the value of the key after decrementing it.


title: DECRBY

summary: Decrements a number from the integer value of a key. Uses 0 as initial value if the key doesn't exist.

title: Overview

text:
The `DECRBY` command reduces the value stored at the specified `key` by the specified `decrement`.
If the key does not exist, it is initialized with a value of `0` before performing the operation.
If the key's value is not of the correct type or cannot be represented as an integer, an error is returned.
This operation is limited to 64-bit signed integers.

See [`INCR`]() for extra information on increment/decrement operations.

title: Examples

text:
SET mykey "10"
DECRBY mykey 3

title: Return information


title: DEL

summary: Deletes one or more keys.

title: Examples

text:
#### Code Examples

Foundational: Delete one or more keys using DEL (ignores non-existent keys, returns count of deleted keys)

**Difficulty:** Beginner

**Commands:** SET, DEL

**Complexity:**
- SET: O(1)
- DEL: O(N)

**Redis CLI:**

[code example]

**Available in:** Redis CLI, C, C# (Synchronous), Go, Java (Asynchronous - Lettuce), Java (Reactive - Lettuce), Java (Synchronous - Jedis), JavaScript (Node.js), JavaScript (Node.js), PHP, Python, Rust (Asynchronous), Rust (Synchronous)

**C:**

[code example]

**C# (Synchronous):**

[code example]

**Go:**

[code example]

**Java (Asynchronous - Lettuce):**

[code example]

**Java (Reactive - Lettuce):**

[code example]

**Java (Synchronous - Jedis):**

[code example]

**JavaScript (Node.js):**

[code example]

**JavaScript (Node.js):**

[code example]

**JavaScript (Node.js):**

[code example]

**JavaScript (Node.js):**

[code example]

**PHP:**

[code example]

**Python:**

[code example]

**Rust (Asynchronous):**

[code example]

**Rust (Synchronous):**

[code example]

Give these commands a try in the interactive console:

SET key1 "Hello"
SET key2 "World"
DEL key1 key2 key3

title: Return information

text:
**RESP2:**

[Integer reply](../../develop/reference/protocol-spec#integers): the number of keys that were removed.

**RESP3:**

[Integer reply](../../develop/reference/protocol-spec#integers): the number of keys that were removed.

code:
> SET key1 "Hello"
"OK"
> SET key2 "World"
"OK"
> DEL key1 key2 key3
(integer) 2

code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <hiredis/hiredis.h>

int main(int argc, char **argv) {
    redisContext *c = redisConnect("127.0.0.1", 6379);

    if (c == NULL || c->err) {
        if (c) {
            printf("Connection error: %s\n", c->errstr);
            redisFree(c);
        } else {
            printf("Connection error: can't allocate redis context\n");
        }
        return 1;
    }

    redisReply *reply;

    // Set up keys
    reply = redisCommand(c, "MSET %s %s %s %s %s %s",
        "firstname", "Jack", "lastname", "Stuntman", "age", "35");
    printf("MSET firstname Jack lastname Stuntman age 35: %s\n", reply->str);
    // >>> OK
    freeReplyObject(reply);

    // Keys matching *name*
    reply = redisCommand(c, "KEYS %s", "*name*");
    printf("KEYS *name*:\n");
    for (size_t i = 0; i < reply->elements; i++) {
        printf("  %s\n", reply->element[i]->str);
    }
    // >>> firstname
    // >>> lastname
    freeReplyObject(reply);

    // Keys matching a??
    reply = redisCommand(c, "KEYS %s", "a??");
    printf("KEYS a??:\n");
    for (size_t i = 0; i < reply->elements; i++) {
        printf("  %s\n", reply->element[i]->str);
    }
    // >>> age
    freeReplyObject(reply);

    // All keys
    reply = redisCommand(c, "KEYS %s", "*");
    printf("KEYS *:\n");
    for (size_t i = 0; i < reply->elements; i++) {
        printf("  %s\n", reply->element[i]->str);
    }
    // >>> age
    // >>> firstname
    // >>> lastname
    freeReplyObject(reply);

    redisFree(c);

    return 0;
}

code:
bool delResult1 = db.StringSet("key1", "Hello");
        Console.WriteLine(delResult1);  // >>> true

        bool delResult2 = db.StringSet("key2", "World");
        Console.WriteLine(delResult2);  // >>> true

        long delResult3 = db.KeyDelete(["key1", "key2", "key3"]);
        Console.WriteLine(delResult3);  // >>> 2

code:
delResult1, err := rdb.Set(ctx, "key1", "Hello", 0).Result()

	if err != nil {
		panic(err)
	}

	fmt.Println(delResult1) // >>> OK

	delResult2, err := rdb.Set(ctx, "key2", "World", 0).Result()

	if err != nil {
		panic(err)
	}

	fmt.Println(delResult2) // >>> OK

	delResult3, err := rdb.Del(ctx, "key1", "key2", "key3").Result()

	if err != nil {
		panic(err)
	}

	fmt.Println(delResult3) // >>> 2

code:
package io.redis.examples.async;

import io.lettuce.core.*;

import io.lettuce.core.api.async.RedisAsyncCommands;

import io.lettuce.core.api.StatefulRedisConnection;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

public class CmdsGenericExample {

    public void run() {

            CompletableFuture<Void> existsExample = asyncCommands.set("key1", "Hello").thenCompose(res1 -> {
                System.out.println(res1); // >>> OK

                return asyncCommands.exists("key1");
            }).thenCompose(res2 -> {
                System.out.println(res2); // >>> 1

                return asyncCommands.exists("nosuchkey");
            }).thenCompose(res3 -> {
                System.out.println(res3); // >>> 0

                return asyncCommands.set("key2", "World");
            }).thenCompose(res4 -> {
                System.out.println(res4); // >>> OK

                return asyncCommands.exists("key1", "key2", "nosuchkey");
            }).thenAccept(res5 -> {
                System.out.println(res5); // >>> 2
            }).toCompletableFuture();
            existsExample.join();

            CompletableFuture<Void> keysExample = asyncCommands.mset(Map.of(
                    "firstname", "Jack",
                    "lastname", "Stuntman",
                    "age", "35"
            )).thenCompose(res1 -> {
                System.out.println(res1); // >>> OK

                return asyncCommands.keys("*name*");
            }).thenCompose(res2 -> {
                Collections.sort(res2);
                System.out.println(res2); // >>> [firstname, lastname]

                return asyncCommands.keys("a??");
            }).thenCompose(res3 -> {
                System.out.println(res3); // >>> [age]

                return asyncCommands.keys("*");
            }).thenAccept(res4 -> {
                Collections.sort(res4);
                System.out.println(res4); // >>> [age, firstname, lastname]
            }).toCompletableFuture();
            keysExample.join();
        } finally {
            redisClient.shutdown();
        }
    }
}

code:
package io.redis.examples.reactive;

import io.lettuce.core.*;
import io.lettuce.core.api.reactive.RedisReactiveCommands;
import io.lettuce.core.api.StatefulRedisConnection;
import reactor.core.publisher.Mono;

import java.util.Collections;
import java.util.Map;

public class CmdsGenericExample {

    public void run() {
        RedisClient redisClient = RedisClient.create("redis://localhost:6379");

        try (StatefulRedisConnection<String, String> connection = redisClient.connect()) {
            RedisReactiveCommands<String, String> reactiveCommands = connection.reactive();

            Mono<Void> existsExample = reactiveCommands.set("key1", "Hello").doOnNext(res1 -> {
                System.out.println(res1); // >>> OK
            }).then(reactiveCommands.exists("key1")).doOnNext(res2 -> {
                System.out.println(res2); // >>> 1
            }).then(reactiveCommands.exists("nosuchkey")).doOnNext(res3 -> {
                System.out.println(res3); // >>> 0
            }).then(reactiveCommands.set("key2", "World")).doOnNext(res4 -> {
                System.out.println(res4); // >>> OK
            }).then(reactiveCommands.exists("key1", "key2", "nosuchkey")).doOnNext(res5 -> {
                System.out.println(res5); // >>> 2
            }).then();

            Mono.when(existsExample).block();

            Mono<Void> keysExample = reactiveCommands.mset(Map.of(
                    "firstname", "Jack",
                    "lastname", "Stuntman",
                    "age", "35"
            )).doOnNext(res1 -> {
                System.out.println(res1); // >>> OK
            }).then(reactiveCommands.keys("*name*").collectList()).doOnNext(res2 -> {
                Collections.sort(res2);
                System.out.println(res2); // >>> [firstname, lastname]
            }).then(reactiveCommands.keys("a??").collectList()).doOnNext(res3 -> {
                System.out.println(res3); // >>> [age]
            }).then(reactiveCommands.keys("*").collectList()).doOnNext(res4 -> {
                Collections.sort(res4);
                System.out.println(res4); // >>> [age, firstname, lastname]
            }).then();

            Mono.when(keysExample).block();

        } finally {
            redisClient.shutdown();
        }
    }

}

code:
String delResult1 = jedis.set("key1", "Hello");
        System.out.println(delResult1); // >>> OK

        String delResult2 = jedis.set("key2", "World");
        System.out.println(delResult2); // >>> OK

        long delResult3 = jedis.del("key1", "key2", "key3");
        System.out.println(delResult3); // >>> 2

code:
const delRes1 = await client.set('key1', 'Hello');
console.log(delRes1); // OK

const delRes2 = await client.set('key2', 'World');
console.log(delRes2); // OK

const delRes3 = await client.del(['key1', 'key2', 'key3']);
console.log(delRes3); // 2

code:
import assert from 'node:assert';
import { Redis } from 'ioredis';

const redis = new Redis();

const keysRes1 = await redis.mset({ firstname: 'Jack', lastname: 'Stuntman', age: '35' });
console.log(keysRes1); // >>> OK

const keysRes2 = await redis.keys('*name*');
console.log(keysRes2.sort()); // >>> ['firstname', 'lastname']

const keysRes3 = await redis.keys('a??');
console.log(keysRes3); // >>> ['age']

const keysRes4 = await redis.keys('*');
console.log(keysRes4.sort()); // >>> ['age', 'firstname', 'lastname']

redis.disconnect();

code:
<?php
use PHPUnit\Framework\TestCase;
use Predis\Client as PredisClient;

class CmdsGenericTest
{
    public function testCmdsGeneric() {
        $r = new PredisClient([
            'scheme'   => 'tcp',
            'host'     => '127.0.0.1',
            'port'     => 6379,
            'password' => '',
            'database' => 0,
        ]);

        $existsResult1 = $r->set('key1', 'Hello');
        echo $existsResult1 . PHP_EOL; // >>> OK

        $existsResult2 = $r->exists('key1');
        echo $existsResult2 . PHP_EOL; // >>> 1

        $existsResult3 = $r->exists('nosuchkey');
        echo $existsResult3 . PHP_EOL; // >>> 0

        $existsResult4 = $r->set('key2', 'World');
        echo $existsResult4 . PHP_EOL; // >>> OK

        $existsResult5 = $r->exists('key1', 'key2', 'nosuchkey');
        echo $existsResult5 . PHP_EOL; // >>> 2

        $keysResult1 = $r->mset(['firstname' => 'Jack', 'lastname' => 'Stuntman', 'age' => '35']);
        echo $keysResult1 . PHP_EOL; // >>> OK

        $keysResult2 = $r->keys('*name*');
        sort($keysResult2);
        echo implode(', ', $keysResult2) . PHP_EOL; // >>> firstname, lastname

        $keysResult3 = $r->keys('a??');
        echo implode(', ', $keysResult3) . PHP_EOL; // >>> age

        $keysResult4 = $r->keys('*');
        sort($keysResult4);
        echo implode(', ', $keysResult4) . PHP_EOL; // >>> age, firstname, lastname

    }
}

code:
res = r.set("key1", "Hello")
print(res)
# >>> True

res = r.set("key2", "World")
print(res)
# >>> True

res = r.delete("key1", "key2", "key3")
print(res)
# >>> 2

code:
if let Ok(res) = r.set("key1", "Hello").await {
            let res: String = res;
            println!("{res}");    // >>> OK
        }

        if let Ok(res) = r.set("key2", "World").await {
            let res: String = res;
            println!("{res}");    // >>> OK
        }

        match r.del(&["key1", "key2", "key3"]).await {
            Ok(res) => {
                let res: i32 = res;
                println!("{res}");    // >>> 2
            },
            Err(e) => {
                println!("Error deleting keys: {e}");
                return;
            }
        }

code:
if let Ok(res) = r.set("key1", "Hello") {
            let res: String = res;
            println!("{res}");    // >>> OK
        }

        if let Ok(res) = r.set("key2", "World") {
            let res: String = res;
            println!("{res}");    // >>> OK
        }

        match r.del(&["key1", "key2", "key3"]) {
            Ok(res) => {
                let res: i32 = res;
                println!("{res}");    // >>> 2
            },
            Err(e) => {
                println!("Error deleting keys: {e}");
                return;
            }
        }


title: DELEX

summary: Conditionally removes the specified key based on value or hash digest comparison.

title: Overview

title: Hash Digest

text: A hash digest is a fixed-size numerical representation of a string value, computed using the XXH3 hash algorithm. Redis uses this hash digest for efficient comparison operations without needing to compare the full string content. You can retrieve a key's hash digest using the [`DIGEST`]() command, which returns it as a hexadecimal string that you can use with the `IFDEQ` and `IFDNE` options, and also the [`SET`]() command's `IFDEQ` and `IFDNE` options.

title: Options

text:
The DELEX command supports a set of options that modify its behavior.
Only one of the options can be specified.

* `IFEQ ifeq-value` -- Remove the key if the value is equal to the specified value.
* `IFNE ifne-value` -- Remove the key if the value is not equal to the specified value.
* `IFDEQ ifeq-digest` -- Remove the key if its hash digest is equal to the specified hash digest.
* `IFDNE ifne-digest` -- Remove the key if its hash digest is not equal to the specified hash digest.

In 8.4, keys must be of type string when using one of the options above. If no options are specified, the key is removed regardless of its type.

text:
| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ❌ Standard
<nobr>❌ Active-Active</nobr> | ❌ Standard
<nobr>❌ Active-Active</nobr> |  |

title: Return information

text:
**RESP2:**

One of the following:
- [Integer reply](): 0 if not deleted (the key does not exist or a specified `IFEQ/IFNE/IFDEQ/IFDNE` condition is false), or 1 if deleted.
- [Simple error reply]() if the key exists but holds a value that is not a string and one of `IFEQ, IFNE, IFDEQ,` or `IFDNE` is specified.

**RESP3:**

One of the following:
- [Integer reply](): 0 if not deleted (the key does not exist or a specified `IFEQ/IFNE/IFDEQ/IFDNE` condition is false), or 1 if deleted.
- [Simple error reply]() if the key exists but holds a value that is not a string and one of `IFEQ, IFNE, IFDEQ,` or `IFDNE` is specified.


title: DIGEST

summary: Returns the hash digest of a string value.

title: Overview

text: Get the hash digest for the value stored in the specified key as a hexadecimal string. Keys must be of type string.

title: Hash Digest

text: A hash digest is a fixed-size numerical representation of a string value, computed using the XXH3 hash algorithm. Redis uses this hash digest for efficient comparison operations without needing to compare the full string content. You can use these hash digests with the [SET]() command's `IFDEQ` and `IFDNE` options, and also the [DELEX]() command's `IFDEQ` and `IFDNE` options.

title: Example

text: [code example]

title: Return information

text:
**RESP2:**

One of the following:

- [Null bulk string reply]() if the key does not exist.
- [Simple error reply]() if the key exists but holds a value which is not a string.
- [Bulk string reply]() the hash digest of the value stored in the key as a hexadecimal string.

**RESP3:**

One of the following:

- [Null bulk string reply]() if the key does not exist.
- [Simple error reply]() if the key exists but holds a value which is not a string.
- [Bulk string reply]() the hash digest of the value stored in the key as a hexadecimal string.

code:
> SET key1 "Hello world"
OK
> DIGEST key1
"b6acb9d84a38ff74"

section_id: example


title: DISCARD

summary: Discards a transaction.

title: Overview

text:
Flushes all previously queued commands in a [transaction][tt] and restores the
connection state to normal.

[tt]: /develop/interact/transactions

If [`WATCH`]() was used, `DISCARD` unwatches all keys watched by the connection.

title: Return information

text:
**RESP2:**

[Simple string reply](../../develop/reference/protocol-spec#simple-strings): `OK`.

**RESP3:**

[Simple string reply](../../develop/reference/protocol-spec#simple-strings): `OK`.


title: DUMP

summary: Returns a serialized representation of the value stored at a key.

title: Overview

text:
Serialize the value stored at key in a Redis-specific format and return it to
the user.
The returned value can be synthesized back into a Redis key using the [`RESTORE`]()
command.

The serialization format is opaque and non-standard, however it has a few
semantic characteristics:

* It contains a 64-bit checksum that is used to make sure errors will be
  detected.
  The [`RESTORE`]() command makes sure to check the checksum before synthesizing a
  key using the serialized value.
* Values are encoded in the same format used by RDB.
* An RDB version is encoded inside the serialized value, so that different Redis
  versions with incompatible RDB formats will refuse to process the serialized
  value.

The serialized value does NOT contain expire information.
In order to capture the time to live of the current value the [`PTTL`]() command
should be used.

If `key` does not exist a nil bulk reply is returned.

title: Examples

text: [code example]

text:
| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ✅ Standard
<nobr>✅ Active-Active</nobr> | ✅ Standard
<nobr>✅ Active-Active</nobr> |  |

title: Return information

text:
**RESP2:**

One of the following:
* [Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): The serialized value of the key.
* [Nil reply](../../develop/reference/protocol-spec#bulk-strings): the key does not exist.

**RESP3:**

One of the following:
* [Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): the serialized value of the key.
* [Null reply](../../develop/reference/protocol-spec#nulls): the key does not exist.

code:
> SET mykey 10
OK
> DUMP mykey
"\x00\xc0\n\n\x00n\x9fWE\x0e\xaec\xbb"


title: ECHO

summary: Returns the given string.

title: Overview

text: Returns `message`.

title: Examples

text: ECHO "Hello World!"

title: Return information

text:
**RESP2:**

[Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): the given string.

**RESP3:**

[Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): the given string.


title: EVAL

summary: Executes a server-side Lua script.

title: Overview

text:
This command's behavior varies in clustered Redis environments. See the [multi-key operations]() page for more information.

Invoke the execution of a server-side Lua script.

The first argument is the script's source code.
Scripts are written in [Lua](https://lua.org) and executed by the embedded [Lua 5.1]() interpreter in Redis.

The second argument is the number of input key name arguments, followed by all the keys accessed by the script.
These names of input keys are available to the script as the [_KEYS_ global runtime variable]()
Any additional input arguments **should not** represent names of keys.

**Important:**
to ensure the correct execution of scripts, both in standalone and clustered deployments, all names of keys that a script accesses must be explicitly provided as input key arguments.
The script **should only** access keys whose names are given as input arguments.
Scripts **should never** access keys with programmatically-generated names or based on the contents of data structures stored in the database.

**Note:**
in some cases, users will abuse Lua EVAL by embedding values in the script instead of providing them as argument, and thus generating a different script on each call to EVAL.
These are added to the Lua interpreter and cached to redis-server, consuming a large amount of memory over time.
Starting from Redis 7.4, scripts loaded with `EVAL` or [`EVAL_RO`]() will be deleted from redis after a certain number (least recently used order).
The number of evicted scripts can be viewed through [`INFO`]()'s `evicted_scripts`.

Please refer to the [Redis Programmability]() and [Introduction to Eval Scripts]() for more information about Lua scripts.

title: Examples

text:
The following example will run a script that returns the first argument that it gets.

[code example]

title: Return information

text:
**RESP2:**

The return value depends on the script that was executed.

**RESP3:**

The return value depends on the script that was executed.

code:
> EVAL "return ARGV[1]" 0 hello
"hello"


title: EVAL_RO

summary: Executes a read-only server-side Lua script.

title: Overview

text:
This is a read-only variant of the [`EVAL`]() command that cannot execute commands that modify data.

For more information about when to use this command vs [`EVAL`](), please refer to [Read-only scripts]().

For more information about [`EVAL`]() scripts please refer to [Introduction to Eval Scripts]().

title: Examples

text: [code example]

title: Return information

code:
> SET mykey "Hello"
OK

> EVAL_RO "return redis.call('GET', KEYS[1])" 1 mykey
"Hello"

> EVAL_RO "return redis.call('DEL', KEYS[1])" 1 mykey
(error) ERR Error running script (call to b0d697da25b13e49157b2c214a4033546aba2104): @user_script:1: @user_script: 1: Write commands are not allowed from read-only scripts.


title: EVALSHA

summary: Executes a server-side Lua script by SHA1 digest.

title: Overview

text:
This command's behavior varies in clustered Redis environments. See the [multi-key operations]() page for more information.

Evaluate a script from the server's cache by its SHA1 digest.

The server caches scripts by using the [`SCRIPT LOAD`]() command.
The command is otherwise identical to [`EVAL`]().

Please refer to the [Redis Programmability]() and [Introduction to Eval Scripts]() for more information about Lua scripts.

title: Return information


title: EVALSHA_RO

summary: Executes a read-only server-side Lua script by SHA1 digest.

title: Overview

text:
This is a read-only variant of the [`EVALSHA`]() command that cannot execute commands that modify data.

For more information about when to use this command vs [`EVALSHA`](), please refer to [Read-only scripts]().

For more information about [`EVALSHA`]() scripts please refer to [Introduction to Eval Scripts]().

title: Return information


title: EXEC

summary: Executes all commands in a transaction.

title: Overview

text:
This command's behavior varies in clustered Redis environments. See the [multi-key operations]() page for more information.

Executes all previously queued commands in a [transaction][tt] and restores the
connection state to normal.

[tt]: /develop/interact/transactions

When using [`WATCH`](), `EXEC` will execute commands only if the watched keys were
not modified, allowing for a [check-and-set mechanism][ttc].

[ttc]: /develop/interact/transactions#cas

title: Return information

text:
**RESP2:**

One of the following:
* [Array reply](../../develop/reference/protocol-spec#arrays): each element being the reply to each of the commands in the atomic transaction.
* [Nil reply](../../develop/reference/protocol-spec#bulk-strings): the transaction was aborted because a `WATCH`ed key was touched.

**RESP3:**

One of the following:
* [Array reply](../../develop/reference/protocol-spec#arrays): each element being the reply to each of the commands in the atomic transaction.
* [Null reply](../../develop/reference/protocol-spec#nulls): the transaction was aborted because a `WATCH`ed key was touched.