title: KEYS

summary: Returns all key names that match a pattern.

title: Examples

text:
#### Code Examples

Returns all key names that match a pattern

**Difficulty:** Beginner

**Commands:** MSET, KEYS

**Complexity:**
- MSET: O(N)
- KEYS: 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:

MSET firstname Jack lastname Stuntman age 35
KEYS *name*
KEYS a??
KEYS *

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 keys matching _pattern_.

**RESP3:**

[Array reply](../../develop/reference/protocol-spec#arrays): a list of keys matching _pattern_.

code:
> MSET firstname Jack lastname Stuntman age 35
"OK"
> KEYS *name*
1) "lastname"
2) "firstname"
> KEYS a??
1) "age"
> KEYS *
1) "age"
2) "lastname"
3) "firstname"

section_id: examples

code:
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);

code:
bool keysResult1 = db.StringSet(
            new KeyValuePair<RedisKey, RedisValue>[] {
                new("firstname", "Jack"),
                new("lastname", "Stuntman"),
                new("age", "35")
            }
        );
        Console.WriteLine(keysResult1);  // >>> True

        IServer server = muxer.GetServer("localhost:6379");

        RedisKey[] keysResult2 = server.Keys(pattern: "*name*").ToArray();
        Array.Sort(keysResult2, (a, b) => a.ToString().CompareTo(b.ToString()));
        Console.WriteLine(string.Join(", ", keysResult2.Select(k => k.ToString())));  // >>> firstname, lastname

        RedisKey[] keysResult3 = server.Keys(pattern: "a??").ToArray();
        Console.WriteLine(string.Join(", ", keysResult3.Select(k => k.ToString())));  // >>> age

        RedisKey[] keysResult4 = server.Keys(pattern: "*").ToArray();
        Array.Sort(keysResult4, (a, b) => a.ToString().CompareTo(b.ToString()));
        Console.WriteLine(string.Join(", ", keysResult4.Select(k => k.ToString())));  // >>> age, firstname, lastname

code:
keysResult1, err := rdb.MSet(ctx, "firstname", "Jack", "lastname", "Stuntman", "age", "35").Result()

	if err != nil {
		panic(err)
	}

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

	keysResult2, err := rdb.Keys(ctx, "*name*").Result()

	if err != nil {
		panic(err)
	}

	sort.Strings(keysResult2)
	fmt.Println(keysResult2) // >>> [firstname lastname]

	keysResult3, err := rdb.Keys(ctx, "a??").Result()

	if err != nil {
		panic(err)
	}

	fmt.Println(keysResult3) // >>> [age]

	keysResult4, err := rdb.Keys(ctx, "*").Result()

	if err != nil {
		panic(err)
	}

	sort.Strings(keysResult4)
	fmt.Println(keysResult4) // >>> [age firstname lastname]

code:
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();

code:
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();

code:
String keysResult1 = jedis.mset("firstname", "Jack", "lastname", "Stuntman", "age", "35");
        System.out.println(keysResult1); // >>> OK

        Set<String> keysResult2 = jedis.keys("*name*");
        ArrayList<String> keysResult2List = new ArrayList<>(keysResult2);
        Collections.sort(keysResult2List);
        System.out.println(keysResult2List); // >>> [firstname, lastname]

        Set<String> keysResult3 = jedis.keys("a??");
        System.out.println(keysResult3); // >>> [age]

        Set<String> keysResult4 = jedis.keys("*");
        ArrayList<String> keysResult4List = new ArrayList<>(keysResult4);
        Collections.sort(keysResult4List);
        System.out.println(keysResult4List); // >>> [age, firstname, lastname]

code:
const keysRes1 = await client.mSet({ firstname: 'Jack', lastname: 'Stuntman', age: '35' });
console.log(keysRes1); // OK

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

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

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

code:
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']

code:
$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.mset({"firstname": "Jack", "lastname": "Stuntman", "age": "35"})
print(res)
# >>> True

res = r.keys("*name*")
print(sorted(res))
# >>> ['firstname', 'lastname']

res = r.keys("a??")
print(res)
# >>> ['age']

res = r.keys("*")
print(sorted(res))
# >>> ['age', 'firstname', 'lastname']

code:
match r.mset(&[("firstname", "Jack"), ("lastname", "Stuntman"), ("age", "35")]).await {
            Ok(res) => {
                let res: String = res;
                println!("{res}");    // >>> OK
            },
            Err(e) => {
                println!("Error setting keys: {e}");
                return;
            }
        }

        match r.keys::<&str, Vec<String>>("*name*").await {
            Ok(res) => {
                let mut sorted_res = res.clone();
                sorted_res.sort();
                println!("{sorted_res:?}");    // >>> ["firstname", "lastname"]
            },
            Err(e) => {
                println!("Error getting keys: {e}");
                return;
            }
        }

        match r.keys::<&str, Vec<String>>("a??").await {
            Ok(res) => {
                println!("{res:?}");    // >>> ["age"]
            },
            Err(e) => {
                println!("Error getting keys: {e}");
                return;
            }
        }

        match r.keys::<&str, Vec<String>>("*").await {
            Ok(res) => {
                let mut sorted_res = res.clone();
                sorted_res.sort();
                println!("{sorted_res:?}");    // >>> ["age", "firstname", "lastname"]
            },
            Err(e) => {
                println!("Error getting keys: {e}");
                return;
            }
        }

code:
match r.mset(&[("firstname", "Jack"), ("lastname", "Stuntman"), ("age", "35")]) {
            Ok(res) => {
                let res: String = res;
                println!("{res}");    // >>> OK
            },
            Err(e) => {
                println!("Error setting keys: {e}");
                return;
            }
        }

        match r.keys::<&str, Vec<String>>("*name*") {
            Ok(res) => {
                let mut sorted_res = res.clone();
                sorted_res.sort();
                println!("{sorted_res:?}");    // >>> ["firstname", "lastname"]
            },
            Err(e) => {
                println!("Error getting keys: {e}");
                return;
            }
        }

        match r.keys::<&str, Vec<String>>("a??") {
            Ok(res) => {
                println!("{res:?}");    // >>> ["age"]
            },
            Err(e) => {
                println!("Error getting keys: {e}");
                return;
            }
        }

        match r.keys::<&str, Vec<String>>("*") {
            Ok(res) => {
                let mut sorted_res = res.clone();
                sorted_res.sort();
                println!("{sorted_res:?}");    // >>> ["age", "firstname", "lastname"]
            },
            Err(e) => {
                println!("Error getting keys: {e}");
                return;
            }
        }


title: LASTSAVE

summary: Returns the Unix timestamp of the last successful save to disk.

page_type: content

title: Overview

role: overview

text:
Return the UNIX TIME of the last DB save executed with success.
A client may check if a [`BGSAVE`]() command succeeded reading the `LASTSAVE` value,
then issuing a [`BGSAVE`]() command and checking at regular intervals every N
seconds if `LASTSAVE` changed. Redis considers the database saved successfully at startup.

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:**

[Integer reply](../../develop/reference/protocol-spec#integers): UNIX TIME of the last DB save executed with success.

**RESP3:**

[Integer reply](../../develop/reference/protocol-spec#integers): UNIX TIME of the last DB save executed with success.


title: LATENCY

summary: A container for latency diagnostics commands.

title: Content

text:
This is a container command for latency diagnostics commands.

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


title: LATENCY DOCTOR

summary: Returns a human-readable latency analysis report.

title: Overview

text:
The `LATENCY DOCTOR` command reports about different latency-related issues and advises about possible remedies.

This command is the most powerful analysis tool in the latency monitoring
framework, and is able to provide additional statistical data like the average
period between latency spikes, the median deviation, and a human-readable
analysis of the event. For certain events, like `fork`, additional information
is provided, like the rate at which the system forks processes.

This is the output you should post in the Redis mailing list if you are
looking for help about Latency related issues.

title: Examples

role: example

text:
[code example]

**Note:** the doctor has erratic psychological behaviors, so we recommend interacting with it carefully.

For more information refer to the [Latency Monitoring Framework page][lm].

[lm]: /operate/oss_and_stack/management/optimization/latency-monitor.md

title: Return information

text:
**RESP2:**

[Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): a human readable latency analysis report.

**RESP3:**

[Verbatim string reply](../../develop/reference/protocol-spec#verbatim-strings): a human readable latency analysis report.

code:
127.0.0.1:6379> latency doctor

Dave, I have observed latency spikes in this Redis instance.
You don't mind talking about it, do you Dave?

1. command: 5 latency spikes (average 300ms, mean deviation 120ms,
    period 73.40 sec). Worst all time event 500ms.

I have a few advices for you:

- Your current Slow Log configuration only logs events that are
    slower than your configured latency monitor threshold. Please
    use 'CONFIG SET slowlog-log-slower-than 1000'.
- Check your Slow Log to understand what are the commands you are
    running which are too slow to execute. Please check
    http://redis.io/commands/slowlog for more information.
- Deleting, expiring or evicting (because of maxmemory policy)
    large objects is a blocking operation. If you have very large
    objects that are often deleted, expired, or evicted, try to
    fragment those objects into multiple smaller objects.


title: LATENCY GRAPH

summary: Returns a latency graph for an event.

title: Overview

text:
Produces an ASCII-art style graph for the specified event.

`LATENCY GRAPH` lets you intuitively understand the latency trend of an `event` via state-of-the-art visualization. It can be used for quickly grasping the situation before resorting to means such parsing the raw data from [`LATENCY HISTORY`]() or external tooling.

Valid values for `event` are:
* `active-defrag-cycle`
* `aof-fsync-always`
* `aof-stat`
* `aof-rewrite-diff-write`
* `aof-rename`
* `aof-write`
* `aof-write-active-child`
* `aof-write-alone`
* `aof-write-pending-fsync`
* `command`
* `expire-cycle`
* `eviction-cycle`
* `eviction-del`
* `fast-command`
* `fork`
* `rdb-unlink-temp-file`

title: Examples

text:
[code example]

The vertical labels under each graph column represent the amount of seconds,
minutes, hours or days ago the event happened. For example "15s" means that the
first graphed event happened 15 seconds ago.

The graph is normalized in the min-max scale so that the zero (the underscore
in the lower row) is the minimum, and a # in the higher row is the maximum.

For more information refer to the [Latency Monitoring Framework page][lm].

[lm]: /operate/oss_and_stack/management/optimization/latency-monitor.md

title: Return information

text:
**RESP2:**

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

**RESP3:**

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


title: LATENCY HELP

summary: Returns helpful text about the different subcommands.

title: Overview

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

For more information refer to the [Latency Monitoring Framework page][lm].

[lm]: /operate/oss_and_stack/management/optimization/latency-monitor.md

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: LATENCY HISTOGRAM

summary: Returns the cumulative distribution of latencies of a subset or all commands.

title: Overview

text:
`LATENCY HISTOGRAM` returns a cumulative distribution of commands' latencies in histogram format.

By default, all available latency histograms are returned.
You can filter the reply by providing specific command names.

Each histogram consists of the following fields:

* Command name
* The total calls for that command
* A map of time buckets:
  * Each bucket represents a latency range
  * Each bucket covers twice the previous bucket's range
  * Empty buckets are excluded from the reply
  * The tracked latencies are between 1 nanosecond and roughly 1 second
  * Everything above 1 second is considered +Inf
  * At max, there will be log2(1,000,000,000) = 30 buckets

This command requires the extended latency monitoring feature to be enabled, which is the default.
If you need to enable it, call `CONFIG SET latency-tracking yes`.

To delete the latency histograms' data use the [`CONFIG RESETSTAT`]() command.

title: Examples

text: [code example]

title: Return information

text:
**RESP2:**

[Array reply](../../develop/reference/protocol-spec#arrays): a map where each key is a command name, and each value is a map with the total calls, and an inner map of the histogram time buckets.

**RESP3:**

[Map reply](../../develop/reference/protocol-spec#maps): a map where each key is a command name, and each value is a map with the total calls, and an inner map of the histogram time buckets.

code:
127.0.0.1:6379> LATENCY HISTOGRAM set
1# "set" =>
   1# "calls" => (integer) 100000
   2# "histogram_usec" =>
      1# (integer) 1 => (integer) 99583
      2# (integer) 2 => (integer) 99852
      3# (integer) 4 => (integer) 99914
      4# (integer) 8 => (integer) 99940
      5# (integer) 16 => (integer) 99968
      6# (integer) 33 => (integer) 100000


title: LATENCY HISTORY

summary: Returns timestamp-latency samples for an event.

title: Overview

text:
The `LATENCY HISTORY` command returns the raw data of the `event`'s latency spikes time series.

This is useful to an application that wants to fetch raw data in order to perform monitoring, display graphs, and so forth.

The command will return up to 160 timestamp-latency pairs for the `event`.

Valid values for `event` are:
* `active-defrag-cycle`
* `aof-fsync-always`
* `aof-stat`
* `aof-rewrite-diff-write`
* `aof-rename`
* `aof-write`
* `aof-write-active-child`
* `aof-write-alone`
* `aof-write-pending-fsync`
* `command`
* `expire-cycle`
* `eviction-cycle`
* `eviction-del`
* `fast-command`
* `fork`
* `rdb-unlink-temp-file`

title: Examples

text:
[code example]

For more information refer to the [Latency Monitoring Framework page][lm].

[lm]: /operate/oss_and_stack/management/optimization/latency-monitor.md

title: Return information

text:
**RESP2:**

[Array reply](../../develop/reference/protocol-spec#arrays): an array where each element is a two elements array representing the timestamp and the latency of the event.

**RESP3:**

[Array reply](../../develop/reference/protocol-spec#arrays): an array where each element is a two elements array representing the timestamp and the latency of the event.


title: LATENCY LATEST

summary: Returns the latest latency samples for all events.

title: Overview

text:
The `LATENCY LATEST` command reports the latest latency events logged.

Each reported event has the following fields:

* Event name.
* Unix timestamp of the latest latency spike for the event.
* Latest event latency in millisecond.
* All-time maximum latency for this event.

"All-time" means the maximum latency since the Redis instance was
started, or the time that events were reset [`LATENCY RESET`]().

title: Examples

title: Return information

text:
**RESP2:**

[Array reply](../../develop/reference/protocol-spec#arrays): an array where each element is a four elements array representing the event's name, timestamp, latest and all-time latency measurements.

**RESP3:**

[Array reply](../../develop/reference/protocol-spec#arrays): an array where each element is a four elements array representing the event's name, timestamp, latest and all-time latency measurements.


title: LATENCY RESET

summary: Resets the latency data for one or more events.

title: Overview

text:
The `LATENCY RESET` command resets the latency spikes time series of all, or only some, events.

When the command is called without arguments, it resets all the
events, discarding the currently logged latency spike events, and resetting
the maximum event time register.

It is possible to reset only specific events by providing the `event` names
as arguments.

Valid values for `event` are:
* `active-defrag-cycle`
* `aof-fsync-always`
* `aof-stat`
* `aof-rewrite-diff-write`
* `aof-rename`
* `aof-write`
* `aof-write-active-child`
* `aof-write-alone`
* `aof-write-pending-fsync`
* `command`
* `expire-cycle`
* `eviction-cycle`
* `eviction-del`
* `fast-command`
* `fork`
* `rdb-unlink-temp-file`

For more information refer to the [Latency Monitoring Framework page][lm].

[lm]: /operate/oss_and_stack/management/optimization/latency-monitor.md

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 event time series that were reset.

**RESP3:**

[Integer reply](../../develop/reference/protocol-spec#integers): the number of event time series that were reset.


title: LCS

summary: Finds the longest common substring.

title: Overview

text:
The LCS command implements the longest common subsequence algorithm. Note that this is different than the longest common string algorithm, since matching characters in the string does not need to be contiguous.

For instance the LCS between "foo" and "fao" is "fo", since scanning the two strings from left to right, the longest common set of characters is composed of the first "f" and then the "o".

LCS is very useful in order to evaluate how similar two strings are. Strings can represent many things. For instance if two strings are DNA sequences, the LCS will provide a measure of similarity between the two DNA sequences. If the strings represent some text edited by some user, the LCS could represent how different the new text is compared to the old one, and so forth.

Note that this algorithm runs in `O(N*M)` time, where N is the length of the first string and M is the length of the second string. So either spin a different Redis instance in order to run this algorithm, or make sure to run it against very small strings.

[code example]

Sometimes we need just the length of the match:

[code example]

However what is often very useful, is to know the match position in each strings:

[code example]

Matches are produced from the last one to the first one, since this is how
the algorithm works, and it more efficient to emit things in the same order.
The above array means that the first match (second element of the array)
is between positions 2-3 of the first string and 0-1 of the second.
Then there is another match between 4-7 and 5-8.

To restrict the list of matches to the ones of a given minimal length:

[code example]

Finally to also have the match len:

[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 longest common subsequence.
* [Integer reply](../../develop/reference/protocol-spec#integers): the length of the longest common subsequence when _LEN_ is given.
* [Array reply](../../develop/reference/protocol-spec#arrays): an array with the LCS length and all the ranges in both the strings when _IDX_ is given.

**RESP3:**

One of the following:
* [Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): the longest common subsequence.
* [Integer reply](../../develop/reference/protocol-spec#integers): the length of the longest common subsequence when _LEN_ is given.
* [Map reply](../../develop/reference/protocol-spec#maps): a map with the LCS length and all the ranges in both the strings when _IDX_ is given.

code:
> MSET key1 ohmytext key2 mynewtext
OK
> LCS key1 key2
"mytext"

section_id: overview

code:
> LCS key1 key2 LEN
(integer) 6

code:
> LCS key1 key2 IDX
1) "matches"
2) 1) 1) 1) (integer) 4
         2) (integer) 7
      2) 1) (integer) 5
         2) (integer) 8
   2) 1) 1) (integer) 2
         2) (integer) 3
      2) 1) (integer) 0
         2) (integer) 1
3) "len"
4) (integer) 6

code:
> LCS key1 key2 IDX MINMATCHLEN 4
1) "matches"
2) 1) 1) 1) (integer) 4
         2) (integer) 7
      2) 1) (integer) 5
         2) (integer) 8
3) "len"
4) (integer) 6

code:
> LCS key1 key2 IDX MINMATCHLEN 4 WITHMATCHLEN
1) "matches"
2) 1) 1) 1) (integer) 4
         2) (integer) 7
      2) 1) (integer) 5
         2) (integer) 8
      3) (integer) 4
3) "len"
4) (integer) 6


title: LINDEX

summary: Returns an element from a list by its index.

title: Overview

text:
Returns the element at index `index` in the list stored at `key`.
The index is zero-based, so `0` means the first element, `1` the second element
and so on.
Negative indices can be used to designate elements starting at the tail of the
list.
Here, `-1` means the last element, `-2` means the penultimate and so forth.

When the value at `key` is not a list, an error is returned.

title: Examples

text:
LPUSH mylist "World"
LPUSH mylist "Hello"
LINDEX mylist 0
LINDEX mylist -1
LINDEX mylist 3

title: Return information

text:
**RESP2:**

One of the following:
* [Nil reply](../../develop/reference/protocol-spec#bulk-strings): when _index_ is out of range.
* [Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): the requested element.

**RESP3:**

One of the following:
* [Null reply](../../develop/reference/protocol-spec#nulls): when _index_ is out of range.
* [Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): the requested element.


title: LINSERT

summary: Inserts an element before or after another element in a list.

title: Overview

text:
Inserts `element` in the list stored at `key` either before or after the reference
value `pivot`.

When `key` does not exist, it is considered an empty list and no operation is
performed.

An error is returned when `key` exists but does not hold a list value.

title: Examples

text:
RPUSH mylist "Hello"
RPUSH mylist "World"
LINSERT mylist BEFORE "World" "There"
LRANGE mylist 0 -1

title: Return information

text:
**RESP2:**

One of the following:
* [Integer reply](../../develop/reference/protocol-spec#integers): the list length after a successful insert operation.
* [Integer reply](../../develop/reference/protocol-spec#integers): `0` when the key doesn't exist.
* [Integer reply](../../develop/reference/protocol-spec#integers): `-1` when the pivot wasn't found.

**RESP3:**

One of the following:
* [Integer reply](../../develop/reference/protocol-spec#integers): the list length after a successful insert operation.
* [Integer reply](../../develop/reference/protocol-spec#integers): `0` when the key doesn't exist.
* [Integer reply](../../develop/reference/protocol-spec#integers): `-1` when the pivot wasn't found.


title: LLEN

summary: Returns the length of a list.

title: Examples

text:
#### Code Examples

Foundational: Get the length of a list using LLEN (returns 0 if key doesn't exist, useful for checking list size)

**Difficulty:** Beginner

**Commands:** LPUSH, LLEN

**Complexity:**
- LPUSH: O(1)
- LLEN: O(1)

**Redis CLI:**

[code example]

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

**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]

**PHP:**

[code example]

**Python:**

[code example]

Give these commands a try in the interactive console:

LPUSH mylist "World"
LPUSH mylist "Hello"
LLEN mylist

title: Return information

text:
**RESP2:**

[Integer reply](../../develop/reference/protocol-spec#integers): the length of the list.

**RESP3:**

[Integer reply](../../develop/reference/protocol-spec#integers): the length of the list.

code:
redis> LPUSH mylist "World"
(integer) 1
redis> LPUSH mylist "Hello"
(integer) 2
redis> LLEN mylist
(integer) 2

code:
long lLenResult1 = db.ListLeftPush("mylist", "World");
        Console.WriteLine(lLenResult1); // >>> 1

        long lLenResult2 = db.ListLeftPush("mylist", "Hello");
        Console.WriteLine(lLenResult2); // >>> 2

        long lLenResult3 = db.ListLength("mylist");
        Console.WriteLine(lLenResult3); // >>> 2

code:
lPushResult1, err := rdb.LPush(ctx, "mylist", "World").Result()

	if err != nil {
		panic(err)
	}

	fmt.Println(lPushResult1) // >>> 1

	lPushResult2, err := rdb.LPush(ctx, "mylist", "Hello").Result()

	if err != nil {
		panic(err)
	}

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

	lLenResult, err := rdb.LLen(ctx, "mylist").Result()

	if err != nil {
		panic(err)
	}

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

code:
CompletableFuture<Void> llen = asyncCommands.lpush("mylist", "World").thenCompose(res11 -> {
                System.out.println(res11); // >>> 1

                return asyncCommands.lpush("mylist", "Hello");
            }).thenCompose(res12 -> {
                System.out.println(res12); // >>> 2

                return asyncCommands.llen("mylist");
            })
                    .thenAccept(res13 -> System.out.println(res13)) // >>> 2
                    .toCompletableFuture();

code:
Mono<Void> llen = reactiveCommands.lpush("mylist", "World").doOnNext(res11 -> {
                System.out.println(res11); // >>> 1
            }).flatMap(res11 -> reactiveCommands.lpush("mylist", "Hello")).doOnNext(res12 -> {
                System.out.println(res12); // >>> 2
            }).flatMap(res12 -> reactiveCommands.llen("mylist")).doOnNext(res13 -> {
                System.out.println(res13); // >>> 2
            }).then();

code:
long lLenResult1 = jedis.lpush("mylist", "World");
        System.out.println(lLenResult1); // >>> 1

        long lLenResult2 = jedis.lpush("mylist", "Hello");
        System.out.println(lLenResult2); // >>> 2

        long lLenResult3 = jedis.llen("mylist");
        System.out.println(lLenResult3); // >>> 2

code:
const res11 = await client.lPush('mylist', 'World');
console.log(res11); // 1

const res12 = await client.lPush('mylist', 'Hello');
console.log(res12); // 2

const res13 = await client.lLen('mylist');
console.log(res13); // 2

code:
$res11 = $r->lpush('mylist', 'World');
        echo $res11 . PHP_EOL;
        // >>> 1

        $res12 = $r->lpush('mylist', 'Hello');
        echo $res12 . PHP_EOL;
        // >>> 2

        $res13 = $r->llen('mylist');
        echo $res13 . PHP_EOL;
        // >>> 2

code:
res11 = r.lpush("mylist", "World")
print(res11) # >>> 1

res12 = r.lpush("mylist", "Hello")
print(res12) # >>> 2

res13 = r.llen("mylist")
print(res13)  # >>> 2


title: LMOVE

summary: Returns an element after popping it from one list and pushing it to another. Deletes the list if the last element was moved.

title: Overview

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

Atomically returns and removes the first/last element (head/tail depending on
the `wherefrom` argument) of the list stored at `source`, and pushes the
element at the first/last element (head/tail depending on the `whereto`
argument) of the list stored at `destination`.

For example: consider `source` holding the list `a,b,c`, and `destination`
holding the list `x,y,z`.
Executing `LMOVE source destination RIGHT LEFT` results in `source` holding
`a,b` and `destination` holding `c,x,y,z`.

If `source` does not exist, the value `nil` is returned and no operation is
performed.
If `source` and `destination` are the same, the operation is equivalent to
removing the first/last element from the list and pushing it as first/last
element of the list, so it can be considered as a list rotation command (or a
no-op if `wherefrom` is the same as `whereto`).

This command comes in place of the now deprecated [`RPOPLPUSH`](). Doing
`LMOVE RIGHT LEFT` is equivalent.

title: Examples

text:
RPUSH mylist "one"
RPUSH mylist "two"
RPUSH mylist "three"
LMOVE mylist myotherlist RIGHT LEFT
LMOVE mylist myotherlist LEFT RIGHT
LRANGE mylist 0 -1
LRANGE myotherlist 0 -1

title: Pattern: Reliable queue

text:
Redis is often used as a messaging server to implement processing of background
jobs or other kinds of messaging tasks.
A simple form of queue is often obtained pushing values into a list in the
producer side, and waiting for this values in the consumer side using [`RPOP`]()
(using polling), or [`BRPOP`]() if the client is better served by a blocking
operation.

However in this context the obtained queue is not _reliable_ as messages can
be lost, for example in the case there is a network problem or if the consumer
crashes just after the message is received but it is still to process.

`LMOVE` (or [`BLMOVE`]() for the blocking variant) offers a way to avoid
this problem: the consumer fetches the message and at the same time pushes it
into a _processing_ list.
It will use the [`LREM`]() command in order to remove the message from the
_processing_ list once the message has been processed.

An additional client may monitor the _processing_ list for items that remain
there for too much time, and will push those timed out items into the queue
again if needed.

title: Pattern: Circular list

text:
Using `LMOVE` with the same source and destination key, a client can visit
all the elements of an N-elements list, one after the other, in O(N) without
transferring the full list from the server to the client using a single [`LRANGE`]()
operation.

The above pattern works even in the following conditions:

* There are multiple clients rotating the list: they'll fetch different
  elements, until all the elements of the list are visited, and the process
  restarts.
* Even if other clients are actively pushing new items at the end of the list.

The above makes it very simple to implement a system where a set of items must
be processed by N workers continuously as fast as possible.
An example is a monitoring system that must check that a set of web sites are
reachable, with the smallest delay possible, using a number of parallel workers.

Note that this implementation of workers is trivially scalable and reliable,
because even if a message is lost the item is still in the queue and will be
processed at the next iteration.

title: Return information

text:
**RESP2:**

[Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): the element being popped and pushed.

**RESP3:**

[Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): the element being popped and pushed.


title: LMPOP

summary: Returns multiple elements from a list after removing them. Deletes the list if the last element was popped.

title: Overview

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

Pops one or more elements from the first non-empty list key from the list of provided key names.

`LMPOP` and [`BLMPOP`]() are similar to the following, more limited, commands:

- [`LPOP`]() or [`RPOP`]() which take only one key, and can return multiple elements.
- [`BLPOP`]() or [`BRPOP`]() which take multiple keys, but return only one element from just one key.

See [`BLMPOP`]() for the blocking variant of this command.

Elements are popped from either the left or right of the first non-empty list based on the passed argument.
The number of returned elements is limited to the lower between the non-empty list's length, and the count argument (which defaults to 1).

title: Examples

text:
LMPOP 2 non1 non2 LEFT COUNT 10
LPUSH mylist "one" "two" "three" "four" "five"
LMPOP 1 mylist LEFT
LRANGE mylist 0 -1
LMPOP 1 mylist RIGHT COUNT 10
LPUSH mylist "one" "two" "three" "four" "five"
LPUSH mylist2 "a" "b" "c" "d" "e"
LMPOP 2 mylist mylist2 right count 3
LRANGE mylist 0 -1
LMPOP 2 mylist mylist2 right count 5
LMPOP 2 mylist mylist2 right count 10
EXISTS mylist mylist2

title: Return information

text:
**RESP2:**

One of the following:
* [Nil reply](../../develop/reference/protocol-spec#bulk-strings): if no element could be popped.
* [Array reply](../../develop/reference/protocol-spec#arrays): a two-element array with the first element being the name of the key from which elements were popped and the second element being an array of elements.

**RESP3:**

One of the following:
* [Null reply](../../develop/reference/protocol-spec#nulls): if no element could be popped.
* [Array reply](../../develop/reference/protocol-spec#arrays): a two-element array with the first element being the name of the key from which elements were popped and the second element being an array of elements.


title: LOLWUT

summary: Displays computer art and the Redis version

title: Overview

text:
The LOLWUT command displays the Redis version: however as a side effect of
doing so, it also creates a piece of generative computer art that is different
with each version of Redis. The command was introduced in Redis 5 and announced
with this [blog post](http://antirez.com/news/123).

By default the `LOLWUT` command will display the piece corresponding to the
current Redis version, however it is possible to display a specific version
using the following form:

    LOLWUT VERSION 5 ... other optional arguments ...

Of course the "5" above is an example. Each LOLWUT version takes a different
set of arguments in order to change the output. The user is encouraged to
play with it to discover how the output changes adding more numerical
arguments.

LOLWUT wants to be a reminder that there is more in programming than just
putting some code together in order to create something useful. Every
LOLWUT version should have the following properties:

1. It should display some computer art. There are no limits as long as the output works well in a normal terminal display. However the output should not be limited to graphics (like LOLWUT 5 and 6 actually do), but can be generative poetry and other non graphical things.
2. LOLWUT output should be completely useless. Displaying some useful Redis internal metrics does not count as a valid LOLWUT.
3. LOLWUT output should be fast to generate so that the command can be called in production instances without issues. It should remain fast even when the user experiments with odd parameters.
4. LOLWUT implementations should be safe and carefully checked for security, and resist to untrusted inputs if they take arguments.
5. LOLWUT must always display the Redis version at the end.

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

title: Return information

text:
**RESP2:**

[Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): a string containing generative computer art and the Redis version.

**RESP3:**

[Verbatim string reply](../../develop/reference/protocol-spec#verbatim-strings): a string containing generative computer art and the Redis version.


title: LPOP

summary: Returns the first elements in a list after removing it. Deletes the list if the last element was popped.

title: Examples

text:
#### Code Examples

Foundational: Remove and return the first element(s) from a list using LPOP (supports optional count parameter to pop multiple elements)

**Difficulty:** Beginner

**Commands:** RPUSH, LPOP, LRANGE

**Complexity:**
- RPUSH: O(1)
- LPOP: O(N)
- LRANGE: O(S+N)

**Redis CLI:**

[code example]

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

**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]

**PHP:**

[code example]

**Python:**

[code example]

Give these commands a try in the interactive console:

RPUSH mylist "one" "two" "three" "four" "five"
LPOP mylist
LPOP mylist 2
LRANGE mylist 0 -1

title: Return information

text:
**RESP2:**

One of the following:
* [Nil reply](../../develop/reference/protocol-spec#bulk-strings): if the key does not exist.
* [Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): when called without the _count_ argument, the value of the first element.
* [Array reply](../../develop/reference/protocol-spec#arrays): when called with the _count_ argument, a list of popped elements.

**RESP3:**

One of the following:
* [Null reply](../../develop/reference/protocol-spec#nulls): if the key does not exist.
* [Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): when called without the _count_ argument, the value of the first element.
* [Array reply](../../develop/reference/protocol-spec#arrays): when called with the _count_ argument, a list of popped elements.

code:
redis> RPUSH mylist "one" "two" "three" "four" "five"
(integer) 5
redis> LPOP mylist
"one"
redis> LPOP mylist 2
1) "two"
2) "three"
redis> LRANGE mylist 0 -1
1) "four"
2) "five"

code:
long lPopResult1 = db.ListRightPush("mylist", ["one", "two", "three", "four", "five"]);
        Console.WriteLine(lPopResult1); // >>> 5

        RedisValue lPopResult2 = db.ListLeftPop("mylist");
        Console.WriteLine(lPopResult2); // >>> one

        RedisValue[] lPopResult3 = db.ListLeftPop("mylist", 2);
        Console.WriteLine($"[{string.Join(", ", lPopResult3)}]");
        // >>> [two, three]

        RedisValue[] lPopResult4 = db.ListRange("mylist", 0, -1);
        Console.WriteLine($"[{string.Join(", ", lPopResult4)}]");
        // >>> [four, five]

code:
RPushResult, err := rdb.RPush(ctx,
		"mylist", "one", "two", "three", "four", "five",
	).Result()

	if err != nil {
		panic(err)
	}

	fmt.Println(RPushResult) // >>> 5

	lPopResult, err := rdb.LPop(ctx, "mylist").Result()

	if err != nil {
		panic(err)
	}

	fmt.Println(lPopResult) // >>> one

	lPopCountResult, err := rdb.LPopCount(ctx, "mylist", 2).Result()

	if err != nil {
		panic(err)
	}

	fmt.Println(lPopCountResult) // >>> [two three]

	lRangeResult, err := rdb.LRange(ctx, "mylist", 0, -1).Result()

	if err != nil {
		panic(err)
	}

	fmt.Println(lRangeResult) // >>> [four five]

code:
CompletableFuture<Void> lpop = asyncCommands.rpush("mylist", "one", "two", "three", "four", "five")
                    .thenCompose(res17 -> {
                        System.out.println(res17); // >>> 5

                        return asyncCommands.lpop("mylist");
                    }).thenCompose(res18 -> {
                        System.out.println(res18); // >>> one

                        return asyncCommands.lpop("mylist", 2);
                    }).thenCompose(res19 -> {
                        System.out.println(res19); // >>> [two, three]

                        return asyncCommands.lrange("mylist", 0, -1);
                    })
                    .thenAccept(res17_final -> System.out.println(res17_final)) // >>> [four, five]
                    .toCompletableFuture();

code:
Mono<Void> lpop = reactiveCommands.rpush("mylist", "one", "two", "three", "four", "five").doOnNext(res17 -> {
                System.out.println(res17); // >>> 5
            }).flatMap(res17 -> reactiveCommands.lpop("mylist")).doOnNext(res18 -> {
                System.out.println(res18); // >>> one
            }).flatMap(res18 -> reactiveCommands.lpop("mylist", 2).collectList()).doOnNext(res19 -> {
                System.out.println(res19); // >>> [two, three]
            }).flatMap(res19 -> reactiveCommands.lrange("mylist", 0, -1).collectList()).doOnNext(res17_final -> {
                System.out.println(res17_final); // >>> [four, five]
            }).then();

code:
long lPopResult1 = jedis.rpush(
            "mylist", "one", "two", "three", "four", "five"
        );
        System.out.println(lPopResult1); // >>> 5

        String lPopResult2 = jedis.lpop("mylist");
        System.out.println(lPopResult2); // >>> one

        List<String> lPopResult3 = jedis.lpop("mylist", 2);
        System.out.println(lPopResult3); // >>> [two, three]

        List<String> lPopResult4 = jedis.lrange("mylist", 0, -1);
        System.out.println(lPopResult4); // >>> [four, five]

code:
const res17 = await client.rPush('mylist', ["one", "two", "three", "four", "five"]);
console.log(res17); // 5

const res18 = await client.lPop('mylist');
console.log(res18); // 'one'

const res19 = await client.lPopCount('mylist', 2);
console.log(res19); // [ 'two', 'three' ]

const res20 = await client.lRange('mylist', 0, -1);
console.log(res20); // [ 'four', 'five' ]

code:
$res17 = $r->rpush('mylist', 'one', 'two', 'three', 'four', 'five');
        echo $res17 . PHP_EOL;
        // >>> 5

        $res18 = $r->lpop('mylist');
        echo $res18 . PHP_EOL;
        // >>> one

        $res19 = $r->lpop('mylist', 2);
        echo json_encode($res19) . PHP_EOL;
        // >>> ["two","three"]

        $res20 = $r->lrange('mylist', 0, -1);
        echo json_encode($res20) . PHP_EOL;
        // >>> ["four","five"]

code:
res17 = r.rpush("mylist", *["one", "two", "three", "four", "five"])
print(res17) # >>> 5

res18 = r.lpop("mylist")
print(res18) # >>> "one"

res19 = r.lpop("mylist", 2)
print(res19) # >>> ['two', 'three']

res17 = r.lrange("mylist", 0, -1)
print(res17)  # >>> [ "four", "five" ]


title: LPOS

summary: Returns the index of matching elements in a list.

title: Overview

text:
The command returns the index of matching elements inside a Redis list.
By default, when no options are given, it will scan the list from head to tail,
looking for the first match of "element". If the element is found, its index (the zero-based position in the list) is returned. Otherwise, if no match is found, `nil` is returned.

[code example]

The optional arguments and options can modify the command's behavior.
The `RANK` option specifies the "rank" of the first element to return, in case there are multiple matches. A rank of 1 means to return the first match, 2 to return the second match, and so forth.

For instance, in the above example the element "c" is present multiple times, if I want the index of the second match, I'll write:

[code example]

That is, the second occurrence of "c" is at position 6.
A negative "rank" as the `RANK` argument tells `LPOS` to invert the search direction, starting from the tail to the head.

So, we want to say, give me the first element starting from the tail of the list:

[code example]

Note that the indexes are still reported in the "natural" way, that is, considering the first element starting from the head of the list at index 0, the next element at index 1, and so forth. This basically means that the returned indexes are stable whatever the rank is positive or negative.

Sometimes we want to return not just the Nth matching element, but the position of all the first N matching elements. This can be achieved using the `COUNT` option.

[code example]

We can combine `COUNT` and `RANK`, so that `COUNT` will try to return up to the specified number of matches, but starting from the Nth match, as specified by the `RANK` option.

[code example]

When `COUNT` is used, it is possible to specify 0 as the number of matches, as a way to tell the command we want all the matches found returned as an array of indexes. This is better than giving a very large `COUNT` option because it is more general.

[code example]

When `COUNT` is used and no match is found, an empty array is returned. However when `COUNT` is not used and there are no matches, the command returns `nil`.

Finally, the `MAXLEN` option tells the command to compare the provided element only with a given maximum number of list items. So for instance specifying `MAXLEN 1000` will make sure that the command performs only 1000 comparisons, effectively running the algorithm on a subset of the list (the first part or the last part depending on the fact we use a positive or negative rank). This is useful to limit the maximum complexity of the command. It is also useful when we expect the match to be found very early, but want to be sure that in case this is not true, the command does not take too much time to run.

When `MAXLEN` is used, it is possible to specify 0 as the maximum number of comparisons, as a way to tell the command we want unlimited comparisons. This is better than giving a very large `MAXLEN` option because it is more general.

title: Examples

text:
RPUSH mylist a b c d 1 2 3 4 3 3 3
LPOS mylist 3
LPOS mylist 3 COUNT 0 RANK 2

title: Return information

text:
**RESP2:**

Any of the following:
* [Nil reply](../../develop/reference/protocol-spec#bulk-strings): if there is no matching element.
* [Integer reply](../../develop/reference/protocol-spec#integers): an integer representing the matching element.
* [Array reply](../../develop/reference/protocol-spec#arrays): If the COUNT option is given, an array of integers representing the matching elements (or an empty array if there are no matches).

**RESP3:**

Any of the following:
* [Null reply](../../develop/reference/protocol-spec#nulls): if there is no matching element.
* [Integer reply](../../develop/reference/protocol-spec#integers): an integer representing the matching element.
* [Array reply](../../develop/reference/protocol-spec#arrays): If the COUNT option is given, an array of integers representing the matching elements (or an empty array if there are no matches).

code:
> RPUSH mylist a b c 1 2 3 c c
> LPOS mylist c
2

code:
> LPOS mylist c RANK 2
6

code:
> LPOS mylist c RANK -1
7

code:
> LPOS mylist c COUNT 2
[2,6]

code:
> LPOS mylist c RANK -1 COUNT 2
[7,6]

code:
> LPOS mylist c COUNT 0
[2,6,7]


title: LPUSH

summary: Prepends one or more elements to a list. Creates the key if it doesn't exist.

title: Examples

text:
#### Code Examples

Foundational: Add one or more elements to the head of a list using LPUSH (creates list if needed, returns new list length)

**Difficulty:** Beginner

**Commands:** LPUSH, LRANGE

**Complexity:**
- LPUSH: O(1)
- LRANGE: O(S+N)

**Redis CLI:**

[code example]

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

**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]

**PHP:**

[code example]

**Python:**

[code example]

Give these commands a try in the interactive console:

LPUSH mylist "world"
LPUSH mylist "hello"
LRANGE mylist 0 -1

title: Return information

text:
**RESP2:**

[Integer reply](../../develop/reference/protocol-spec#integers): the length of the list after the push operation.

**RESP3:**

[Integer reply](../../develop/reference/protocol-spec#integers): the length of the list after the push operation.

code:
redis> LPUSH mylist "world"
(integer) 1
redis> LPUSH mylist "hello"
(integer) 2
redis> LRANGE mylist 0 -1
1) "hello"
2) "world"

code:
long lPushResult1 = db.ListLeftPush("mylist", "World");
        Console.WriteLine(lPushResult1); // >>> 1

        long lPushResult2 = db.ListLeftPush("mylist", "Hello");
        Console.WriteLine(lPushResult2); // >>> 2

        RedisValue[] lPushResult3 = db.ListRange("mylist", 0, -1);
        Console.WriteLine($"[{string.Join(", ", lPushResult3)}]");
        // >>> [Hello, World]

code:
lPushResult1, err := rdb.LPush(ctx, "mylist", "World").Result()

	if err != nil {
		panic(err)
	}

	fmt.Println(lPushResult1) // >>> 1

	lPushResult2, err := rdb.LPush(ctx, "mylist", "Hello").Result()

	if err != nil {
		panic(err)
	}

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

	lRangeResult, err := rdb.LRange(ctx, "mylist", 0, -1).Result()

	if err != nil {
		panic(err)
	}

	fmt.Println(lRangeResult) // >>> [Hello World]

code:
CompletableFuture<Void> lpush = asyncCommands.lpush("mylist", "world").thenCompose(res1 -> {
                System.out.println(res1); // >>> 1

                return asyncCommands.lpush("mylist", "hello");
            }).thenCompose(res2 -> {
                System.out.println(res2); // >>> 2

                return asyncCommands.lrange("mylist", 0, -1);
            })
                    .thenAccept(res3 -> System.out.println(res3)) // >>> [hello, world]
                    .toCompletableFuture();

code:
Mono<Void> lpush = reactiveCommands.lpush("mylist", "world").doOnNext(res1 -> {
                System.out.println(res1); // >>> 1
            }).flatMap(res1 -> reactiveCommands.lpush("mylist", "hello")).doOnNext(res2 -> {
                System.out.println(res2); // >>> 2
            }).flatMap(res2 -> reactiveCommands.lrange("mylist", 0, -1).collectList()).doOnNext(res3 -> {
                System.out.println(res3); // >>> [hello, world]
            }).then();

code:
long lPushResult1 = jedis.lpush("mylist", "World");
        System.out.println(lPushResult1); // >>> 1

        long lPushResult2 = jedis.lpush("mylist", "Hello");
        System.out.println(lPushResult2); // >>> 2

        List<String> lPushResult3 = jedis.lrange("mylist", 0, -1);
        System.out.println(lPushResult3);
        // >>> [Hello, World]

code:
const res1 = await client.lPush('mylist', 'world');
console.log(res1); // 1

const res2 = await client.lPush('mylist', 'hello');
console.log(res2); // 2

const res3 = await client.lRange('mylist', 0, -1);
console.log(res3); // [ 'hello', 'world' ]

code:
$res1 = $r->lpush('mylist', 'world');
        echo $res1 . PHP_EOL;
        // >>> 1

        $res2 = $r->lpush('mylist', 'hello');
        echo $res2 . PHP_EOL;
        // >>> 2

        $res3 = $r->lrange('mylist', 0, -1);
        echo json_encode($res3) . PHP_EOL;
        // >>> ["hello","world"]

code:
res1 = r.lpush("mylist", "world")
print(res1) # >>> 1

res2 = r.lpush("mylist", "hello")
print(res2) # >>> 2

res3 = r.lrange("mylist", 0, -1)
print(res3)  # >>> [ "hello", "world" ]


title: LPUSHX

summary: Prepends one or more elements to a list only when the list exists.

title: Overview

text:
Inserts specified values at the head of the list stored at `key`, only if `key`
already exists and holds a list.
In contrary to [`LPUSH`](), no operation will be performed when `key` does not yet
exist.

title: Examples

text:
LPUSH mylist "World"
LPUSHX mylist "Hello"
LPUSHX myotherlist "Hello"
LRANGE mylist 0 -1
LRANGE myotherlist 0 -1

title: Return information


title: LRANGE

summary: Returns a range of elements from a list.

title: Consistency with range functions in various programming languages

text:
Note that if you have a list of numbers from 0 to 100, `LRANGE list 0 10` will
return 11 elements, that is, the rightmost item is included.
This **may or may not** be consistent with behavior of range-related functions
in your programming language of choice (think Ruby's `Range.new`, `Array#slice`
or Python's `range()` function).

title: Out-of-range indexes

text:
Out of range indexes will not produce an error.
If `start` is larger than the end of the list, an empty list is returned.
If `stop` is larger than the actual end of the list, Redis will treat it like
the last element of the list.

title: Examples

text:
#### Code Examples

Foundational: Retrieve a range of elements from a list using LRANGE with start and stop indexes (supports negative indexes, inclusive range)

**Difficulty:** Beginner

**Commands:** RPUSH, LRANGE

**Complexity:**
- RPUSH: O(1)
- LRANGE: O(S+N)

**Redis CLI:**

[code example]

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

**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]

**PHP:**

[code example]

**Python:**

[code example]

Give these commands a try in the interactive console:

RPUSH mylist "one"
RPUSH mylist "two"
RPUSH mylist "three"
LRANGE mylist 0 0
LRANGE mylist -3 2
LRANGE mylist -100 100
LRANGE mylist 5 10

title: Return information

text:
**RESP2:**

[Array reply](../../develop/reference/protocol-spec#arrays): a list of elements in the specified range, or an empty array if the key doesn't exist.

**RESP3:**

[Array reply](../../develop/reference/protocol-spec#arrays): a list of elements in the specified range, or an empty array if the key doesn't exist.

code:
redis> RPUSH mylist "one"
(integer) 1
redis> RPUSH mylist "two"
(integer) 2
redis> RPUSH mylist "three"
(integer) 3
redis> LRANGE mylist 0 0
1) "one"
redis> LRANGE mylist -3 2
1) "one"
2) "two"
3) "three"
redis> LRANGE mylist -100 100
1) "one"
2) "two"
3) "three"
redis> LRANGE mylist 5 10
(empty array)

code:
long lRangeResult1 = db.ListRightPush("mylist", ["one", "two", "three"]);
        Console.WriteLine(lRangeResult1); // >>> 3

        RedisValue[] lRangeResult2 = db.ListRange("mylist", 0, 0);
        Console.WriteLine($"[{string.Join(", ", lRangeResult2)}]");
        // >>> [one]

        RedisValue[] lRangeResult3 = db.ListRange("mylist", -3, 2);
        Console.WriteLine($"[{string.Join(", ", lRangeResult3)}]");
        // >>> [one, two, three]

        RedisValue[] lRangeResult4 = db.ListRange("mylist", -100, 100);
        Console.WriteLine($"[{string.Join(", ", lRangeResult4)}]");
        // >>> [one, two, three]

        RedisValue[] lRangeResult5 = db.ListRange("mylist", 5, 10);
        Console.WriteLine($"[{string.Join(", ", lRangeResult5)}]");
        // >>> []

code:
RPushResult, err := rdb.RPush(ctx, "mylist",
		"one", "two", "three",
	).Result()

	if err != nil {
		panic(err)
	}

	fmt.Println(RPushResult) // >>> 3

	lRangeResult1, err := rdb.LRange(ctx, "mylist", 0, 0).Result()

	if err != nil {
		panic(err)
	}

	fmt.Println(lRangeResult1) // >>> [one]

	lRangeResult2, err := rdb.LRange(ctx, "mylist", -3, 2).Result()

	if err != nil {
		panic(err)
	}

	fmt.Println(lRangeResult2) // >>> [one two three]

	lRangeResult3, err := rdb.LRange(ctx, "mylist", -100, 100).Result()

	if err != nil {
		panic(err)
	}

	fmt.Println(lRangeResult3) // >>> [one two three]

	lRangeResult4, err := rdb.LRange(ctx, "mylist", 5, 10).Result()

	if err != nil {
		panic(err)
	}

	fmt.Println(lRangeResult4) // >>> []

code:
CompletableFuture<Void> lrange = asyncCommands.rpush("mylist", "one").thenCompose(res4 -> {
                System.out.println(res4); // >>> 1

                return asyncCommands.rpush("mylist", "two");
            }).thenCompose(res5 -> {
                System.out.println(res5); // >>> 2

                return asyncCommands.rpush("mylist", "three");
            }).thenCompose(res6 -> {
                System.out.println(res6); // >>> 3

                return asyncCommands.lrange("mylist", 0, 0);
            }).thenCompose(res7 -> {
                System.out.println(res7); // >>> [one]

                return asyncCommands.lrange("mylist", -3, 2);
            }).thenCompose(res8 -> {
                System.out.println(res8); // >>> [one, two, three]

                return asyncCommands.lrange("mylist", -100, 100);
            }).thenCompose(res9 -> {
                System.out.println(res9); // >>> [one, two, three]

                return asyncCommands.lrange("mylist", 5, 10);
            })
                    .thenAccept(res10 -> System.out.println(res10)) // >>> []
                    .toCompletableFuture();

code:
Mono<Void> lrange = reactiveCommands.rpush("mylist", "one").doOnNext(res4 -> {
                System.out.println(res4); // >>> 1
            }).flatMap(res4 -> reactiveCommands.rpush("mylist", "two")).doOnNext(res5 -> {
                System.out.println(res5); // >>> 2
            }).flatMap(res5 -> reactiveCommands.rpush("mylist", "three")).doOnNext(res6 -> {
                System.out.println(res6); // >>> 3
            }).flatMap(res6 -> reactiveCommands.lrange("mylist", 0, 0).collectList()).doOnNext(res7 -> {
                System.out.println(res7); // >>> [one]
            }).flatMap(res7 -> reactiveCommands.lrange("mylist", -3, 2).collectList()).doOnNext(res8 -> {
                System.out.println(res8); // >>> [one, two, three]
            }).flatMap(res8 -> reactiveCommands.lrange("mylist", -100, 100).collectList()).doOnNext(res9 -> {
                System.out.println(res9); // >>> [one, two, three]
            }).flatMap(res9 -> reactiveCommands.lrange("mylist", 5, 10).collectList()).doOnNext(res10 -> {
                System.out.println(res10); // >>> []
            }).then();

code:
long lRangeResult1 = jedis.rpush("mylist", "one", "two", "three");
        System.out.println(lRangeResult1); // >>> 3

        List<String> lRangeResult2 = jedis.lrange("mylist", 0, 0);
        System.out.println(lRangeResult2); // >>> [one]

        List<String> lRangeResult3 = jedis.lrange("mylist", -3, 2);
        System.out.println(lRangeResult3); // >>> [one, two, three]

        List<String> lRangeResult4 = jedis.lrange("mylist", -100, 100);
        System.out.println(lRangeResult4); // >>> [one, two, three]

        List<String> lRangeResult5 = jedis.lrange("mylist", 5, 10);
        System.out.println(lRangeResult5); // >>> []

code:
const res4 = await client.rPush('mylist', 'one');
console.log(res4); // 1

const res5 = await client.rPush('mylist', 'two');
console.log(res5); // 2

const res6 = await client.rPush('mylist', 'three');
console.log(res6); // 3

const res7 = await client.lRange('mylist', 0, 0);
console.log(res7); // [ 'one' ]

const res8 = await client.lRange('mylist', -3, 2);
console.log(res8); // [ 'one', 'two', 'three' ]

const res9 = await client.lRange('mylist', -100, 100);
console.log(res9); // [ 'one', 'two', 'three' ]

const res10 = await client.lRange('mylist', 5, 10);
console.log(res10); // []

code:
$res4 = $r->rpush('mylist', 'one');
        echo $res4 . PHP_EOL;
        // >>> 1

        $res5 = $r->rpush('mylist', 'two');
        echo $res5 . PHP_EOL;
        // >>> 2

        $res6 = $r->rpush('mylist', 'three');
        echo $res6 . PHP_EOL;
        // >>> 3

        $res7 = $r->lrange('mylist', 0, 0);
        echo json_encode($res7) . PHP_EOL;
        // >>> ["one"]

        $res8 = $r->lrange('mylist', -3, 2);
        echo json_encode($res8) . PHP_EOL;
        // >>> ["one","two","three"]

        $res9 = $r->lrange('mylist', -100, 100);
        echo json_encode($res9) . PHP_EOL;
        // >>> ["one","two","three"]

        $res10 = $r->lrange('mylist', 5, 10);
        echo json_encode($res10) . PHP_EOL;
        // >>> []

code:
res4 = r.rpush("mylist", "one");
print(res4) # >>> 1

res5 = r.rpush("mylist", "two")
print(res5) # >>> 2

res6 = r.rpush("mylist", "three")
print(res6) # >>> 3

res7 = r.lrange('mylist', 0, 0)
print(res7) # >>> [ 'one' ]

res8 = r.lrange('mylist', -3, 2)
print(res8) # >>> [ 'one', 'two', 'three' ]

res9 = r.lrange('mylist', -100, 100)
print(res9) # >>> [ 'one', 'two', 'three' ]

res10 = r.lrange('mylist', 5, 10)
print(res10) # >>> []


title: LREM

summary: Removes elements from a list. Deletes the list if the last element was removed.

title: Overview

text:
Removes the first `count` occurrences of elements equal to `element` from the list
stored at `key`.
The `count` argument influences the operation in the following ways:

* `count > 0`: Remove elements equal to `element` moving from head to tail.
* `count < 0`: Remove elements equal to `element` moving from tail to head.
* `count = 0`: Remove all elements equal to `element`.

For example, `LREM list -2 "hello"` will remove the last two occurrences of
`"hello"` in the list stored at `list`.

Note that non-existing keys are treated like empty lists, so when `key` does not
exist, the command will always return `0`.

title: Examples

text:
RPUSH mylist "hello"
RPUSH mylist "hello"
RPUSH mylist "foo"
RPUSH mylist "hello"
LREM mylist -2 "hello"
LRANGE mylist 0 -1

title: Return information

text:
**RESP2:**

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

**RESP3:**

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


title: LSET

summary: Sets the value of an element in a list by its index.

title: Overview

text:
Sets the list element at `index` to `element`.
For more information on the `index` argument, see [`LINDEX`]().

An error is returned for out of range indexes.

title: Examples

text:
RPUSH mylist "one"
RPUSH mylist "two"
RPUSH mylist "three"
LSET mylist 0 "four"
LSET mylist -2 "five"
LRANGE mylist 0 -1

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): `OK`.

**RESP3:**

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


title: LTRIM

summary: Removes elements from both ends a list. Deletes the list if all elements were trimmed.

title: Overview

text:
Trim an existing list so that it will contain only the specified range of
elements specified.
Both `start` and `stop` are zero-based indexes, where `0` is the first element
of the list (the head), `1` the next element and so on.

For example: `LTRIM foobar 0 2` will modify the list stored at `foobar` so that
only the first three elements of the list will remain.

`start` and `end` can also be negative numbers indicating offsets from the end
of the list, where `-1` is the last element of the list, `-2` the penultimate
element and so on.

Out of range indexes will not produce an error: if `start` is larger than the
end of the list, or `start > end`, the result will be an empty list (which
causes `key` to be removed).
If `end` is larger than the end of the list, Redis will treat it like the last
element of the list.

A common use of `LTRIM` is together with [`LPUSH`]() / [`RPUSH`]().
For example:

[code example]

This pair of commands will push a new element on the list, while making sure
that the list will not grow larger than 100 elements.
This is very useful when using Redis to store logs for example.
It is important to note that when used in this way `LTRIM` is an O(1) operation
because in the average case just one element is removed from the tail of the
list.

title: Examples

text:
RPUSH mylist "one"
RPUSH mylist "two"
RPUSH mylist "three"
LTRIM mylist 1 -1
LRANGE mylist 0 -1

title: Return information

code:
LPUSH mylist someelement
LTRIM mylist 0 99


title: MEMORY

summary: A container for memory diagnostics commands.

title: Content

text:
This is a container command for memory introspection and management commands.

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


title: MEMORY DOCTOR

summary: Outputs a memory problems report.

title: Overview

text:
The `MEMORY DOCTOR` command reports about different memory-related issues that
the Redis server experiences, and advises about possible remedies.

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

title: Return information

text:
**RESP2:**

[Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): a memory problems report.

**RESP3:**

[Verbatim string reply](../../develop/reference/protocol-spec#verbatim-strings): a memory problems report.


title: MEMORY HELP

summary: Returns helpful text about the different subcommands.

title: Overview

text:
The `MEMORY 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> | Not supported for [scripts]() in Redis versions earlier than 7. |

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: MEMORY MALLOC-STATS

summary: Returns the allocator statistics.

title: Overview

text:
The `MEMORY MALLOC-STATS` command provides an internal statistics report from
the memory allocator.

This command is currently implemented only when using **jemalloc** as an
allocator, and evaluates to a benign NOOP for all others.

title: Return information

text:
**RESP2:**

[Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): a long string of statistics.

**RESP3:**

[Verbatim string reply](../../develop/reference/protocol-spec#verbatim-strings): a long string of statistics.


title: MEMORY PURGE

summary: Asks the allocator to release memory.

title: Overview

text:
The `MEMORY PURGE` command attempts to purge dirty pages so these can be
reclaimed by the allocator.

This command is currently implemented only when using **jemalloc** as an
allocator, and evaluates to a benign NOOP for all others.

title: Return information


title: MEMORY STATS

summary: Returns details about memory usage.

title: Overview

text:
The `MEMORY STATS` command returns an [Array reply]() about the memory usage of the
server.

The information about memory usage is provided as metrics and their respective
values. The following metrics are reported:

*   `peak.allocated`: Peak memory consumed by Redis in bytes (see [`INFO`]()'s
     `used_memory_peak`)
*   `total.allocated`: Total number of bytes allocated by Redis using its
     allocator (see [`INFO`]()'s `used_memory`)
*   `startup.allocated`: Initial amount of memory consumed by Redis at startup
     in bytes (see [`INFO`]()'s `used_memory_startup`)
*   `replication.backlog`: Size in bytes of the replication backlog (see
     [`INFO`]()'s `repl_backlog_active`)
*   `clients.slaves`: The total size in bytes of all replicas overheads (output
     and query buffers, connection contexts)
*   `clients.normal`: The total size in bytes of all clients overheads (output
     and query buffers, connection contexts)
*   `cluster.links`: Memory usage by cluster links (Added in Redis 7.0, see [`INFO`]()'s `mem_cluster_links`).
*   `aof.buffer`: The summed size in bytes of AOF related buffers.
*   `lua.caches`: the summed size in bytes of the overheads of the Lua scripts'
     caches
*   `functions.caches`: the summed size in bytes of the overheads of the Function scripts'
     caches
*   `dbXXX`: For each of the server's databases, the overheads of the main and
     expiry dictionaries (`overhead.hashtable.main` and
    `overhead.hashtable.expires`, respectively) are reported in bytes
*   `overhead.db.hashtable.lut`: Total overhead of dictionary buckets in databases (Added in Redis 7.4)
*   `overhead.db.hashtable.rehashing`: Temporary memory overhead of database dictionaries currently being rehashed (Added in Redis 7.4)
*   `overhead.total`: The sum of all overheads, i.e. `startup.allocated`,
     `replication.backlog`, `clients.slaves`, `clients.normal`, `aof.buffer` and
     those of the internal data structures that are used in managing the
     Redis keyspace (see [`INFO`]()'s `used_memory_overhead`)
*   `db.dict.rehashing.count`: Number of DB dictionaries currently being rehashed (Added in Redis 7.4)
*   `keys.count`: The total number of keys stored across all databases in the
     server
*   `keys.bytes-per-key`: The ratio between `dataset.bytes` and `keys.count`
*   `dataset.bytes`: The size in bytes of the dataset, i.e. `overhead.total`
     subtracted from `total.allocated` (see [`INFO`]()'s `used_memory_dataset`)
*   `dataset.percentage`: The percentage of `dataset.bytes` out of the total
     memory usage
*   `peak.percentage`: The percentage of `total.allocated` out of
     `peak.allocated`
*   `allocator.allocated`: See [`INFO`]()'s `allocator_allocated`
*   `allocator.active`: See [`INFO`]()'s `allocator_active`
*   `allocator.resident`: See [`INFO`]()'s `allocator_resident`
*   `allocator.muzzy`: See [`INFO`]()'s `allocator_muzzy`
*   `allocator-fragmentation.ratio`: See [`INFO`]()'s `allocator_frag_ratio`
*   `allocator-fragmentation.bytes`: See [`INFO`]()'s `allocator_frag_bytes`
*   `allocator-rss.ratio`: See [`INFO`]()'s `allocator_rss_ratio`
*   `allocator-rss.bytes`: See [`INFO`]()'s `allocator_rss_bytes`
*   `rss-overhead.ratio`: See [`INFO`]()'s `rss_overhead_ratio`
*   `rss-overhead.bytes`: See [`INFO`]()'s `rss_overhead_bytes`
*   `fragmentation`: See [`INFO`]()'s `mem_fragmentation_ratio`
*   `fragmentation.bytes`: See [`INFO`]()'s `mem_fragmentation_bytes`

**A note about the word slave used in this man page**: 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.

title: Return information

text:
**RESP2:**

[Array reply](../../develop/reference/protocol-spec#arrays): a nested list of memory usage metrics and their values.

**RESP3:**

[Map reply](../../develop/reference/protocol-spec#maps): memory usage metrics and their values.


title: MEMORY USAGE

summary: Estimates the memory usage of a key.

title: Overview

text:
The `MEMORY USAGE` command reports the number of bytes that a key and its value
require to be stored in RAM.

The reported usage is the total of memory allocations for data and
administrative overheads that a key and its value require.

For nested data types, the optional `SAMPLES` option can be provided, where
`count` is the number of sampled nested values. The samples are averaged to estimate the total size.
By default, this option is set to `5`. To sample the all of the nested values, use `SAMPLES 0`.

title: Examples

text:
With Redis v7.2.0 64-bit and **jemalloc**, the empty string measures as follows:

[code example]

These bytes are pure overhead at the moment as no actual data is stored, and are
used for maintaining the internal data structures of the server (include internal allocator fragmentation). Longer keys and
values show asymptotically linear usage.

[code example]

text:
| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
|✅ Standard
<nobr>✅ Active-Active</nobr> | ✅ Standard
<nobr>✅ Active-Active</nobr> | Not supported for [scripts]() in Redis versions earlier than 7. |

Note: key memory usage is different on Redis Software or Redis Cloud active-active databases than on non-active-active databases. This is because memory usage includes some amount of CRDB overhead.

title: Return information

text:
**RESP2:**

One of the following:
* [Integer reply](../../develop/reference/protocol-spec#integers): the memory usage in bytes.
* [Nil reply](../../develop/reference/protocol-spec#bulk-strings): if the key does not exist.

**RESP3:**

One of the following:
* [Integer reply](../../develop/reference/protocol-spec#integers): the memory usage in bytes.
* [Null reply](../../develop/reference/protocol-spec#nulls): if the key does not exist.

code:
> SET "" ""
OK
> MEMORY USAGE ""
(integer) 56


title: MGET

summary: Atomically returns the string values of one or more keys.

title: Examples

text:
#### Code Examples

Returns the values of all specified keys.

**Difficulty:** Beginner

**Commands:** SET, MGET

**Complexity:**
- SET: O(1)
- MGET: 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"
MGET key1 key2 nonexisting

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 values at the specified keys.

**RESP3:**

[Array reply](../../develop/reference/protocol-spec#arrays): a list of values at the specified keys.

code:
> SET key1 "Hello"
"OK"
> SET key2 "World"
"OK"
> MGET key1 key2 nonexisting
1) "Hello"
2) "World"
3) (nil)

code:
redisReply *reply = redisCommand(c, "SET key1 Hello");
    freeReplyObject(reply);

    reply = redisCommand(c, "SET key2 World");
    freeReplyObject(reply);

    reply = redisCommand(c, "MGET key1 key2 nonexisting");

    for (size_t i = 0; i < reply->elements; i++) {
        if (i > 0) {
            printf(", ");
        }

        if (reply->element[i]->type == REDIS_REPLY_NIL) {
            printf("null");
        } else {
            printf("%s", reply->element[i]->str);
        }
    }
    printf("\n");
    // >>> Hello, World, null

code:
bool mgetResult1 = db.StringSet("key1", "Hello");
        bool mgetResult2 = db.StringSet("key2", "World");

        RedisValue[] mgetResult3 = db.StringGet(new RedisKey[] { "key1", "key2", "nonexisting" });
        Console.WriteLine(string.Join(", ", mgetResult3.Select(v => v.IsNull ? "null" : v.ToString())));
        // >>> Hello, World, null

code:
if err := rdb.Set(ctx, "key1", "Hello", 0).Err(); err != nil {
		panic(err)
	}

	if err := rdb.Set(ctx, "key2", "World", 0).Err(); err != nil {
		panic(err)
	}

	mgetResult, err := rdb.MGet(ctx, "key1", "key2", "nonexisting").Result()
	if err != nil {
		panic(err)
	}

	fmt.Println(mgetResult) // >>> [Hello World <nil>]

code:
CompletableFuture<Void> mgetExample = asyncCommands.set("key1", "Hello")
                    .thenCompose(res1 -> asyncCommands.set("key2", "World"))
                    .thenCompose(res2 -> asyncCommands.mget("key1", "key2", "nonexisting"))
                    .thenAccept(res3 -> {
                        System.out.println(res3);
                        // >>> [KeyValue[key1, Hello], KeyValue[key2, World], KeyValue[nonexisting, null]]
                    })
                    .toCompletableFuture();

code:
Mono<Void> mgetExample = reactiveCommands.set("key1", "Hello")
                    .flatMap(res1 -> reactiveCommands.set("key2", "World"))
                    .flatMap(res2 -> reactiveCommands.mget("key1", "key2", "nonexisting").collectList())
                    .doOnNext(res3 -> {
                        System.out.println(res3);
                        // >>> [KeyValue[key1, Hello], KeyValue[key2, World], KeyValue[nonexisting, null]]
                    })
                    .then();

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

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

        java.util.List<String> mgetResult3 = jedis.mget("key1", "key2", "nonexisting");
        System.out.println(mgetResult3);    // >>> [Hello, World, null]

code:
await client.set('key1', 'Hello');
await client.set('key2', 'World');

const mgetResult = await client.mGet(['key1', 'key2', 'nonexisting']);
console.log(mgetResult); // >>> [ 'Hello', 'World', null ]

code:
await redis.set('key1', 'Hello');
await redis.set('key2', 'World');

const mgetResult = await redis.mget('key1', 'key2', 'nonexisting');
console.log(mgetResult); // >>> ['Hello', 'World', null]

code:
$r->set('key1', 'Hello');
        $r->set('key2', 'World');

        $mgetResult = $r->mget(['key1', 'key2', 'nonexisting']);
        echo json_encode($mgetResult) . PHP_EOL; // >>> ["Hello","World",null]

code:
r.set("key1", "Hello")
r.set("key2", "World")

mget_result = r.mget("key1", "key2", "nonexisting")
print(mget_result)
# >>> ['Hello', 'World', None]

code:
if let Ok(res) = r.set("key1", "Hello").await {
            let _: String = res;
        }

        if let Ok(res) = r.set("key2", "World").await {
            let _: String = res;
        }

        match r.mget(&["key1", "key2", "nonexisting"]).await {
            Ok(mget_result) => {
                let mget_result: Vec<Option<String>> = mget_result;
                println!("{mget_result:?}");    // >>> [Some("Hello"), Some("World"), None]
            }
            Err(e) => {
                println!("Error getting values: {e}");
            }
        }

code:
if let Ok(res) = r.set("key1", "Hello") {
            let _: String = res;
        }

        if let Ok(res) = r.set("key2", "World") {
            let _: String = res;
        }

        match r.mget(&["key1", "key2", "nonexisting"]) {
            Ok(mget_result) => {
                let mget_result: Vec<Option<String>> = mget_result;
                println!("{mget_result:?}");    // >>> [Some("Hello"), Some("World"), None]
            }
            Err(e) => {
                println!("Error getting values: {e}");
            }
        }


title: MIGRATE

summary: Atomically transfers a key from one Redis instance to another.

title: Overview

text:
Atomically transfer a key from a source Redis instance to a destination Redis
instance.
On success the key is deleted from the original instance and is guaranteed to
exist in the target instance.

The command is atomic and blocks the two instances for the time required to
transfer the key, at any given time the key will appear to exist in a given
instance or in the other instance, unless a timeout error occurs. In 3.2 and
above, multiple keys can be pipelined in a single call to `MIGRATE` by passing
the empty string ("") as key and adding the `KEYS` clause.

The command internally uses [`DUMP`]() to generate the serialized version of the key
value, and [`RESTORE`]() in order to synthesize the key in the target instance.
The source instance acts as a client for the target instance.
If the target instance returns OK to the [`RESTORE`]() command, the source instance
deletes the key using [`DEL`]().

The timeout specifies the maximum idle time in any moment of the communication
with the destination instance in milliseconds.
This means that the operation does not need to be completed within the specified
amount of milliseconds, but that the transfer should make progresses without
blocking for more than the specified amount of milliseconds.

`MIGRATE` needs to perform I/O operations and to honor the specified timeout.
When there is an I/O error during the transfer or if the timeout is reached the
operation is aborted and the special error - `IOERR` returned.
When this happens the following two cases are possible:

* The key may be on both the instances.
* The key may be only in the source instance.

It is not possible for the key to get lost in the event of a timeout, but the
client calling `MIGRATE`, in the event of a timeout error, should check if the
key is _also_ present in the target instance and act accordingly.

When any other error is returned (starting with `ERR`) `MIGRATE` guarantees that
the key is still only present in the originating instance (unless a key with the
same name was also _already_ present on the target instance).

If there are no keys to migrate in the source instance `NOKEY` is returned.
Because missing keys are possible in normal conditions, from expiry for example,
`NOKEY` isn't an error.

title: Migrating multiple keys with a single command call

text:
Starting with Redis 3.0.6 `MIGRATE` supports a new bulk-migration mode that
uses pipelining in order to migrate multiple keys between instances without
incurring in the round trip time latency and other overheads that there are
when moving each key with a single `MIGRATE` call.

In order to enable this form, the `KEYS` option is used, and the normal *key*
argument is set to an empty string. The actual key names will be provided
after the `KEYS` argument itself, like in the following example:

    MIGRATE 192.168.1.34 6379 "" 0 5000 KEYS key1 key2 key3

When this form is used the `NOKEY` status code is only returned when none
of the keys is present in the instance, otherwise the command is executed, even if
just a single key exists.

title: Options

role: parameters

text:
* `COPY` -- Do not remove the key from the local instance.
* `REPLACE` -- Replace existing key on the remote instance.
* `KEYS` -- If the key argument is an empty string, the command will instead migrate all the keys that follow the `KEYS` option (see the above section for more info).
* `AUTH` -- Authenticate with the given password to the remote instance.
* `AUTH2` -- Authenticate with the given username and password pair (Redis 6 or greater ACL auth style).

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:
* [Simple string reply](../../develop/reference/protocol-spec#simple-strings): `OK` on success.
* [Simple string reply](../../develop/reference/protocol-spec#simple-strings): `NOKEY` when no keys were found in the source instance.

**RESP3:**

One of the following:
* [Simple string reply](../../develop/reference/protocol-spec#simple-strings): `OK` on success.
* [Simple string reply](../../develop/reference/protocol-spec#simple-strings): `NOKEY` when no keys were found in the source instance.


title: MODULE

summary: A container for module commands.

title: Content

text:
This is a container command for module management commands.

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


title: MODULE HELP

title: Overview

text: The `MODULE 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: MODULE LIST

summary: Returns all loaded modules.

title: Overview

text: Returns information about the modules loaded to the server.

title: Return information

text:
**RESP2:**

[Array reply](../../develop/reference/protocol-spec#arrays): list of loaded modules. Each element in the list represents a represents a module, and is in itself a list of property names and their values. The following properties is reported for each loaded module:
* name: the name of the module.
* ver: the version of the module.

**RESP3:**

[Array reply](../../develop/reference/protocol-spec#arrays): list of loaded modules. Each element in the list represents a represents a module, and is a [Map reply](../../develop/reference/protocol-spec#maps) of property names and their values. The following properties is reported for each loaded module:
* name: the name of the module.
* ver: the version of the module.


title: MODULE LOAD

summary: Loads a module.

title: Overview

text:
Loads a module from a dynamic library at runtime.

This command loads and initializes the Redis module from the dynamic library
specified by the `path` argument. The `path` should be the absolute path of the
library, including the full filename. Any additional arguments are passed
unmodified to the module.

**Note**: modules can also be loaded at server startup with `loadmodule`
configuration directive in `redis.conf`.

As of Redis 8 in Redis Open Source, loading a module using the Redis CLI with configuration parameters is deprecated.

title: Return information

text:
**RESP2:**

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

**RESP3:**

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


title: MODULE LOADEX

summary: Loads a module using extended parameters.

title: Overview

text:
Loads a module from a dynamic library at runtime with configuration directives.

This is an extended version of the [`MODULE LOAD`]() command.

It loads and initializes the Redis module from the dynamic library specified by the `path` argument. The `path` should be the absolute path of the library, including the full filename.

You can use the optional `CONFIG` argument to provide the module with configuration directives.
Any additional arguments that follow the `ARGS` keyword are passed unmodified to the module.

**Note**: modules can also be loaded at server startup with `loadmodule`
configuration directive in `redis.conf`.

title: Return information


title: MODULE UNLOAD

summary: Unloads a module.

title: Overview

text:
Unloads a module.

This command unloads the module specified by `name`. Note that the module's name
is reported by the [`MODULE LIST`]() command, and may differ from the dynamic
library's filename.

Known limitations:

*   Modules that register custom data types can not be unloaded.

title: Return information

text:
**RESP2:**

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

**RESP3:**

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


title: MONITOR

summary: Listens for all requests received by the server in real-time.

title: Overview

text:
`MONITOR` is a debugging command that streams back every command processed by
the Redis server.
It can help in understanding what is happening to the database.
This command can both be used via `redis-cli` and via `telnet`.

The ability to see all the requests processed by the server is useful in order
to spot bugs in an application both when using Redis as a database and as a
distributed caching system.

[code example]

Use `SIGINT` (Ctrl-C) to stop a `MONITOR` stream running via `redis-cli`.

[code example]

Manually issue the [`QUIT`]() or [`RESET`]() commands to stop a `MONITOR` stream running
via `telnet`.

title: Commands not logged by MONITOR

role: syntax

text:
Because of security concerns, no administrative commands are logged
by `MONITOR`'s output and sensitive data is redacted in the command [`AUTH`]().

Furthermore, the command [`QUIT`]() is also not logged.

title: Cost of running MONITOR

text:
Because `MONITOR` streams back **all** commands, its use comes at a cost.
The following (totally unscientific) benchmark numbers illustrate what the cost
of running `MONITOR` can be.

Benchmark result **without** `MONITOR` running:

[code example]

Benchmark result **with** `MONITOR` running (`redis-cli monitor > /dev/null`):

[code example]

In this particular case, running a single `MONITOR` client can reduce the
throughput by more than 50%.
Running more `MONITOR` clients will reduce throughput even more.

title: Behavior change history

text:
*   `>= 6.0.0`: [`AUTH`]() excluded from the command's output.
*   `>= 6.2.0`: "[`RESET`]() can be called to exit monitor mode.
*   `>= 6.2.4`: "[`AUTH`](), [`HELLO`](), [`EVAL`](), [`EVAL_RO`](), [`EVALSHA`]() and [`EVALSHA_RO`]() included in the command's output.

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

title: Return information

text:
**RESP2:**

**Non-standard return value**. Dumps the received commands in an infinite flow.

**RESP3:**

**Non-standard return value**. Dumps the received commands in an infinite flow.

code:
$ src/redis-benchmark -c 10 -n 100000 -q
PING_INLINE: 101936.80 requests per second
PING_BULK: 102880.66 requests per second
SET: 95419.85 requests per second
GET: 104275.29 requests per second
INCR: 93283.58 requests per second

section_id: cost-of-running-monitor

code:
$ src/redis-benchmark -c 10 -n 100000 -q
PING_INLINE: 58479.53 requests per second
PING_BULK: 59136.61 requests per second
SET: 41823.50 requests per second
GET: 45330.91 requests per second
INCR: 41771.09 requests per second


title: MOVE

summary: Moves a key to another database.

title: Overview

text:
Move `key` from the currently selected database (see [`SELECT`]()) to the specified
destination database.
When `key` already exists in the destination database, or it does not exist in
the source database, it does nothing.
It is possible to use `MOVE` as a locking primitive because of this.

text:
| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ❌ Standard
<nobr>❌ Active-Active</nobr> | ❌ Standard
<nobr>❌ Active-Active</nobr> | Redis Software does not support shared databases due to potential negative performance impacts and blocks any related commands. |

title: Return information

text:
**RESP2:**

One of the following:
* [Integer reply](../../develop/reference/protocol-spec#integers): `1` if _key_ was moved.
* [Integer reply](../../develop/reference/protocol-spec#integers): `0` if _key_ wasn't moved.

**RESP3:**

One of the following:
* [Integer reply](../../develop/reference/protocol-spec#integers): `1` if _key_ was moved.
* [Integer reply](../../develop/reference/protocol-spec#integers): `0` if _key_ wasn't moved.


title: MSET

summary: Atomically creates or modifies the string values of one or more keys.

title: Overview

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

Sets the given keys to their respective values.
`MSET` replaces existing values with new values, just as regular [`SET`]().
See [`MSETNX`]() if you don't want to overwrite existing values.

`MSET` is atomic, so all given keys are set at once.
It is not possible for clients to see that some of the keys were updated while
others are unchanged.

title: Examples

text:
MSET key1 "Hello" key2 "World"
GET key1
GET key2

title: Return information

text:
**RESP2:**

[Simple string reply](../../develop/reference/protocol-spec#simple-strings): always `OK` because `MSET` can't fail.

**RESP3:**

[Simple string reply](../../develop/reference/protocol-spec#simple-strings): always `OK` because `MSET` can't fail.


title: MSETEX

summary: Atomically sets multiple string keys with a shared expiration in a single operation. Supports flexible argument parsing where condition and expiration flags can appear in any order.

title: Overview

text: Atomically sets multiple string keys with an optional shared expiration in a single operation.

title: Required arguments

text:
numkeys

The number of keys being set.

key value [key value ...]

A series of key/value pairs.

title: Optional arguments

text:
condition and expiration flags

The `MSETEX` command supports a set of options that modify its behavior:

* `NX` -- Set the keys and their expiration time only if none of the specified keys exist.
* `XX` -- Set the keys and their expiration time only if all of the specified keys already exist.
* `EX seconds` -- Set the specified expiration time in seconds (a positive integer).
* `PX milliseconds` -- Set the specified expiration time in milliseconds (a positive integer).
* `EXAT unix-time-seconds` -- Set the specified Unix time in seconds (a positive integer) at which the key(s) will expire.
* `PXAT unix-time-milliseconds` -- Set the specified Unix time in milliseconds (a positive integer) at which the key(s) will expire.
* `KEEPTTL` -- Retain the time to live associated with the keys.

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

title: Return information

text:
**RESP2:**

[Integer reply](): 0 if none of the keys were set; 1 if all of the keys were set.

**RESP3:**

[Integer reply](): 0 if none of the keys were set; 1 if all of the keys were set.