Commands
- acl-cat
- acl-delrole
- acl-deluser
- acl-digest
- acl-dryrun
- acl-genpass
- acl-getrole
- acl-getuser
- acl-help
- acl-list
- acl-load
- acl-log
- acl-roles
- acl-save
- acl-setrole
- acl-setuser
- acl-users
- acl-whoami
- acl
- append
- asking
- auth
- bf.add
- bf.card
- bf.exists
- bf.info
- bf.insert
- bf.load
- bf.madd
- bf.mexists
- bf.reserve
- bgrewriteaof
- bgsave
- bitcount
- bitfield
- bitfield_ro
- bitop
- bitpos
- blmove
- blmpop
- blpop
- brpop
- brpoplpush
- bzmpop
- bzpopmax
- bzpopmin
- client-caching
- client-capa
- client-getname
- client-getredir
- client-help
- client-id
- client-import-source
- client-info
- client-kill
- client-list
- client-no-evict
- client-no-touch
- client-pause
- client-reply
- client-setinfo
- client-setname
- client-tracking
- client-trackinginfo
- client-unblock
- client-unpause
- client
- cluster-addslots
- cluster-addslotsrange
- cluster-bumpepoch
- cluster-cancelslotmigrations
- cluster-count-failure-reports
- cluster-countkeysinslot
- cluster-delslots
- cluster-delslotsrange
- cluster-failover
- cluster-flushslots
- cluster-forget
- cluster-getkeysinslot
- cluster-getslotmigrations
- cluster-help
- cluster-info
- cluster-keyslot
- cluster-links
- cluster-meet
- cluster-migrateslots
- cluster-myid
- cluster-myshardid
- cluster-nodes
- cluster-replicas
- cluster-replicate
- cluster-reset
- cluster-saveconfig
- cluster-set-config-epoch
- cluster-setslot
- cluster-shards
- cluster-slaves
- cluster-slot-stats
- cluster-slots
- cluster-syncslots
- cluster
- clusterscan
- command-count
- command-docs
- command-getkeys
- command-getkeysandflags
- command-help
- command-info
- command-list
- command
- commandlog-get
- commandlog-help
- commandlog-len
- commandlog-reset
- commandlog
- config-get
- config-help
- config-resetstat
- config-rewrite
- config-set
- config
- copy
- dbsize
- debug
- decr
- decrby
- del
- delex
- delifeq
- discard
- dump
- echo
- eval
- eval_ro
- evalsha
- evalsha_ro
- exec
- exists
- expire
- expireat
- expiretime
- failover
- fcall
- fcall_ro
- flushall
- flushdb
- ft._list
- ft.aggregate
- ft.create
- ft.cursor
- ft.dropindex
- ft.hybrid
- ft.info
- ft.search
- function-delete
- function-dump
- function-flush
- function-help
- function-kill
- function-list
- function-load
- function-restore
- function-stats
- function
- geoadd
- geodist
- geohash
- geopos
- georadius
- georadius_ro
- georadiusbymember
- georadiusbymember_ro
- geosearch
- geosearchstore
- get
- getbit
- getdel
- getex
- getrange
- getset
- hdel
- hello
- hexists
- hexpire
- hexpireat
- hexpiretime
- hget
- hgetall
- hgetdel
- hgetex
- hincrby
- hincrbyfloat
- hkeys
- hlen
- hmget
- hmset
- hpersist
- hpexpire
- hpexpireat
- hpexpiretime
- hpttl
- hrandfield
- hscan
- hset
- hsetex
- hsetnx
- hstrlen
- httl
- hvals
- incr
- incrby
- incrbyfloat
- info
- json.arrappend
- json.arrindex
- json.arrinsert
- json.arrlen
- json.arrpop
- json.arrtrim
- json.clear
- json.debug
- json.del
- json.forget
- json.get
- json.mget
- json.mset
acl-cat
The command shows the available ACL categories if called without arguments. If a category name is given, the command shows all the Valkey commands in the specified category.
ACL categories are very useful in order to create ACL rules that include or
exclude a large set of commands at once, without specifying every single
command. For instance, the following rule will let the user karin perform
everything but the most dangerous operations that may affect the server
stability:
ACL SETUSER karin on +@all -@dangerous
We first add all the commands to the set of commands that karin is able
to execute, but then we remove all the dangerous commands.
Checking for all the available categories is as simple as:
> ACL CAT
1) "keyspace"
2) "read"
3) "write"
4) "set"
5) "sortedset"
6) "list"
7) "hash"
8) "string"
9) "bitmap"
10) "hyperloglog"
11) "geo"
12) "stream"
13) "pubsub"
14) "admin"
15) "fast"
16) "slow"
17) "blocking"
18) "dangerous"
19) "connection"
20) "transaction"
21) "scripting"
Then we may want to know what commands are part of a given category:
> ACL CAT dangerous
1) "flushdb"
2) "acl"
3) "slowlog"
4) "debug"
5) "role"
6) "keys"
7) "pfselftest"
8) "client"
9) "bgrewriteaof"
10) "replicaof"
11) "monitor"
12) "restore-asking"
13) "latency"
14) "replconf"
15) "pfdebug"
16) "bgsave"
17) "sync"
18) "config"
19) "flushall"
20) "cluster"
21) "info"
22) "lastsave"
23) "slaveof"
24) "swapdb"
25) "module"
26) "restore"
27) "migrate"
28) "save"
29) "shutdown"
30) "psync"
31) "sort"
acl-delrole
Delete all the specified ACL roles.
A role cannot be deleted while it is assigned to a user: if any of the specified roles is still held by a user, the command returns an error and no role is deleted.
Use the resetroles or role= rules of ACL SETUSER to remove the role from its users first.
The users holding a role are listed by ACL GETROLE.
The list of roles may include role names that do not exist, in such case no operation is performed for the non existing roles.
Examples
127.0.0.1:6379> ACL DELROLE reader
(error) ERR Role 'reader' is assigned to one or more users. Remove it from them first.
127.0.0.1:6379> ACL SETUSER alice resetroles
OK
127.0.0.1:6379> ACL DELROLE reader nosuchrole
(integer) 1
acl-deluser
Delete all the specified ACL users and terminate all the connections that are
authenticated with such users. Note: the special default user cannot be
removed from the system, this is the default user that every new connection
is authenticated with. The list of users may include usernames that do not
exist, in such case no operation is performed for the non existing users.
Examples
127.0.0.1:6379> ACL DELUSER antirez
(integer) 1
acl-digest
Return a fingerprint of the ACL rules currently in effect, as a hexadecimal string. The digest depends only on the rules in effect and not on the order the users were created in, so two servers configured alike report the same digest.
The digest covers everything ACL LIST reports: the user names, their
flags, their password hashes, and their command, key and channel rules.
Any change to any user changes the digest.
The reply is the same size however many users are configured.
This is meant for confirming which revision of an ACL a server is running.
A client that manages users through an ACL file can read the digest before and after an
ACL LOAD to tell whether the file it wrote is the one now in effect.
Comparing the rules themselves is impractical, because the server reports them in its
own normalized form rather than the form they were written in, so a client would need its
own copy of the rule parser to compare them.
Examples
127.0.0.1:6379> ACL DIGEST
"24ece0a4daea0bcb936b438ae6c9f36db76f57dfc70e00def7b2c26041c49822"
127.0.0.1:6379> ACL SETUSER alice on >alice ~key:* +get
OK
127.0.0.1:6379> ACL DIGEST
"d06ec40dd1a8e30a4babea1011d4b0daf02dbdf5de95ea18768e15f346a7d385"
127.0.0.1:6379> ACL DELUSER alice
(integer) 1
127.0.0.1:6379> ACL DIGEST
"24ece0a4daea0bcb936b438ae6c9f36db76f57dfc70e00def7b2c26041c49822"
acl-dryrun
Simulate the execution of a given command by a given user. This command can be used to test the permissions of a given user without having to enable the user or cause the side effects of running the command.
Examples
127.0.0.1:6379> ACL SETUSER VIRGINIA +SET ~*
"OK"
127.0.0.1:6379> ACL DRYRUN VIRGINIA SET foo bar
"OK"
127.0.0.1:6379> ACL DRYRUN VIRGINIA GET foo
"User VIRGINIA has no permissions to run the 'get' command"
acl-genpass
ACL users need a solid password in order to authenticate to the server without
security risks. Such password does not need to be remembered by humans, but
only by computers, so it can be very long and strong (unguessable by an
external attacker). The ACL GENPASS command generates a password starting
from /dev/urandom if available, otherwise (in systems without /dev/urandom) it
uses a weaker system that is likely still better than picking a weak password
by hand.
By default (if /dev/urandom is available) the password is strong and
can be used for other uses in the context of an application, for
instance in order to create unique session identifiers or other kind of
unguessable and not colliding IDs. The password generation is also very cheap
because we don't really ask /dev/urandom for bits at every execution. At
startup Valkey creates a seed using /dev/urandom, then it will use SHA256
in counter mode, with HMAC-SHA256(seed,counter) as primitive, in order to
create more random bytes as needed. This means that the application developer
should be feel free to abuse ACL GENPASS to create as many secure
pseudorandom strings as needed.
The command output is a hexadecimal representation of a binary string. By default it emits 256 bits (so 64 hex characters). The user can provide an argument in form of number of bits to emit from 1 to 1024 to change the output length. Note that the number of bits provided is always rounded to the next multiple of 4. So for instance asking for just 1 bit password will result in 4 bits to be emitted, in the form of a single hex character.
Examples
127.0.0.1:6379> ACL GENPASS
"dd721260bfe1b3d9601e7fbab36de6d04e2e67b0ef1c53de59d45950db0dd3cc"
127.0.0.1:6379> ACL GENPASS 32
"355ef3dd"
127.0.0.1:6379> ACL GENPASS 5
"90"
acl-getrole
The command returns all the rules defined for an existing ACL role, and the users that hold it. The command returns a null reply if the role does not exist.
Specifically, it lists the role's commands, key patterns, channel patterns, databases and selectors, with rules returned in the same format as the one used in the ACL SETROLE command, followed by the names of the users the role is assigned to.
Examples
127.0.0.1:6379> ACL SETROLE reader ~app:* +@read (+info)
OK
127.0.0.1:6379> ACL SETUSER alice on >alicepass role=reader
OK
127.0.0.1:6379> ACL GETROLE reader
1) "commands"
2) "-@all +@read"
3) "keys"
4) "~app:*"
5) "channels"
6) ""
7) "databases"
8) "alldbs"
9) "selectors"
10) 1) 1) "commands"
2) "-@all +info"
3) "keys"
4) ""
5) "channels"
6) ""
7) "databases"
8) "alldbs"
11) "users"
12) 1) "alice"
127.0.0.1:6379> ACL GETROLE nosuchrole
(nil)
acl-getuser
The command returns all the rules defined for an existing ACL user.
Specifically, it lists the user's ACL flags, password hashes, commands, key patterns, channel patterns (Added in version 6.2), selectors (Added in version 7.0), databases (Added in version 9.1) and roles (Added in version 9.2). Additional information may be returned in the future if more metadata is added to the user.
Command rules are always returned in the same format as the one used in the ACL SETUSER command.
Before version 7.0, keys and channels were returned as an array of patterns, however in version 7.0 later they are now also returned in same format as the one used in the ACL SETUSER command.
Note: This description of command rules reflects the user's effective permissions, so while it may not be identical to the set of rules used to configure the user, it is still functionally identical.
Selectors are listed in the order they were applied to the user, and include information about commands, key patterns, channel patterns, and database permissions.
Roles are listed in the order they were assigned to the user.
The commands, keys, channels, databases and selectors fields only describe the user's own rules, not the permissions the user gets from its roles.
Use ACL GETROLE to inspect the rules of a role, and ACL DRYRUN to check the effective permissions of a user.
Examples
Here's an example configuration for a user
127.0.0.1:6379> ACL SETUSER sample on nopass +GET allkeys &* (+SET ~key2)
"OK"
127.0.0.1:6379> ACL GETUSER sample
1) "flags"
2) 1) "on"
2) "nopass"
3) "passwords"
4) (empty array)
5) "commands"
6) "-@all +get"
7) "keys"
8) "~*"
9) "channels"
10) "&*"
11) "databases"
12) "alldbs"
13) "selectors"
14) 1) 1) "commands"
2) "-@all +set"
3) "keys"
4) "~key2"
5) "channels"
6) ""
7) "databases"
8) "alldbs"
15) "roles"
16) (empty array)
acl-help
The ACL HELP command returns a helpful text describing the different subcommands.
acl-list
The command shows the currently active ACL rules in the Valkey server. Each
line in the returned array defines a different role or user. Lines starting
with role describe roles and are listed first,
followed by the lines starting with user. The format is the
same used in the valkey.conf file or the external ACL file, so you can
cut and paste what is returned by the ACL LIST command directly inside a
configuration file if you wish (but make sure to check ACL SAVE).
Implicit defaults may be omitted: for example, access to all databases (alldbs)
is not shown, while explicit db=<dbid> and resetdbs rules are shown.
Examples
127.0.0.1:6379> ACL LIST
1) "role reader ~app:* resetchannels -@all +@read"
2) "user alice on #13dc8554575637802eec3c0117f41591a990e1a2d37160018c48c9125063838a resetchannels -@all role=reader"
3) "user antirez on #9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08 ~objects:* &* +@all -@admin -@dangerous"
4) "user default on nopass ~* &* +@all"
acl-load
When Valkey is configured to use an ACL file (with the aclfile configuration
option), this command will reload the ACLs from the file, replacing all
the current ACL rules with the ones defined in the file. The command makes
sure to have an all or nothing behavior, that is:
- If every line in the file is valid, all the ACLs are loaded.
- If one or more line in the file is not valid, nothing is loaded, and the old ACL rules defined in the server memory continue to be used.
Examples
127.0.0.1:6379> ACL LOAD
OK
127.0.0.1:6379> ACL LOAD
(error) ERR /tmp/foo:1: Unknown command or category name in ACL...
acl-log
The command shows a list of recent ACL security events:
- Failures to authenticate their connections with
AUTHorHELLO. - Commands denied because against the current ACL rules.
- Commands denied because accessing keys not allowed in the current ACL rules.
- Commands denied because accessing Pub/Sub channels not allowed in the current ACL rules.
- Commands denied because accessing a database not allowed in the current ACL rules.
- TLS clients failing automatic authentication via certificate field because no matching user exists.
The optional argument specifies how many entries to show. By default
up to ten failures are returned. The special RESET argument clears the log.
Entries are displayed starting from the most recent.
Examples
127.0.0.1:6379> AUTH someuser wrongpassword
(error) WRONGPASS invalid username-password pair
> ACL LOG 1
1) 1) "count"
2) (integer) 1
3) "reason"
4) "auth"
5) "context"
6) "toplevel"
7) "object"
8) "AUTH"
9) "username"
10) "someuser"
11) "age-seconds"
12) "8.038"
13) "client-info"
14) "id=3 addr=127.0.0.1:57275 laddr=127.0.0.1:6379 fd=8 name= age=16 idle=0 flags=N db=0 sub=0 psub=0 ssub=0 multi=-1 qbuf=48 qbuf-free=16842 argv-mem=25 multi-mem=0 rbs=1024 rbp=0 obl=0 oll=0 omem=0 tot-mem=18737 events=r cmd=auth user=default redir=-1 resp=2"
15) "entry-id"
16) (integer) 0
17) "timestamp-created"
18) (integer) 1675361492408
19) "timestamp-last-updated"
20) (integer) 1675361492408
Each log entry is composed of the following fields:
count: The number of security events detected within a 60 second period that are represented by this entry.reason: The reason that the security events were logged. One of the following:command: the user has no permission to run the command.key: the user has no permission to access one of the keys used by the command.channel: the user has no permission to access one of the Pub/Sub channels used by the command.database: the user has no permission to access one of the databases referenced by the command.auth: authentication failed for the connection.tls-cert: automatic authentication from a TLS certificate failed because no matching user exists.
context: The context that the security events were detected in. Eithertoplevel,multi,lua,script, ormodule.object: The resource that the user had insufficient permissions to access. The value depends onreason:command: the command name.key: the key pattern.channel: the Pub/Sub channel.database: the database id, or the command name when the command implicitly accesses every database (such asFLUSHALL).auth: the literal stringAUTH.tls-cert: the certificate that did not match any existing user.
username: The username that executed the command that caused the security events or the username that had a failed authentication attempt.age-seconds: Age of the log entry in seconds.client-info: Displays the client info of a client which caused one of the security events.entry-id: The sequence number of the entry (starting at 0) since the server process started. Can also be used to check if items were “lost”, if they fell between periods.timestamp-created: A UNIX timestamp inmillisecondsat the time the entry was first created.timestamp-last-updated: A UNIX timestamp inmillisecondsat the time the entry was last updated.
acl-roles
The command shows a list of all the names of the currently configured roles in the Valkey ACL system.
Examples
127.0.0.1:6379> ACL ROLES
1) "ops"
2) "reader"
3) "writer"
acl-save
When Valkey is configured to use an ACL file (with the aclfile configuration
option), this command will save the currently defined ACLs from the server memory to the ACL file.
Examples
127.0.0.1:6379> ACL SAVE
OK
127.0.0.1:6379> ACL SAVE
(error) ERR There was an error trying to save the ACLs. Please check the server logs for more information
acl-setrole
Create an ACL role with the specified rules or modify the rules of an existing role.
A role is a named, reusable set of permissions that can be assigned to any number of users with the role= rule of ACL SETUSER, so a policy is written once instead of being repeated in every user.
See roles for more information.
If the role does not exist, the command creates it without any privilege.
It then reads from left to right all the rules provided as successive arguments, setting the role ACL rules as specified.
If the role already exists, the provided ACL rules are applied in addition to the rules already set, exactly as ACL SETUSER does for users.
The rules are applied atomically: if any rule is invalid, the role is left unchanged.
A role accepts the command rules of ACL SETUSER, as well as selectors ((<rule list>)) and clearselectors.
The rules that only make sense for a user are rejected with an error: on, off, reset, the password rules (>, <, #, !, nopass, resetpass), role= and resetroles.
Roles cannot be nested.
Changes to a role take effect immediately for every user holding it. If the change removes access to Pub/Sub channels, the clients of those users that are subscribed to channels they can no longer access are disconnected.
Role names are case sensitive and may contain any printable ASCII character except for spaces, commas, quotes (" and ') and backslashes.
Roles live in a namespace of their own, so a role may have the same name as a user, a command, or a category.
Note: a new role starts with access to all databases (alldbs), and to all Pub/Sub channels if acl-pubsub-default is set to allchannels, just like a new user.
Since a user's own permissions and those of its roles are combined with OR logic, such a role grants those databases and channels to its users even if the user itself is restricted with resetdbs, db=<id> or resetchannels.
Use db=<id> (or resetdbs) and resetchannels in the role rules to restrict the role itself.
See database permissions.
Examples
127.0.0.1:6379> ACL SETROLE reader ~app:* +@read
OK
127.0.0.1:6379> ACL SETROLE ops ~* +info (+config|get)
OK
127.0.0.1:6379> ACL SETROLE reader on
(error) ERR Error in ACL SETROLE modifier 'on': Syntax error
acl-setuser
Create an ACL user with the specified rules or modify the rules of an existing user.
Manipulate Valkey ACL users interactively. If the username does not exist, the command creates the username without any privilege. It then reads from left to right all the rules provided as successive arguments, setting the user ACL rules as specified. If the user already exists, the provided ACL rules are simply applied in addition to the rules already set. For example:
ACL SETUSER virginia on allkeys +set
The above command creates a user called virginia who is active(the on rule), can access any key (allkeys rule), and can call the set command (+set rule).
Then, you can use another ACL SETUSER call to modify the user rules:
ACL SETUSER virginia +get
The above rule applies the new rule to the user virginia, so other than SET, the user virginia can now also use the GET command.
ACL rules can also be grouped into multiple distinct sets of rules, called selectors. Selectors are added by wrapping the rules in parentheses and providing them just like any other rule. In order to execute a command, either the root permissions (rules defined outside of parenthesis) or any of the selectors (rules defined inside parenthesis) must match the given command. For example:
ACL SETUSER virginia on +GET allkeys (+SET ~app1*)
This sets a user with two sets of permissions, one defined on the user and one defined with a selector.
The root user permissions only allow executing the get command, but can be executed on any keys.
The selector then grants a secondary set of permissions: access to the SET command to be executed on any key that starts with app1.
Using multiple selectors allows you to grant permissions that are different depending on what keys are being accessed.
Permissions can also be defined once in a named role, created with ACL SETROLE, and assigned to any number of users with the role= rule:
ACL SETROLE reader ~app:* +@read
ACL SETUSER virginia on >password role=reader
A user's own permissions are combined with those of its roles, so a user can add permissions on top of a role but cannot take away what a role grants.
When we want to be sure to define a user from scratch, without caring if
it had previously defined rules associated, we can use the special rule
reset as first rule, in order to flush all the other existing rules:
ACL SETUSER antirez reset [... other rules ...]
After resetting a user, its ACL rules revert to the default: inactive, passwordless, can't execute any command nor access any key or channel:
127.0.0.1:6379> ACL SETUSER antirez reset
OK
127.0.0.1:6379> ACL LIST
1) "user antirez off -@all"
ACL rules are either words like "on", "off", "reset", "allkeys", or are special rules that start with a special character, and are followed by another string (without any space in between), like "+SET".
The following documentation is a reference manual about the capabilities of this command, however our ACL tutorial may be a more gentle introduction to how the ACL system works in general.
ACL rules
Valkey ACL rules are split into two categories: rules that define command permissions or command rules, and rules that define the user state or user management rules. This is a list of all the supported Valkey ACL rules:
Command rules
~<pattern>: Adds the specified key pattern (glob style pattern, like in theKEYScommand), to the list of key patterns accessible by the user. This grants both read and write permissions to keys that match the pattern. You can add multiple key patterns to the same user. Example:~objects:*%R~<pattern>: Adds the specified read key pattern. This behaves similar to the regular key pattern but only grants permission to read from keys that match the given pattern. See key permissions for more information.%W~<pattern>: Adds the specified write key pattern. This behaves similar to the regular key pattern but only grants permission to write to keys that match the given pattern. See key permissions for more information.%RW~<pattern>: Alias for~<pattern>.allkeys: Alias for~*, it allows the user to access all the keys.resetkeys: Removes all the key patterns from the list of key patterns the user can access.&<pattern>: Adds the specified glob style pattern to the list of Pub/Sub channel patterns accessible by the user. You can add multiple channel patterns to the same user. Example:&chatroom:*allchannels: Alias for&*, it allows the user to access all Pub/Sub channels.resetchannels: Removes all channel patterns from the list of Pub/Sub channel patterns the user can access.+<command>: Adds the command to the list of commands the user can call. Can be used with|for allowing subcommands (e.g "+config|get").+@<category>: Adds all the commands in the specified category to the list of commands the user is able to execute. Example:+@string(adds all the string commands). For a list of categories, check theACL CATcommand.+<command>|first-arg: Allows a specific first argument of an otherwise disabled command. It is only supported on commands with no sub-commands, and is not allowed as negative form like -SELECT|1, only additive starting with "+". This feature is deprecated and may be removed in the future.allcommands: Alias of+@all. Adds all the commands there are in the server, including future commands loaded via module, to be executed by this user.-<command>: Remove the command to the list of commands the user can call. It can be used with|for blocking subcommands (e.g., "-config|set").-@<category>: Like+@<category>but removes all the commands in the category instead of adding them.nocommands: Alias for-@all. Removes all the commands, and the user is no longer able to execute anything.db=<id>[,<id>...]: Sets the specified database id(s) as the databases the selector is allowed to access. Multiple ids are separated by commas, e.g.db=0,1,2; at least one id is required. Clears thealldbsflag and any previously configured database ids on the selector. See database permissions for more information.alldbs: Allows the selector to access all databases. This is the default for new selectors and is omitted from generated ACL strings.resetdbs: Removes all databases from the list of allowed databases and clears thealldbsflag.
User management rules
on: Set the user as active, it will be possible to authenticate as this user usingAUTH<username> <password>.off: Set user as not active, it will be impossible to log as this user. Please note that if a user gets disabled (set to off) after there are connections already authenticated with such a user, the connections will continue to work as expected. To also kill the old connections you can useCLIENT KILLwith the user option. An alternative is to delete the user withACL DELUSER, that will result in all the connections authenticated as the deleted user to be disconnected.nopass: The user is set as a no password user. It means that it will be possible to authenticate as such user with any password. By default, thedefaultspecial user is set as "nopass". Thenopassrule will also reset all the configured passwords for the user.>password: Adds the specified clear text password as a hashed password in the list of the users passwords. Every user can have many active passwords, so that password rotation will be simpler. The specified password is not stored as clear text inside the server. Example:>mypassword.#<hashedpassword>: Adds the specified hashed password to the list of user passwords. A hashed password is hashed with SHA256 and translated into a hexadecimal string. Example:#c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2.<password: Like>passwordbut removes the password instead of adding it.!<hashedpassword>: Like#<hashedpassword>but removes the password instead of adding it.(<rule list>): Creates a new selector to match rules against. Selectors are evaluated after the user permissions, and are evaluated according to the order they are defined. If a command matches either the user permissions or any selector, it is allowed. See selectors for more information.clearselectors: Deletes all of the selectors attached to the user.role=<role>[,<role> ...]: Assigns the named roles to the user, replacing any role the user already had. At least one role has to be named, and every named role must already exist (seeACL SETROLE). The permissions of each role are combined with those of the user using OR logic, the same way selectors are. See roles for more information. Example:role=reader,writer. (Added in version 9.2)resetroles: Removes every role from the user. (Added in version 9.2)reset: Removes any capability from the user. They are set to off, without passwords, without roles, unable to execute any command, unable to access any key.
Examples
127.0.0.1:6379> ACL SETUSER alan allkeys +@string +@set -SADD >alanpassword
OK
127.0.0.1:6379> ACL SETUSER antirez heeyyyy
(error) ERR Error in ACL SETUSER modifier 'heeyyyy': Syntax error
Restrict a user to a subset of databases:
127.0.0.1:6379> ACL SETUSER alice on +@all ~* db=0,1 nopass
OK
127.0.0.1:6379> ACL LIST
1) "user alice on nopass ~* resetchannels db=0,1 +@all"
2) "user default on nopass ~* &* +@all"
A later db= rule replaces the previous database list:
127.0.0.1:6379> ACL SETUSER alice db=2,3
OK
127.0.0.1:6379> ACL LIST
1) "user alice on nopass ~* resetchannels db=2,3 +@all"
2) "user default on nopass ~* &* +@all"
Different selectors can grant access on different databases:
127.0.0.1:6379> ACL SETUSER bob on nopass (db=0,1 +@write +select ~*) (db=2,3 +@read +select ~*)
OK
127.0.0.1:6379> ACL LIST
1) "user bob on nopass resetchannels -@all (~* resetchannels db=0,1 -@all +@write +select) (~* resetchannels db=2,3 -@all +@read +select)"
2) "user default on nopass ~* &* +@all"
The ACL LIST output shows three sets of permissions for bob: the root
permissions (-@all, with implicit alldbs) and two selectors, one for each
parenthesized rule set. A command is allowed when the root permissions or any selector matches it.
See selectors for more information.
acl-users
The command shows a list of all the usernames of the currently configured
users in the Valkey ACL system. Roles are not included, use
ACL ROLES to list them.
Examples
127.0.0.1:6379> ACL USERS
1) "anna"
2) "antirez"
3) "default"
acl-whoami
Return the username the current connection is authenticated with.
New connections are authenticated with the "default" user. They
can change user using AUTH.
Examples
127.0.0.1:6379> ACL WHOAMI
"default"
acl
This is a container command for Access Control List commands.
To see the list of available commands you can call ACL HELP.
append
If key already exists and is a string, this command appends the value at the
end of the string.
If key does not exist it is created and set as an empty string, so APPEND
will be similar to SET in this special case.
Examples
127.0.0.1:6379> EXISTS mykey
(integer) 0
127.0.0.1:6379> APPEND mykey "Hello"
(integer) 5
127.0.0.1:6379> APPEND mykey " World"
(integer) 11
127.0.0.1:6379> GET mykey
"Hello World"
Pattern: Time series
The APPEND command can be used to create a very compact representation of a
list of fixed-size samples, usually referred as time series.
Every time a new sample arrives we can store it using the command
APPEND timeseries "fixed-size sample"
Accessing individual elements in the time series is not hard:
STRLENcan be used in order to obtain the number of samples.GETRANGEallows for random access of elements. If our time series have associated time information we can easily implement a binary search to get range combiningGETRANGEwith the Lua scripting engine.SETRANGEcan be used to overwrite an existing time series.
The limitation of this pattern is that we are forced into an append-only mode of operation, there is no way to cut the time series to a given size easily because Valkey currently lacks a command able to trim string objects. However the space efficiency of time series stored in this way is remarkable.
Hint: it is possible to switch to a different key based on the current Unix time, in this way it is possible to have just a relatively small amount of samples per key, to avoid dealing with very big keys, and to make this pattern more friendly to be distributed across many Valkey instances.
An example sampling the temperature of a sensor using fixed-size strings (using a binary format is better in real implementations).
127.0.0.1:6379> APPEND ts "0043"
(integer) 4
127.0.0.1:6379> APPEND ts "0035"
(integer) 8
127.0.0.1:6379> GETRANGE ts 0 3
"0043"
127.0.0.1:6379> GETRANGE ts 4 7
"0035"
asking
When a cluster client receives an -ASK redirect, the ASKING command is sent to the target node followed by the command which was redirected.
This is normally done automatically by cluster clients.
If an -ASK redirect is received during a transaction, only one ASKING command needs to be sent to the target node before sending the complete transaction to the target node.
See ASK redirection in the Valkey Cluster Specification for details.
auth
The AUTH command authenticates the current connection using the Valkey ACL system.
The standard way to AUTH is the two-argument form:
AUTH <username> <password>
This authenticates the current connection with one of the users
defined in the ACL list (see ACL SETUSER and the official ACL guide for more information).
When the single argument form of the command is used, where only the password is specified, it is assumed that the implicit username is "default".
AUTH <password>
This form authenticates against the "default" user's password set with requirepass.
If the password provided via AUTH matches the password in the configuration file, the server replies with the OK status code and starts accepting commands.
Otherwise, an error is returned and the clients needs to try a new password.
Security notice
Because of the high performance nature of Valkey, it is possible to try
a lot of passwords in parallel in very short time, so make sure to generate a
strong and very long password so that this attack is infeasible.
A good way to generate strong passwords is via the ACL GENPASS command.
bf.add
Adds a single item to a bloom filter. If the specified bloom filter does not exist, a bloom filter is created with the provided name with default properties.
To add multiple items to a bloom filter, you can use the BF.MADD or BF.INSERT commands.
To create a bloom filter with non-default properties, use the BF.INSERT or BF.RESERVE command.
Examples
127.0.0.1:6379> BF.ADD key val
(integer) 1
127.0.0.1:6379> BF.ADD key val
(integer) 0
bf.card
Returns the cardinality of a bloom filter which is the number of items that have been successfully added to it.
Examples
127.0.0.1:6379> BF.ADD key val
(integer) 1
127.0.0.1:6379> BF.CARD key
(integer) 1
127.0.0.1:6379> BF.CARD nonexistentkey
(integer) 0
bf.exists
Determines if an item has been added to the bloom filter previously.
A bloom filter has two possible responses when you check if an item exists:
-
0 - The item definitely does not exist since with bloom filters, false negatives are not possible.
-
1 - The item exists with a given false positive (
fp) percentage. There is anfprate % chance that the item does not exist. You can create bloom filters with a more strict false positive rate as needed.
Examples
127.0.0.1:6379> BF.ADD key val
(integer) 1
127.0.0.1:6379> BF.EXISTS key val
(integer) 1
127.0.0.1:6379> BF.EXISTS key nonexistent
(integer) 0
bf.info
Returns usage information and properties of a specific bloom filter.
Info Fields
- CAPACITY - The number of unique items that would need to be added before a scale out occurs or (non scaling) before it rejects addition of unique items.
- SIZE - The number of bytes allocated by this bloom filter.
- FILTERS - Returns the number of sub filters contained within the bloom filter.
- ITEMS - The number of unique items that have been added to the bloom filter.
- ERROR - The false positive rate of the bloom filter.
- EXPANSION - The expansion rate of the bloom filter. Non scaling filters will have an expansion rate of nil.
- TIGHTENING - The tightening ratio of the bloom filter.
- MAXSCALEDCAPACITY - The maximum capacity that a scalable bloom filter can be expand to and reach before a subsequent scale out will fail.
For non-scaling filters, the TIGHTENING and MAXSCALEDCAPACITY fields are not applicable and will not be returned.
When no optional fields are specified, all available fields for the given filter type are returned.
Examples
127.0.0.1:6379> BF.ADD key val
(integer) 1
127.0.0.1:6379> BF.INFO key
1) Capacity
2) (integer) 100
3) Size
4) (integer) 384
5) Number of filters
6) (integer) 1
7) Number of items inserted
8) (integer) 2
9) Error rate
10) "0.01"
11) Expansion rate
12) (integer) 2
13) Tightening ratio
14) "0.5"
15) Max scaled capacity
16) (integer) 26214300
127.0.0.1:6379> BF.INFO key CAPACITY
(integer) 100
bf.insert
If the bloom filter does not exist under the specified name, a bloom filter is created with the specified parameters. Default properties will be used if the options below are not specified.
When the ITEMS option is provided, all items provided will be attempted to be added.
Insert Fields
- CAPACITY capacity - The number of unique items that would need to be added before a scale out occurs or (non scaling) before it rejects addition of unique items.
- ERROR fp_error - The false positive rate of the bloom filter.
- EXPANSION expansion - This option will specify the bloom filter as scaling and controls the size of the sub filter that will be created upon scale out / expansion of the bloom filter.
- NOCREATE - Will not create the bloom filter and add items if the filter does not exist already.
- TIGHTENING tightening_ratio - The tightening ratio for the bloom filter.
- SEED seed - The 32 byte seed the bloom filter's hash functions will use.
- NONSCALING - This option will configure the bloom filter as non scaling; it cannot expand / scale beyond its specified capacity.
- VALIDATESCALETO validatescaleto - Validates if the filter can scale out and reach to this capacity based on limits and if not, return an error without creating the bloom filter.
- ITEMS item - One or more items to be added to the bloom filter.
Due to the nature of NONSCALING and VALIDATESCALETO arguments, specifying NONSCALING and VALIDATESCALETO together is not allowed.
Examples
127.0.0.1:6379> BF.INSERT key ITEMS item1 item2
1) (integer) 1
2) (integer) 1
# This does not update the capacity since the filter already exists. It only adds the provided items.
127.0.0.1:6379> BF.INSERT key CAPACITY 1000 ITEMS item2 item3
1) (integer) 0
2) (integer) 1
127.0.0.1:6379> BF.INSERT key_new CAPACITY 1000
[]
127.0.0.1:6379> BF.INSERT key NONSCALING VALIDATESCALETO 100
(error) ERR cannot use NONSCALING and VALIDATESCALETO options together
127.0.0.1:6379> BF.INSERT key CAPACITY 1000 VALIDATESCALETO 999999999999999999 ITEMS item2 item3
(error) ERR provided VALIDATESCALETO causes bloom object to exceed memory limit
127.0.0.1:6379> BF.INSERT key VALIDATESCALETO 999999999999999999 EXPANSION 1 ITEMS item2 item3
(error) ERR provided VALIDATESCALETO causes false positive to degrade to 0
127.0.0.1:6379> BF.INSERT key NOCREATE ITEMS item1 item2
(error) ERR not found
bf.load
Restores a bloom filter from a dump of an existing bloom filter with all of its specific the properties and bit vector dump of sub filter/s. This command is only generated during AOF rewrite to restore a bloom filter in the future.
bf.madd
Adds one or more items to a bloom filter. If the specified bloom filter does not exist, a bloom filter is created with the provided name with default properties.
If you want to create a bloom filter with non-default properties, use the BF.INSERT or BF.RESERVE command.
Examples
127.0.0.1:6379> BF.MADD key item1 item2
1) (integer) 1
2) (integer) 1
127.0.0.1:6379> BF.MADD key item2 item3
1) (integer) 0
2) (integer) 1
127.0.0.1:6379> BF.MADD key_new item1
1) (integer) 1
bf.mexists
Determines if the provided item/s have been added to a bloom filter previously.
A Bloom filter has two possible responses when you check if an item exists:
-
0 - The item definitely does not exist since with bloom filters, false negatives are not possible.
-
1 - The item exists with a given false positive (
fp) percentage. There is anfprate % chance that the item does not exist. You can create bloom filters with a more strict false positive rate as needed.
Examples
127.0.0.1:6379> BF.MADD key item1 item2
1) (integer) 1
2) (integer) 1
127.0.0.1:6379> BF.MEXISTS key item1 item2 item3
1) (integer) 1
2) (integer) 1
3) (integer) 0
127.0.0.1:6379> BF.MEXISTS key item1
1) (integer) 1
bf.reserve
Creates an empty bloom filter with the specified capacity and false positive rate. By default, a scaling filter is created with the default expansion rate.
To specify the scaling / non scaling nature of the bloom filter, use the options: NONSCALING or SCALING <expansion rate>. It is invalid to provide both options together.
Reserve fields
- error_rate - The false positive rate of the bloom filter
- capacity - The number of unique items that would need to be added before a scale out occurs or (non scaling) before it rejects addition of unique items.
- EXPANSION expansion - This option will specify the bloom filter as scaling and controls the size of the sub filter that will be created upon scale out / expansion of the bloom filter.
- NONSCALING - This option will configure the bloom filter as non scaling; it cannot expand / scale beyond its specified capacity.
Examples
127.0.0.1:6379> BF.RESERVE key 0.01 1000
OK
127.0.0.1:6379> BF.RESERVE key 0.1 1000000
(error) ERR item exists
127.0.0.1:6379> BF.RESERVE bf_expansion 0.0001 5000 EXPANSION 3
OK
127.0.0.1:6379> BF.RESERVE bf_nonscaling 0.0001 5000 NONSCALING
OK
bgrewriteaof
Instruct Valkey to start an Append Only File rewrite process. The rewrite will create a small optimized version of the current Append Only File.
If BGREWRITEAOF fails, no data gets lost as the old AOF will be untouched.
The rewrite will be only triggered by Valkey if there is not already a background process doing persistence.
Specifically:
- If a Valkey child is creating a snapshot on disk, the AOF rewrite is scheduled but not started until the saving child producing the RDB file terminates. In this case the
BGREWRITEAOFwill still return a positive status reply, but with an appropriate message. You can check if an AOF rewrite is scheduled looking at theINFOcommand. - If an AOF rewrite is already in progress the command returns an error and no AOF rewrite will be scheduled for a later time.
- If the AOF rewrite could start, but the attempt at starting it fails (for instance because of an error in creating the child process), an error is returned to the caller.
The AOF rewrite is automatically triggered by Valkey, however the
BGREWRITEAOF command can be used to trigger a rewrite at any time.
Please refer to the persistence documentation for detailed information.
bgsave
Save the DB in background.
Normally the OK code is immediately returned. Valkey forks, the parent continues to serve the clients, the child saves the DB on disk then exits.
An error is returned if there is already a background save running or if there is another non-background-save process running, specifically an in-progress AOF rewrite.
If BGSAVE SCHEDULE is used, the command will immediately return OK when an
AOF rewrite is in progress and schedule the background save to run at the next
opportunity.
If BGSAVE CANCEL is used, it will immediately terminate any in-progress RDB save or replication full sync process.
In case a background save is scheduled to run (e.g. using BGSAVE SCHEDULE command) the scheduled execution will be
cancelled as well.
A client may be able to check if the operation succeeded using the LASTSAVE
command.
Please refer to the persistence documentation for detailed information.
bitcount
Count the number of set bits (population counting) in a string.
By default all the bytes contained in the string are examined. It is possible to specify the counting operation only in an interval passing the additional arguments start and end.
Similar to the GETRANGE command, start and end can contain negative values in
order to index bytes starting from the end of the string, where -1 is the last
byte, -2 is the penultimate, and so forth.
Non-existent keys are treated as empty strings, so the command will return zero.
By default, the additional arguments start and end specify a byte index.
We can use an additional argument BIT to specify a bit index.
So 0 is the first bit, 1 is the second bit, and so forth.
For negative values, -1 is the last bit, -2 is the penultimate, and so forth.
Examples
127.0.0.1:6379> SET mykey "foobar"
OK
127.0.0.1:6379> BITCOUNT mykey
(integer) 26
127.0.0.1:6379> BITCOUNT mykey 0 0
(integer) 4
127.0.0.1:6379> BITCOUNT mykey 1 1
(integer) 6
127.0.0.1:6379> BITCOUNT mykey 1 1 BYTE
(integer) 6
127.0.0.1:6379> BITCOUNT mykey 5 30 BIT
(integer) 17
Pattern: real-time metrics using bitmaps
Bitmaps are a very space-efficient representation of certain kinds of information. One example is a Web application that needs the history of user visits, so that for instance it is possible to determine what users are good targets of beta features.
Using the SETBIT command, this is trivial to accomplish, identifying every day
with a small progressive integer.
For instance day 0 is the first day the application was put online, day 1 the
next day, and so forth.
Every time a user performs a page view, the application can register that in
the current day the user visited the web site using the SETBIT command setting
the bit corresponding to the current day.
Later it will be trivial to know the number of single days the user visited the
web site simply calling the BITCOUNT command against the bitmap.
A similar pattern where user IDs are used instead of days is described in the article called "Fast easy realtime metrics using Redis bitmaps".
Performance considerations
In the above example of counting days, even after 10 years the application is
online we still have just 365*10 bits of data per user, that is just 456 bytes
per user.
With this amount of data BITCOUNT is still as fast as any other O(1) Valkey
command like GET or INCR.
When the bitmap is big, there are two alternatives:
- Taking a separated key that is incremented every time the bitmap is modified. This can be very efficient and atomic using a small Lua script.
- Running the bitmap incrementally using the
BITCOUNTstartandendoptional parameters, accumulating the results client-side, and optionally caching the result into a key.
bitfield
The command treats a string as an array of bits, and is capable of addressing specific integer fields of varying bit widths and arbitrary non (necessary) aligned offset. In practical terms using this command you can set, for example, a signed 5 bits integer at bit offset 1234 to a specific value, retrieve a 31 bit unsigned integer from offset 4567. Similarly the command handles increments and decrements of the specified integers, providing guaranteed and well specified overflow and underflow behavior that the user can configure.
BITFIELD is able to operate with multiple bit fields in the same command call. It takes a list of operations to perform, and returns an array of replies, where each array matches the corresponding operation in the list of arguments.
For example the following command increments a 5 bit signed integer at bit offset 100, and gets the value of the 4 bit unsigned integer at bit offset 0:
> BITFIELD mykey INCRBY i5 100 1 GET u4 0
1) (integer) 1
2) (integer) 0
Note that:
- Addressing with
!GETbits outside the current string length (including the case the key does not exist at all), results in the operation to be performed like the missing part all consists of bits set to 0. - Addressing with
!SETor!INCRBYbits outside the current string length will enlarge the string, zero-padding it, as needed, for the minimal length needed, according to the most far bit touched.
Supported subcommands and integer encoding
The following is the list of supported commands.
- GET
<encoding><offset>-- Returns the specified bit field. - SET
<encoding><offset><value>-- Set the specified bit field and returns its old value. - INCRBY
<encoding><offset><increment>-- Increments or decrements (if a negative increment is given) the specified bit field and returns the new value.
There is another subcommand that only changes the behavior of successive
!INCRBY and !SET subcommands calls by setting the overflow behavior:
- OVERFLOW
[WRAP|SAT|FAIL]
Where an integer encoding is expected, it can be composed by prefixing with i for signed integers and u for unsigned integers with the number of bits of our integer encoding. So for example u8 is an unsigned integer of 8 bits and i16 is a
signed integer of 16 bits.
The supported encodings are up to 64 bits for signed integers, and up to 63 bits for unsigned integers. This limitation with unsigned integers is due to the fact that currently the Valkey protocol is unable to return 64 bit unsigned integers as replies.
Bits and positional offsets
There are two ways in order to specify offsets in the bitfield command. If a number without any prefix is specified, it is used just as a zero based bit offset inside the string.
However if the offset is prefixed with a # character, the specified offset
is multiplied by the integer encoding's width, so for example:
BITFIELD mystring SET i8 #0 100 SET i8 #1 200
Will set the first i8 integer at offset 0 and the second at offset 8. This way you don't have to do the math yourself inside your client if what you want is a plain array of integers of a given size.
Overflow control
Using the OVERFLOW command the user is able to fine-tune the behavior of
the increment or decrement overflow (or underflow) by specifying one of
the following behaviors:
- WRAP: wrap around, both with signed and unsigned integers. In the case of unsigned integers, wrapping is like performing the operation modulo the maximum value the integer can contain (the C standard behavior). With signed integers instead wrapping means that overflows restart towards the most negative value and underflows towards the most positive ones, so for example if an
i8integer is set to the value 127, incrementing it by 1 will yield-128. - SAT: uses saturation arithmetic, that is, on underflows the value is set to the minimum integer value, and on overflows to the maximum integer value. For example incrementing an
i8integer starting from value 120 with an increment of 10, will result into the value 127, and further increments will always keep the value at 127. The same happens on underflows, but towards the value is blocked at the most negative value. - FAIL: in this mode no operation is performed on overflows or underflows detected. The corresponding return value is set to NULL to signal the condition to the caller.
Note that each OVERFLOW statement only affects the !INCRBY and !SET
commands that follow it in the list of subcommands, up to the next OVERFLOW
statement.
By default, WRAP is used if not otherwise specified.
> BITFIELD mykey incrby u2 100 1 OVERFLOW SAT incrby u2 102 1
1) (integer) 1
2) (integer) 1
> BITFIELD mykey incrby u2 100 1 OVERFLOW SAT incrby u2 102 1
1) (integer) 2
2) (integer) 2
> BITFIELD mykey incrby u2 100 1 OVERFLOW SAT incrby u2 102 1
1) (integer) 3
2) (integer) 3
> BITFIELD mykey incrby u2 100 1 OVERFLOW SAT incrby u2 102 1
1) (integer) 0
2) (integer) 3
The following is an example of OVERFLOW FAIL returning NULL.
> BITFIELD mykey OVERFLOW FAIL incrby u2 102 1
1) (nil)
Motivations
The motivation for this command is that the ability to store many small integers as a single large bitmap (or segmented over a few keys to avoid having huge keys) is extremely memory efficient, and opens new use cases for Valkey to be applied, especially in the field of real time analytics. This use cases are supported by the ability to specify the overflow in a controlled way.
Fun fact: Reddit's 2017 April fools' project r/place was built using the BITFIELD command in order to take an in-memory representation of the collaborative canvas.
Performance considerations
Usually BITFIELD is a fast command, however note that addressing far bits of currently short strings will trigger an allocation that may be more costly than executing the command on bits already existing.
Orders of bits
The representation used by BITFIELD considers the bitmap as having the
bit number 0 to be the most significant bit of the first byte, and so forth, so
for example setting a 5 bits unsigned integer to value 23 at offset 7 into a
bitmap previously set to all zeroes, will produce the following representation:
+--------+--------+
|00000001|01110000|
+--------+--------+
When offsets and integer sizes are aligned to bytes boundaries, this is the same as big endian, however when such alignment does not exist, its important to also understand how the bits inside a byte are ordered.
bitfield_ro
Read-only variant of the BITFIELD command.
It is similar to the original BITFIELD but only accepts GET subcommand and can safely be used in read-only replicas.
Since the original BITFIELD has SET and INCRBY options, it is technically flagged as a writing command in the Valkey command table.
For this reason, read-only replicas in a Valkey Cluster will redirect it to the master instance even if the connection is in read-only mode (see the READONLY command of Valkey Cluster).
See original BITFIELD for more details.
BITFIELD_RO hello GET i8 16
bitop
Perform a bitwise operation between multiple keys (containing string values) and store the result in the destination key.
The BITOP command supports four bitwise operations: AND, OR, XOR
and NOT, thus the valid forms to call the command are:
BITOP AND destkey srckey1 srckey2 srckey3 ... srckeyNBITOP OR destkey srckey1 srckey2 srckey3 ... srckeyNBITOP XOR destkey srckey1 srckey2 srckey3 ... srckeyNBITOP NOT destkey srckey
As you can see NOT is special as it only takes an input key, because it performs inversion of bits so it only makes sense as a unary operator.
The result of the operation is always stored at destkey.
Handling of strings with different lengths
When an operation is performed between strings having different lengths, all the strings shorter than the longest string in the set are treated as if they were zero-padded up to the length of the longest string.
The same holds true for non-existent keys, that are considered as a stream of zero bytes up to the length of the longest string.
Examples
127.0.0.1:6379> SET key1 "foobar"
OK
127.0.0.1:6379> SET key2 "abcdef"
OK
127.0.0.1:6379> BITOP AND dest key1 key2
(integer) 6
127.0.0.1:6379> GET dest
"`bc`ab"
Pattern: real time metrics using bitmaps
BITOP is a good complement to the pattern documented in the BITCOUNT command
documentation.
Different bitmaps can be combined in order to obtain a target bitmap where
the population counting operation is performed.
See the article called "Fast easy realtime metrics using Valkey bitmaps" for an interesting use cases.
Performance considerations
BITOP is a potentially slow command as it runs in O(N) time.
Care should be taken when running it against long input strings.
For real-time metrics and statistics involving large inputs a good approach is to use a replica (with replica-read-only option enabled) where the bit-wise operations are performed to avoid blocking the primary instance.
bitpos
Return the position of the first bit set to 1 or 0 in a string.
The position is returned, thinking of the string as an array of bits from left to right, where the first byte's most significant bit is at position 0, the second byte's most significant bit is at position 8, and so forth.
The same bit position convention is followed by GETBIT and SETBIT.
By default, all the bytes contained in the string are examined.
It is possible to look for bits only in a specified interval by passing the additional arguments start and end. You can also just pass start, the operation will assume that the end is the last byte of the string. However there are semantic differences as explained later.
By default, the range is interpreted as a range of bytes and not a range of bits, so start=0 and end=2 means to look at the first three bytes.
You can use the optional BIT modifier to specify that the range should be interpreted as a range of bits.
So start=0 and end=2 means to look at the first three bits.
Note that bit positions are returned always as absolute values starting from bit zero even when start and end are used to specify a range.
Similar to the GETRANGE command, start and end can contain negative values in
order to index bytes starting from the end of the string, where -1 is the last
byte, -2 is the penultimate, and so forth. When BIT is specified, -1 is the last
bit, -2 is the penultimate, and so forth.
Non-existent keys are treated as empty strings.
Examples
127.0.0.1:6379> SET mykey "\xff\xf0\x00"
OK
127.0.0.1:6379> BITPOS mykey 0
(integer) 12
127.0.0.1:6379> SET mykey "\x00\xff\xf0"
OK
127.0.0.1:6379> BITPOS mykey 1 0
(integer) 8
127.0.0.1:6379> BITPOS mykey 1 2
(integer) 16
127.0.0.1:6379> BITPOS mykey 1 2 -1 BYTE
(integer) 16
127.0.0.1:6379> BITPOS mykey 1 7 15 BIT
(integer) 8
127.0.0.1:6379> set mykey "\x00\x00\x00"
OK
127.0.0.1:6379> BITPOS mykey 1
(integer) -1
127.0.0.1:6379> BITPOS mykey 1 7 -3 BIT
(integer) -1
blmove
BLMOVE is the blocking variant of LMOVE.
When source contains elements, this command behaves exactly like LMOVE.
When used inside a MULTI/EXEC block, this command behaves exactly like LMOVE.
When source is empty, Valkey will block the connection until another client
pushes to it or until timeout (a double value specifying the maximum number of seconds to block) is reached.
A timeout of zero can be used to block indefinitely.
This command comes in place of the now deprecated BRPOPLPUSH. Doing
BLMOVE RIGHT LEFT is equivalent.
See LMOVE for more information.
Pattern: Reliable queue
Please see the pattern description in the LMOVE documentation.
Pattern: Circular list
Please see the pattern description in the LMOVE documentation.
blmpop
BLMPOP is the blocking variant of LMPOP.
When any of the lists contains elements, this command behaves exactly like LMPOP.
When used inside a MULTI/EXEC block, this command behaves exactly like LMPOP.
When all lists are empty, Valkey will block the connection until another client pushes to it or until the timeout (a double value specifying the maximum number of seconds to block) elapses.
A timeout of zero can be used to block indefinitely.
See LMPOP for more information.
blpop
BLPOP is a blocking list pop primitive.
It is the blocking version of LPOP because it blocks the connection when there
are no elements to pop from any of the given lists.
An element is popped from the head of the first list that is non-empty, with the
given keys being checked in the order that they are given.
Non-blocking behavior
When BLPOP is called, if at least one of the specified keys contains a
non-empty list, an element is popped from the head of the list and returned to
the caller together with the key it was popped from.
Keys are checked in the order that they are given.
Let's say that the key list1 doesn't exist and list2 and list3 hold
non-empty lists.
Consider the following command:
BLPOP list1 list2 list3 0
BLPOP guarantees to return an element from the list stored at list2 (since
it is the first non empty list when checking list1, list2 and list3 in
that order).
Blocking behavior
If none of the specified keys exist, BLPOP blocks the connection until another
client performs an LPUSH or RPUSH operation against one of the keys.
Once new data is present on one of the lists, the client returns with the name of the key unblocking it and the popped value.
When BLPOP causes a client to block and a non-zero timeout is specified,
the client will unblock returning a nil multi-bulk value when the specified
timeout has expired without a push operation against at least one of the
specified keys.
The timeout argument is interpreted as a double value specifying the maximum number of seconds to block. A timeout of zero can be used to block indefinitely.
What key is served first? What client? What element? Priority ordering details.
- If the client tries to blocks for multiple keys, but at least one key contains elements, the returned key / element pair is the first key from left to right that has one or more elements. In this case the client is not blocked. So for instance
BLPOP key1 key2 key3 key4 0, assuming that bothkey2andkey4are non-empty, will always return an element fromkey2. - If multiple clients are blocked for the same key, the first client to be served is the one that was waiting for more time (the first that blocked for the key). Once a client is unblocked it does not retain any priority, when it blocks again with the next call to
BLPOPit will be served accordingly to the number of clients already blocked for the same key, that will all be served before it (from the first to the last that blocked). - When a client is blocking for multiple keys at the same time, and elements are available at the same time in multiple keys (because of a transaction or a Lua script added elements to multiple lists), the client will be unblocked using the first key that received a push operation (assuming it has enough elements to serve our client, as there may be other clients as well waiting for this key). Basically after the execution of every command Valkey will run a list of all the keys that received data AND that have at least a client blocked. The list is ordered by new element arrival time, from the first key that received data to the last. For every key processed, Valkey will serve all the clients waiting for that key in a FIFO fashion, as long as there are elements in this key. When the key is empty or there are no longer clients waiting for this key, the next key that received new data in the previous command / transaction / script is processed, and so forth.
Behavior of BLPOP when multiple elements are pushed inside a list.
There are times when a list can receive multiple elements in the context of the same conceptual command:
- Variadic push operations such as
LPUSH mylist a b c. - After an
EXECof aMULTIblock with multiple push operations against the same list. - Executing a Lua Script.
What happens is that the command performing multiple pushes is executed, and only after the execution of the command the blocked clients are served. Consider this sequence of commands.
Client A: BLPOP foo 0
Client B: LPUSH foo a b c
If the above condition happens using a Redis OSS 2.6 server or greater, Client A will be served with the c element, because after the LPUSH command the list contains c,b,a, so taking an element from the left means to return c.
Note that for the same reason a Lua script or a MULTI/EXEC block may push elements into a list and afterward delete the list. In this case the blocked clients will not be served at all and will continue to be blocked as long as no data is present on the list after the execution of a single command, transaction, or script.
BLPOP inside a MULTI / EXEC transaction
BLPOP can be used with pipelining (sending multiple commands and
reading the replies in batch), however this setup makes sense almost solely
when it is the last command of the pipeline.
Using BLPOP inside a MULTI/EXEC block does not make a lot of sense
as it would require blocking the entire server in order to execute the block
atomically, which in turn does not allow other clients to perform a push
operation. For this reason the behavior of BLPOP inside MULTI / EXEC when the list is empty is to return a nil multi-bulk reply, which is the same
thing that happens when the timeout is reached.
If you like science fiction, think of time flowing at infinite speed inside a
MULTI / EXEC block...
Examples
127.0.0.1:6379> DEL list1 list2
(integer) 0
127.0.0.1:6379> RPUSH list1 a b c
(integer) 3
127.0.0.1:6379> BLPOP list1 list2 0
1) "list1"
2) "a"
Reliable queues
When BLPOP returns an element to the client, it also removes the element from the list. This means that the element only exists in the context of the client: if the client crashes while processing the returned element, it is lost forever.
This can be a problem with some application where we want a more reliable messaging system. When this is the case, please check the BRPOPLPUSH command, that is a variant of BLPOP that adds the returned element to a target list before returning it to the client.
Pattern: Event notification
Using blocking list operations it is possible to mount different blocking
primitives.
For instance for some application you may need to block waiting for elements
into a Set, so that as far as a new element is added to the Set, it is
possible to retrieve it without resort to polling.
This would require a blocking version of SPOP that is not available, but using
blocking list operations we can easily accomplish this task.
The consumer will do:
LOOP forever
WHILE SPOP(key) returns elements
... process elements ...
END
BRPOP helper_key
END
While in the producer side we'll use simply:
MULTI
SADD key element
LPUSH helper_key x
EXEC
brpop
BRPOP is a blocking list pop primitive.
It is the blocking version of RPOP because it blocks the connection when there
are no elements to pop from any of the given lists.
An element is popped from the tail of the first list that is non-empty, with the
given keys being checked in the order that they are given.
See the BLPOP documentation for the exact semantics, since BRPOP is
identical to BLPOP with the only difference being that it pops elements from
the tail of a list instead of popping from the head.
Examples
127.0.0.1:6379> DEL list1 list2
(integer) 0
127.0.0.1:6379> RPUSH list1 a b c
(integer) 3
127.0.0.1:6379> BRPOP list1 list2 0
1) "list1"
2) "c"
brpoplpush
BRPOPLPUSH is the blocking variant of RPOPLPUSH.
When source contains elements, this command behaves exactly like RPOPLPUSH.
When used inside a MULTI/EXEC block, this command behaves exactly like RPOPLPUSH.
When source is empty, Valkey will block the connection until another client
pushes to it or until timeout is reached.
A timeout of zero can be used to block indefinitely.
See RPOPLPUSH for more information.
Pattern: Reliable queue
Please see the pattern description in the RPOPLPUSH documentation.
Pattern: Circular list
Please see the pattern description in the RPOPLPUSH documentation.
Alternative
BLMOVE with the RIGHT and LEFT arguments.
bzmpop
BZMPOP is the blocking variant of ZMPOP.
When any of the sorted sets contains elements, this command behaves exactly like ZMPOP.
When used inside a MULTI/EXEC block, this command behaves exactly like ZMPOP.
When all sorted sets are empty, Valkey will block the connection until another client adds members to one of the keys or until the timeout (a double value specifying the maximum number of seconds to block) elapses.
A timeout of zero can be used to block indefinitely.
See ZMPOP for more information.
bzpopmax
BZPOPMAX is the blocking variant of the sorted set ZPOPMAX primitive.
It is the blocking version because it blocks the connection when there are no members to pop from any of the given sorted sets. A member with the highest score is popped from first sorted set that is non-empty, with the given keys being checked in the order that they are given.
The timeout argument is interpreted as a double value specifying the maximum
number of seconds to block. A timeout of zero can be used to block indefinitely.
See the BZPOPMIN documentation for the exact semantics, since BZPOPMAX
is identical to BZPOPMIN with the only difference being that it pops members
with the highest scores instead of popping the ones with the lowest scores.
Examples
127.0.0.1:6379> DEL zset1 zset2
(integer) 0
127.0.0.1:6379> ZADD zset1 0 a 1 b 2 c
(integer) 3
127.0.0.1:6379> BZPOPMAX zset1 zset2 0
1) "zset1"
2) "c"
3) "2"
bzpopmin
BZPOPMIN is the blocking variant of the sorted set ZPOPMIN primitive.
It is the blocking version because it blocks the connection when there are no members to pop from any of the given sorted sets. A member with the lowest score is popped from first sorted set that is non-empty, with the given keys being checked in the order that they are given.
The timeout argument is interpreted as a double value specifying the maximum
number of seconds to block. A timeout of zero can be used to block indefinitely.
See the BLPOP documentation for the exact semantics, since BZPOPMIN is
identical to BLPOP with the only difference being the data structure being
popped from.
Examples
127.0.0.1:6379> DEL zset1 zset2
(integer) 0
127.0.0.1:6379> ZADD zset1 0 a 1 b 2 c
(integer) 3
127.0.0.1:6379> BZPOPMIN zset1 zset2 0
1) "zset1"
2) "a"
3) "0"
client-caching
This command controls the tracking of the keys in the next command executed
by the connection, when tracking is enabled in OPTIN or OPTOUT mode.
Please check the
client side caching documentation for
background information.
When tracking is enabled Valkey, using the CLIENT TRACKING command, it is
possible to specify the OPTIN or OPTOUT options, so that keys
in read only commands are not automatically remembered by the server to
be invalidated later. When we are in OPTIN mode, we can enable the
tracking of the keys in the next command by calling CLIENT CACHING yes
immediately before it. Similarly when we are in OPTOUT mode, and keys
are normally tracked, we can avoid the keys in the next command to be
tracked using CLIENT CACHING no.
Basically the command sets a state in the connection, that is valid only for the next command execution, that will modify the behavior of client tracking.
client-capa
Clients can declare their capabilities to Valkey using the CLIENT CAPA command, and Valkey
will adjust the corresponding features for the current connection based on the declared client capabilities.
Multiple capabilities can be declared in the command. If any capabilities are unrecognized, Valkey will ignore them instead of returning an error.
The capabilities currently supported are:
redirect- This indicates that the client is capable of handling redirect messages. When accessing a replica node in standalone mode, if a data operation is performed (read or write commands), Valkey will return-REDIRECT primary-ip:portto this connection. Note that theprimary-ipcan be an IPv6 which itself contains colons, so to properly parse ip and port, a client needs to locate the last colon. Using theREADONLYcommand can enable this connection to execute read commands on the replica node.
client-getname
The CLIENT GETNAME returns the name of the current connection as set by CLIENT SETNAME. Since every new connection starts without an associated name, if no name was assigned a null bulk reply is returned.
client-getredir
This command returns the client ID we are redirecting our
tracking notifications to. We set a client
to redirect to when using CLIENT TRACKING to enable tracking. However in
order to avoid forcing client libraries implementations to remember the
ID notifications are redirected to, this command exists in order to improve
introspection and allow clients to check later if redirection is active
and towards which client ID.
client-help
The CLIENT HELP command returns a helpful text describing the different subcommands.
client-id
The command just returns the ID of the current connection. Every connection ID has certain guarantees:
- It is never repeated, so if
CLIENT IDreturns the same number, the caller can be sure that the underlying client did not disconnect and reconnect the connection, but it is still the same connection. - The ID is monotonically incremental. If the ID of a connection is greater than the ID of another connection, it is guaranteed that the second connection was established with the server at a later time.
This command is especially useful together with CLIENT UNBLOCK.
Check the CLIENT UNBLOCK command page for a pattern involving the two commands.
Examples
127.0.0.1:6379> CLIENT ID
(integer) 2873
client-import-source
When the client sync data from a Redis-like server to Valkey using some sync tools like RedisShake, Valkey performs expiration and eviction as usual because it's a primary, which may cause data corruption. For example, the client calls set key 1 ex 1 on the source server and this command is transferred to the destination server. Then the client calls incr key on the source server before the key expired, there will be a key on the source server with the value of 2. But when the command arrived at the destination server, the key may be expired and has deleted. So there will be a key on the destination server with the value of 1, which is inconsistent with the source server. Sync tools can solve this problem by setting import-mode config to yes and declaring their connections as IMPORT-SOURCE.
The CLIENT IMPORT-SOURCE command mark this client as an import source if import-mode is enabled and can visit expired keys. The following modes are available:
ON. In this mode the client can visit expired keys.OFF. This is the default mode in which the client works as a normal client.
Notes
The server needs to be configured with import-mode yes before marking a client connection as an import source.
client-info
The command returns information and statistics about the current client connection in a mostly human readable format.
The reply format is identical to that of CLIENT LIST, and the content consists only of information about the current client.
Examples
127.0.0.1:6379> CLIENT INFO
id=2875 addr=127.0.0.1:38610 laddr=127.0.0.1:6379 fd=10 name= age=0 idle=0 flags=N capa= db=0 sub=0 psub=0 ssub=0 multi=-1 watch=0 qbuf=26 qbuf-free=20448 argv-mem=10 multi-mem=0 rbs=16384 rbp=16384 obl=0 oll=0 omem=0 tot-mem=37786 events=r cmd=client|info user=default redir=-1 resp=2 lib-name= lib-ver=
client-kill
The CLIENT KILL command closes a given client connection. This command support two formats, the old format:
CLIENT KILL addr:port
The ip:port should match a line returned by the CLIENT LIST command (addr field).
The new format:
CLIENT KILL <filter> <value> ... ... <filter> <value>
With the new form it is possible to kill clients by different attributes instead of killing just by address. The following filters are available:
CLIENT KILL ADDR ip:port. This is exactly the same as the old three-arguments behavior.CLIENT KILL LADDR ip:port. Kill all clients connected to specified local (bind) address.CLIENT KILL ID client-id [client-id ...]. Allows to kill a client by its uniqueIDfield. ClientID's can be retrieved using theCLIENT LISTcommand. The filter supports one or moreclient-idarguments.CLIENT KILL TYPE type, where type is one ofnormal,master,replicaandpubsub. This closes the connections of all the clients in the specified class. Note that clients blocked into theMONITORcommand are considered to belong to thenormalclass.CLIENT KILL USER username. Closes all the connections that are authenticated with the specified ACL username, however it returns an error if the username does not map to an existing ACL user.CLIENT KILL SKIPME yes/no. By default this option is set toyes, that is, the client calling the command will not get killed, however setting this option tonowill have the effect of also killing the client calling the command.CLIENT KILL MAXAGE maxage. Closes all the connections that are older than the specified age, in seconds.CLIENT KILL FLAGS flags. Kill only clients whose flag string includes the specified characters. Returns an error if valid flags are not used.CLIENT KILL NAME name. Kill clients with the specified name.CLIENT KILL IDLE idle. Kill only clients that have been idle for at least the specified time.CLIENT KILL LIB-NAME lib-name. Kill clients using the specified library name.CLIENT KILL LIB-VER lib-version. Kill clients running the specified library version.CLIENT KILL DB db. Kill clients operating on the specified database id.CLIENT KILL IP ip. Kill clients with the specified originating IP address.CLIENT KILL CAPA capa. Kill clients that have the specified capabilities.CLIENT KILL NOT-ID client-id [client-id ...]. Kill clients are not in the IDs set.CLIENT KILL NOT-TYPE type. Kill clients are not in the specified type.CLIENT KILL NOT-ADDR ip:port. Kill clients except the specified ip and port.CLIENT KILL NOT-LADDR ip:port. Kill all clients not connected to specified local (bind) address.CLIENT KILL NOT-USER username. Closes all the connections that are not authenticated with the specified ACL username.CLIENT KILL NOT-FLAGS flags. Kill clients not with the specified flag string.CLIENT KILL NOT-NAME name. Kill clients not with the specified name.CLIENT KILL NOT-LIB-NAME lib-name. Kill clients not using the specified library name.CLIENT KILL NOT-LIB-VER lib-version. Kill clients not with the specified library version.CLIENT KILL NOT-DB db. Kill clients not with the specified database ID.CLIENT KILL NOT-CAPA capa. Kill clients not with the specified capabilities.CLIENT KILL NOT-IP ip. Kill clients not with the specified IP address.
It is possible to provide multiple filters at the same time. The command will handle multiple filters via logical AND. For example:
CLIENT KILL addr 127.0.0.1:12345 type pubsub
is valid and will kill only a pubsub client with the specified address. This format containing multiple filters is rarely useful currently.
When the new form is used the command no longer returns OK or an error, but instead the number of killed clients, that may be zero.
CLIENT KILL and Valkey Sentinel
Valkey Sentinel uses CLIENT KILL to terminate client connections when an instance is reconfigured. This mechanism ensures that clients re-establish a connection with a Sentinel, refreshing their configurations.
Notes
Due to the single-threaded nature of Valkey, it is not possible to kill a client connection while it is executing a command. From the client point of view, the connection can never be closed in the middle of the execution of a command. However, the client will notice the connection has been closed only when the next command is sent (and results in network error).
client-list
The CLIENT LIST command returns information and statistics about the client
connections server in a mostly human readable format.
You can use one or more optional arguments to filter the list:
-
TYPE type: Filters the list by clients' type, where type is one ofnormal,master,replica, andpubsub.Note: Clients blocked by the
MONITORcommand belong to thenormalclass. -
ID client-id [client-id ...]: Returns entries for clients with IDs matching one or moreclient-idarguments. -
USER user: Filters the list to include only clients authenticated as the specified user. -
ADDR ip:port: Filters the list to include only clients connected from the specified address and port. -
LADDR ip:port: Filters the list to include only clients connected to the specified local address and port. -
SKIPME yes|no: Filters whether the list should skip the client making the request.yes: Skips the client making the request.no: Includes the client making the request.
-
MAXAGE milliseconds: Filters the list to include only clients whose connection age (time since the client was created) is greater than or equal to the specified number of milliseconds.Note: This is actually a minimum age, not a maximum age. This filter was first added to CLIENT KILL, where the intention was to keep clients of a maximum age and kill the ones newer than the max age.
-
FLAGS flags: Filters the list by the client's flag string. -
NAME name: Filters the list to include only clients with the specified name. -
IDLE idle: Includes only clients that have been idle for at least the specified time. -
LIB-NAME lib-name: Filters the list to include only clients using the specified library name. -
LIB-VER lib-ver: Filters the list to include only clients with the specified library version. -
DB db: Filters the list to include only clients with the specified database ID. -
IP ip: Filters the list to include only clients with the specified IP address. -
CAPA capa: Filters the list to include only clients with the specified capabilities. -
NOT-ID client-id [client-id ...]: Excludes clients in the IDs set. -
NOT-TYPE type: Excludes clients of the specified type. -
NOT-ADDR ip:port: Excludes clients of the specified address and port. -
NOT-LADDR ip:port: Excludes clients connected to the specified local address and port. -
NOT-USER user: Excludes clients of the specified user. -
NOT-FLAGS flags: Excludes clients with the specified flag string. -
NOT-NAME name: Excludes clients with the specified name. -
NOT-LIB-NAME lib-name: Excludes clients using the specified library name. -
NOT-LIB-VER lib-ver: Excludes clients with the specified library version. -
NOT-DB db: Excludes clients with the specified database ID. -
NOT-CAPA capa: Excludes clients with the specified capabilities. -
NOT-IP ip: Excludes clients with the specified IP address.
Filters can be combined to perform more precise searches. The command will handle multiple filters via logical AND.
Here is the meaning of the fields:
id: a unique 64-bit client IDaddr: address/port of the clientladdr: address/port of local address client connected to (bind address)fd: file descriptor corresponding to the socketname: the name set by the client withCLIENT SETNAMEage: total duration of the connection in secondsidle: idle time of the connection in secondsflags: client flags (see below)capa: client capabilities (see below). Added in Valkey 8.1db: current database IDsub: number of channel subscriptionspsub: number of pattern matching subscriptionsssub: number of shard channel subscriptions.multi: number of commands in a MULTI/EXEC contextwatch: number of keys this client is currently watching. Added in Valkey 8.0qbuf: query buffer length (0 means no query pending)qbuf-free: free space of the query buffer (0 means the buffer is full)argv-mem: incomplete arguments for the next command (already extracted from query buffer)multi-mem: memory is used up by buffered multi commands.obl: output buffer lengtholl: output list length (replies are queued in this list when the buffer is full)omem: output buffer memory usagetot-mem: total memory consumed by this client in its various buffersevents: file descriptor events (see below)cmd: last command playeduser: the authenticated username of the clientredir: client id of current client tracking redirectionresp: client RESP protocol version.lib-name: The client library name as set byCLIENT SETINFOlib-version: The client library version as set byCLIENT SETINFOtot-net-in: Total network input bytes read from this client. Added in Valkey 8.0tot-net-out: Total network output bytes sent to this client. Added in Valkey 8.0tot-cmds: Total count of commands this client executed. Added in Valkey 8.0
The client flags can be a combination of:
A: connection to be closed ASAP
b: the client is waiting in a blocking operation
c: connection to be closed after writing entire reply
d: a watched keys has been modified - EXEC will fail
e: the client is excluded from the client eviction mechanism
i: the client is waiting for a VM I/O (deprecated)
M: the client is a primary
N: no specific flag set
O: the client is a client in MONITOR mode
P: the client is a Pub/Sub subscriber
r: the client is in readonly mode against a cluster node
S: the client is a replica node connection to this instance
u: the client is unblocked
U: the client is connected via a Unix domain socket
x: the client is in a MULTI/EXEC context
t: the client enabled keys tracking in order to perform client side caching
T: the client will not touch the LRU/LFU of the keys it accesses
R: the client tracking target client is invalid
B: the client enabled broadcast tracking mode
I: the client is an import source
Client's capabilities can be:
r: the client can handle redirect messages
The file descriptor events can be:
r: the client socket is readable (event loop)
w: the client socket is writable (event loop)
Examples
CLIENT LIST TYPE normal USER admin MAXAGE 5000 ID 1234 5678
id=1234 addr=127.0.0.1:64000 laddr=127.0.0.1:6379 fd=5 name= age=600 idle=300 flags= db=0 sub=0 psub=0 ssub=0 multi=-1 watch=0 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 tot-mem=1024 events=r cmd=client|list user=default redir=-1 resp=2 lib-name= lib-ver=
id=5678 addr=127.0.0.1:64001 laddr=127.0.0.1:6379 fd=6 name= age=900 idle=450 flags= db=0 sub=0 psub=0 ssub=0 multi=-1 watch=0 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 tot-mem=2048 events=r cmd=client|list user=default redir=-1 resp=2 lib-name= lib-ver=
Notes
New fields are regularly added for debugging purpose. Some could be removed in the future. A version safe Valkey client using this command should parse the output accordingly (i.e. handling gracefully missing fields, skipping unknown fields).
client-no-evict
The CLIENT NO-EVICT command sets the client eviction mode for the current connection.
When turned on and client eviction is configured, the current connection will be excluded from the client eviction process even if we're above the configured client eviction threshold.
When turned off, the current client will be re-included in the pool of potential clients to be evicted (and evicted if needed).
See client eviction for more details.
client-no-touch
The CLIENT NO-TOUCH command controls whether commands sent by the client will alter the LRU/LFU of the keys they access.
When turned on, the current client will not change LFU/LRU stats, unless it sends the TOUCH command.
When turned off, the client touches LFU/LRU stats just as a normal client.
client-pause
CLIENT PAUSE is a connections control command able to suspend all the Valkey clients for the specified amount of time (in milliseconds).
The command performs the following actions:
- It stops processing all the pending commands from normal and pub/sub clients for the given mode. However interactions with replicas will continue normally. Note that clients are formally paused when they try to execute a command, so no work is taken on the server side for inactive clients.
- However it returns OK to the caller ASAP, so the
CLIENT PAUSEcommand execution is not paused by itself. - When the specified amount of time has elapsed, all the clients are unblocked: this will trigger the processing of all the commands accumulated in the query buffer of every client during the pause.
Client pause currently supports two modes:
ALL: This is the default mode. All client commands are blocked.WRITE: Clients are only blocked if they attempt to execute a write command.
For the WRITE mode, some commands have special behavior:
EVAL/EVALSHA: Will block client for all scripts.PUBLISH: Will block client.PFCOUNT: Will block client.WAIT/WAITAOF: Acknowledgments will be delayed, so these commands will appear blocked.
This command is useful as it makes able to switch clients from a Valkey instance to another one in a controlled way. For example during an instance upgrade the system administrator could do the following:
- Pause the clients using
CLIENT PAUSE - Wait a few seconds to make sure the replicas processed the latest replication stream from the primary.
- Turn one of the replicas into a primary.
- Reconfigure clients to connect with the new primary.
The recommended mode for client pause is WRITE. This mode will stop all replication traffic, can be
aborted with the CLIENT UNPAUSE command, and allows reconfiguring the old primary without risking accepting writes after the
failover. This is also the mode used during cluster failover.
This command also prevents keys to be evicted or expired during the time clients are paused. This way the dataset is guaranteed to be static not just from the point of view of clients not being able to write, but also from the point of view of internal operations.
client-reply
Sometimes it can be useful for clients to completely disable replies from the Valkey server. For example when the client sends fire and forget commands or performs a mass loading of data, or in caching contexts where new data is streamed constantly. In such contexts to use server time and bandwidth in order to send back replies to clients, which are going to be ignored, is considered wasteful.
The CLIENT REPLY command controls whether the server will reply the client's commands. The following modes are available:
ON. This is the default mode in which the server returns a reply to every command.OFF. In this mode the server will not reply to client commands.SKIP. This mode skips the reply of command immediately after it.
Note:
Starting with Valkey 9.0, the CLIENT REPLY command is disallowed inside a transaction (MULTI/EXEC). In earlier versions, using CLIENT REPLY within a transaction could corrupt the reply stream. Attempting to use it within a transaction now results in an error reply.
client-setinfo
The CLIENT SETINFO command assigns various info attributes to the current connection which are displayed in the output of CLIENT LIST and CLIENT INFO.
Client libraries are expected to pipeline this command after authentication on all connections and ignore failures since they could be connected to an older version that doesn't support them.
Currently the supported attributes are:
lib-name- meant to hold the name of the client library that's in use.lib-ver- meant to hold the client library's version.
There is no limit to the length of these attributes. However it is not possible to use spaces, newlines, or other non-printable characters that would violate the format of the CLIENT LIST reply.
Note that these attributes are not cleared by the RESET command.
client-setname
The CLIENT SETNAME command assigns a name to the current connection.
The assigned name is displayed in the output of CLIENT LIST so that it is possible to identify the client that performed a given connection.
For instance when Valkey is used in order to implement a queue, producers and consumers of messages may want to set the name of the connection according to their role.
There is no limit to the length of the name that can be assigned if not the usual limits of the String type (512 MB). However it is not possible to use spaces in the connection name as this would violate the format of the CLIENT LIST reply.
It is possible to entirely remove the connection name setting it to the empty string, that is not a valid connection name since it serves to this specific purpose.
The connection name can be inspected using CLIENT GETNAME.
Every new connection starts without an assigned name.
Tip: setting names to connections is a good way to debug connection leaks due to bugs in the application using Valkey.
client-tracking
This command enables the tracking feature of the Valkey server, that is used for server assisted client side caching.
When tracking is enabled Valkey remembers the keys that the connection requested, in order to send later invalidation messages when such keys are modified. Invalidation messages are sent in the same connection (only available when the RESP3 protocol is used) or redirected in a different connection (available also with RESP2 and Pub/Sub). A special broadcasting mode is available where clients participating in this protocol receive every notification just subscribing to given key prefixes, regardless of the keys that they requested. Given the complexity of the argument please refer to the main client side caching documentation for the details. This manual page is only a reference for the options of this subcommand.
In order to enable tracking, use:
CLIENT TRACKING on ... options ...
The feature will remain active in the current connection for all its life,
unless tracking is turned off with CLIENT TRACKING off at some point.
The following are the list of options that modify the behavior of the command when enabling tracking:
REDIRECT <id>: send invalidation messages to the connection with the specified ID. The connection must exist. You can get the ID of a connection usingCLIENT ID. If the connection we are redirecting to is terminated, when in RESP3 mode the connection with tracking enabled will receivetracking-redir-brokenpush messages in order to signal the condition.BCAST: enable tracking in broadcasting mode. In this mode invalidation messages are reported for all the prefixes specified, regardless of the keys requested by the connection. Instead when the broadcasting mode is not enabled, Valkey will track which keys are fetched using read-only commands, and will report invalidation messages only for such keys.PREFIX <prefix>: for broadcasting, register a given key prefix, so that notifications will be provided only for keys starting with this string. This option can be given multiple times to register multiple prefixes. If broadcasting is enabled without this option, Valkey will send notifications for every key. You can't delete a single prefix, but you can delete all prefixes by disabling and re-enabling tracking. Using this option adds the additional time complexity of O(N^2), where N is the total number of prefixes tracked.OPTIN: when broadcasting is NOT active, normally don't track keys in read only commands, unless they are called immediately after aCLIENT CACHING yescommand.OPTOUT: when broadcasting is NOT active, normally track keys in read only commands, unless they are called immediately after aCLIENT CACHING nocommand.NOLOOP: don't send notifications about keys modified by this connection itself.
client-trackinginfo
The command returns information about the current client connection's use of the server assisted client side caching feature.
Here's the list of tracking information sections and their respective values:
- flags: A list of tracking flags used by the connection. The flags and their meanings are as follows:
off: The connection isn't using server assisted client side caching.on: Server assisted client side caching is enabled for the connection.bcast: The client uses broadcasting mode.optin: The client does not cache keys by default.optout: The client caches keys by default.caching-yes: The next command will cache keys (exists only together withoptin).caching-no: The next command won't cache keys (exists only together withoptout).noloop: The client isn't notified about keys modified by itself.broken_redirect: The client ID used for redirection isn't valid anymore.
- redirect: The client ID used for notifications redirection, or -1 when none.
- prefixes: A list of key prefixes for which notifications are sent to the client.
client-unblock
This command can unblock, from a different connection, a client blocked in a blocking operation, such as for instance BRPOP or XREAD or WAIT.
By default the client is unblocked as if the timeout of the command was reached, however if an additional (and optional) argument is passed, it is possible to specify the unblocking behavior, that can be TIMEOUT (the default) or ERROR. If ERROR is specified, the behavior is to unblock the client returning as error the fact that the client was force-unblocked. Specifically the client will receive the following error:
-UNBLOCKED client unblocked via CLIENT UNBLOCK
Note: of course as usually it is not guaranteed that the error text remains
the same, however the error code will remain -UNBLOCKED.
This command is useful especially when we are monitoring many keys with
a limited number of connections. For instance we may want to monitor multiple
streams with XREAD without using more than N connections. However at some
point the consumer process is informed that there is one more stream key
to monitor. In order to avoid using more connections, the best behavior would
be to stop the blocking command from one of the connections in the pool, add
the new key, and issue the blocking command again.
To obtain this behavior the following pattern is used. The process uses
an additional control connection in order to send the CLIENT UNBLOCK command
if needed. In the meantime, before running the blocking operation on the other
connections, the process runs CLIENT ID in order to get the ID associated
with that connection. When a new key should be added, or when a key should
no longer be monitored, the relevant connection blocking command is aborted
by sending CLIENT UNBLOCK in the control connection. The blocking command
will return and can be finally reissued.
This example shows the application in the context of streams, however the pattern is a general one and can be applied to other cases.
Examples
Connection A (blocking connection):
> CLIENT ID
2934
> BRPOP key1 key2 key3 0
(client is blocked)
... Now we want to add a new key ...
Connection B (control connection):
> CLIENT UNBLOCK 2934
1
Connection A (blocking connection):
... BRPOP reply with timeout ...
NULL
> BRPOP key1 key2 key3 key4 0
(client is blocked again)
client-unpause
CLIENT UNPAUSE is used to resume command processing for all clients that were paused by CLIENT PAUSE.
client
This is a container command for client connection commands.
To see the list of available commands you can call CLIENT HELP.
cluster-addslots
This command is useful in order to modify a node's view of the cluster configuration. Specifically it assigns a set of hash slots to the node receiving the command. If the command is successful, the node will map the specified hash slots to itself, and will start broadcasting the new configuration.
However note that:
- The command only works if all the specified slots are, from the point of view of the node receiving the command, currently not assigned. A node will refuse to take ownership for slots that already belong to some other node (including itself).
- The command fails if the same slot is specified multiple times.
- As a side effect of the command execution, if a slot among the ones specified as argument is set as
importing, this state gets cleared once the node assigns the (previously unbound) slot to itself.
Example
For example the following command assigns slots 1 2 3 to the node receiving the command:
> CLUSTER ADDSLOTS 1 2 3
OK
However trying to execute it again results into an error since the slots are already assigned:
> CLUSTER ADDSLOTS 1 2 3
ERR Slot 1 is already busy
Usage in Valkey Cluster
This command only works in cluster mode and is useful in the following Valkey Cluster operations:
- To create a new
cluster ADDSLOTSis used in order to initially setup primary nodes splitting the available hash slots among them. - In order to fix a broken cluster where certain slots are unassigned.
Information about slots propagation and warnings
Note that once a node assigns a set of slots to itself, it will start propagating this information in heartbeat packet headers. However the other nodes will accept the information only if they have the slot as not already bound with another node, or if the configuration epoch of the node advertising the new hash slot, is greater than the node currently listed in the table.
This means that this command should be used with care only by applications
orchestrating Valkey Cluster, like valkey-cli, and the command if used
out of the right context can leave the cluster in a wrong state or cause
data loss.
cluster-addslotsrange
The CLUSTER ADDSLOTSRANGE is similar to the CLUSTER ADDSLOTS command in that they both assign hash slots to nodes.
The difference between the two commands is that CLUSTER ADDSLOTS takes a list of slots to assign to the node, while CLUSTER ADDSLOTSRANGE takes a list of slot ranges (specified by start and end slots) to assign to the node.
Example
To assign slots 1 2 3 4 5 to the node, the CLUSTER ADDSLOTS command is:
> CLUSTER ADDSLOTS 1 2 3 4 5
OK
The same operation can be completed with the following CLUSTER ADDSLOTSRANGE command:
> CLUSTER ADDSLOTSRANGE 1 5
OK
Usage in Valkey Cluster
This command only works in cluster mode and is useful in the following Valkey Cluster operations:
- To create a new cluster,
CLUSTER ADDSLOTSRANGEis used to initially set up primary nodes splitting the available hash slots among them. - In order to fix a broken cluster where certain slots are unassigned.
cluster-bumpepoch
Advances the cluster config epoch.
The CLUSTER BUMPEPOCH command triggers an increment to the cluster's config epoch from the connected node. The epoch will be incremented if the node's config epoch is zero, or if it is less than the cluster's greatest epoch.
Note: config epoch management is performed internally by the cluster, and relies on obtaining a consensus of nodes. The CLUSTER BUMPEPOCH attempts to increment the config epoch WITHOUT getting the consensus, so using it may violate the "last failover wins" rule. Use it with caution.
cluster-cancelslotmigrations
CLUSTER CANCELSLOTMIGRATIONS cancels all in progress
atomic slot migrations initiated through
CLUSTER MIGRATESLOTS.
Only slot migrations initiated on this node are cancelled. If this node is the target of a slot migration, the cancellation must be performed on the source node.
Because the migrations being cancelled may touch keys in any database, the
caller must have ACL access to all databases (the alldbs rule). See
database permissions.
cluster-count-failure-reports
The command returns the number of failure reports for the specified node.
Failure reports are the way Valkey Cluster uses in order to promote a
PFAIL state, that means a node is not reachable, to a FAIL state,
that means that the majority of primaries in the cluster agreed within
a window of time that the node is not reachable.
A few more details:
- A node flags another node with
PFAILwhen the node is not reachable for a time greater than the configured node timeout, which is a fundamental configuration parameter of a Valkey Cluster. - Nodes in
PFAILstate are provided in gossip sections of heartbeat packets. - Every time a node processes gossip packets from other nodes, it creates (and refreshes the TTL if needed) failure reports, remembering that a given node said another given node is in
PFAILcondition. However, once a node has been markedFAIL, additional failure reports are ignored. - Each failure report has a time to live of two times the node timeout time.
- If at a given time a node has another node flagged with
PFAIL, and at the same time collected the majority of other primary nodes failure reports about this node (including itself if it is a primary), then it elevates the failure state of the node fromPFAILtoFAIL, and broadcasts a message forcing all the nodes that can be reached to flag the node asFAIL.
This command returns the number of failure reports for the current node which are currently not expired (so received within two times the node timeout time). The count does not include what the node we are asking this count believes about the node ID we pass as argument, the count only includes the failure reports the node received from other nodes.
This command is mainly useful for debugging, when the failure detector of Valkey Cluster is not operating as we believe it should.
cluster-countkeysinslot
Returns the number of keys in the specified Valkey Cluster hash slot in the currently selected database. The command only queries the local data set, so contacting a node that is not serving the specified hash slot will always result in a count of zero being returned.
> CLUSTER COUNTKEYSINSLOT 7000
(integer) 50341
cluster-delslots
In Valkey Cluster, each node keeps track of which primary is serving a particular hash slot.
The CLUSTER DELSLOTS command asks a particular Valkey Cluster node to
forget which primary is serving the hash slots specified as arguments.
In the context of a node that has received a CLUSTER DELSLOTS command and
has consequently removed the associations for the passed hash slots,
we say those hash slots are unbound. Note that the existence of
unbound hash slots occurs naturally when a node has not been
configured to handle them (something that can be done with the
CLUSTER ADDSLOTS command) and if it has not received any information about
who owns those hash slots (something that it can learn from heartbeat
or update messages).
If a node with unbound hash slots receives a heartbeat packet from another node that claims to be the owner of some of those hash slots, the association is established instantly. Moreover, if a heartbeat or update message is received with a configuration epoch greater than the node's own, the association is re-established.
However, note that:
- The command only works if all the specified slots are already associated with some node.
- The command fails if the same slot is specified multiple times.
- As a side effect of the command execution, the node may go into down state because not all hash slots are covered.
Example
The following command removes the association for slots 5000 and 5001 from the node receiving the command:
> CLUSTER DELSLOTS 5000 5001
OK
Usage in Valkey Cluster
This command only works in cluster mode and may be useful for
debugging and in order to manually orchestrate a cluster configuration
when a new cluster is created. It is currently not used by valkey-cli,
and mainly exists for API completeness.
cluster-delslotsrange
The CLUSTER DELSLOTSRANGE command is similar to the CLUSTER DELSLOTS command in that they both remove hash slots from the node.
The difference is that CLUSTER DELSLOTS takes a list of hash slots to remove from the node, while CLUSTER DELSLOTSRANGE takes a list of slot ranges (specified by start and end slots) to remove from the node.
Example
To remove slots 1 2 3 4 5 from the node, the CLUSTER DELSLOTS command is:
> CLUSTER DELSLOTS 1 2 3 4 5
OK
The same operation can be completed with the following CLUSTER DELSLOTSRANGE command:
> CLUSTER DELSLOTSRANGE 1 5
OK
However, note that:
- The command only works if all the specified slots are already associated with the node.
- The command fails if the same slot is specified multiple times.
- As a side effect of the command execution, the node may go into down state because not all hash slots are covered.
Usage in Valkey Cluster
This command only works in cluster mode and may be useful for
debugging and in order to manually orchestrate a cluster configuration
when a new cluster is created. It is currently not used by valkey-cli,
and mainly exists for API completeness.
cluster-failover
This command, that can only be sent to a Valkey Cluster replica node, forces the replica to start a manual failover of its primary instance.
A manual failover is a special kind of failover that is usually executed when there are no actual failures, but we wish to swap the current primary with one of its replicas (which is the node we send the command to), in a safe way, without any window for data loss. It works in the following way:
- The replica tells the primary to stop processing queries from clients.
- The primary replies to the replica with the current replication offset.
- The replica waits for the replication offset to match on its side, to make sure it processed all the data from the primary before it continues.
- The replica starts a failover, obtains a new configuration epoch from the majority of the primaries, and broadcasts the new configuration.
- The old primary receives the configuration update: unblocks its clients and starts replying with redirection messages so that they'll continue the chat with the new primary.
This way clients are moved away from the old primary to the new primary atomically and only when the replica that is turning into the new primary has processed all of the replication stream from the old primary.
There is a built-in timeout for the primary to resume processing queries if the
replica does not catch quickly enough or is unable to secure the votes to take over.
The default failover timeout is 5000ms. It is possible to configure the timeout
via the cluster-manual-failover-timeout configuration parameter (added in Valkey 8.1)
and decide how long the primary will pause in the worst case scenario.
FORCE option: manual failover when the primary is down
The command behavior can be modified by two options: FORCE and TAKEOVER.
If the FORCE option is given, the replica does not perform any handshake with the primary, that may be not reachable, but instead just starts a failover ASAP starting from point 4. This is useful when we want to start a manual failover while the primary is no longer reachable.
However using FORCE we still need the majority of primaries to be available in order to authorize the failover and generate a new configuration epoch for the replica that is going to become primary.
TAKEOVER option: manual failover without cluster consensus
There are situations where this is not enough, and we want a replica to failover without any agreement with the rest of the cluster. A real world use case for this is to mass promote replicas in a different data center to primaries in order to perform a data center switch, while all the primaries are down or partitioned away.
The TAKEOVER option implies everything FORCE implies, but also does
not uses any cluster authorization in order to failover. A replica receiving
CLUSTER FAILOVER TAKEOVER will instead:
- Generate a new
configEpochunilaterally, just taking the current greatest epoch available and incrementing it if its local configuration epoch is not already the greatest. - Assign itself all the hash slots of its primary, and propagate the new configuration to every node which is reachable ASAP, and eventually to every other node.
Note that TAKEOVER violates the last-failover-wins principle of Valkey Cluster, since the configuration epoch generated by the replica violates the normal generation of configuration epochs in several ways:
- There is no guarantee that it is actually the higher configuration epoch, since, for example, we can use the TAKEOVER option within a minority, nor any message exchange is performed to generate the new configuration epoch.
- If we generate a configuration epoch which happens to collide with another instance, eventually our configuration epoch, or the one of another instance with our same epoch, will be moved away using the configuration epoch collision resolution algorithm.
Because of this the TAKEOVER option should be used with care.
Implementation details and notes
CLUSTER FAILOVER, unless the TAKEOVER option is specified, does not execute a failover synchronously. It only schedules a manual failover, bypassing the failure detection stage.- An
OKreply is no guarantee that the failover will succeed. - A replica can only be promoted to a primary if it is known as a replica by a majority of the primaries in the cluster.
If the replica is a new node that has just been added to the cluster (for example after upgrading it), it may not yet be known to all the primaries in the cluster.
To check that the primaries are aware of a new replica, you can send
CLUSTER NODESorCLUSTER REPLICASto each of the primary nodes and check that it appears as a replica, before sendingCLUSTER FAILOVERto the replica. - To check that the failover has actually happened you can use
ROLE,INFO REPLICATION(which indicates "role:master" after successful failover), orCLUSTER NODESto verify that the state of the cluster has changed sometime after the command was sent. - To check if the failover has failed, check the replica's log for "Manual failover timed out", which is logged if the replica has given up after a few seconds.
cluster-flushslots
Deletes all slots from a node.
The CLUSTER FLUSHSLOTS deletes all information about slots from the connected node. It can only be called when the database is empty.
cluster-forget
The command is used in order to remove a node, specified via its node ID, from the set of known nodes of the Valkey Cluster node receiving the command. In other words the specified node is removed from the nodes table of the node receiving the command.
Because when a given node is part of the cluster, all the other nodes
participating in the cluster knows about it, in order for a node to be
completely removed from a cluster, the CLUSTER FORGET command must be
sent to all the remaining nodes, regardless of the fact they are primaries
or replicas.
However the command cannot simply drop the node from the internal node table of the node receiving the command, it also implements a ban-list, not allowing the same node to be added again as a side effect of processing the gossip section of the heartbeat packets received from other nodes.
Details on why the ban-list is needed
In the following example we'll show why the command must not just remove a given node from the nodes table, but also prevent it for being re-inserted again for some time.
Let's assume we have four nodes, A, B, C and D. In order to end with just a three nodes cluster A, B, C we may follow these steps:
- Reshard all the hash slots from D to nodes A, B, C.
- D is now empty, but still listed in the nodes table of A, B and C.
- We contact A, and send
CLUSTER FORGET D. - B sends node A a heartbeat packet, where node D is listed.
- A does no longer known node D (see step 3), so it starts a handshake with D.
- D ends re-added in the nodes table of A.
As you can see in this way removing a node is fragile, we need to send
CLUSTER FORGET commands to all the nodes ASAP hoping there are no
gossip sections processing in the meantime. Because of this problem the
command implements a ban-list with an expire time for each entry.
So what the command really does is:
- The specified node gets removed from the nodes table.
- The node ID of the removed node gets added to the ban-list, for 1 minute.
- The node will skip all the node IDs listed in the ban-list when processing gossip sections received in heartbeat packets from other nodes.
This way we have a 60 second window to inform all the nodes in the cluster that we want to remove a node.
Special conditions not allowing the command execution
The command does not succeed and returns an error in the following cases:
- The specified node ID is not found in the nodes table.
- The node receiving the command is a replica, and the specified node ID identifies its current primary.
- The node ID identifies the same node we are sending the command to.
cluster-getkeysinslot
The command returns an array of key names stored in the contacted node and
hashing to the specified hash slot in the currently selected database.
The maximum number of keys to return is specified via the count argument,
so that it is possible for the user of this API to batch-process keys.
Note that this works only when deleting keys, as the same count keys are
returned on each call unless removed.
The main usage of this command is during rehashing of cluster slots from one
node to another. The way the rehashing is performed is exposed in the Valkey
Cluster specification, or in a more simple to digest form, as an appendix
of the CLUSTER SETSLOT command documentation.
> CLUSTER GETKEYSINSLOT 7000 3
1) "key_39015"
2) "key_89793"
3) "key_92937"
cluster-getslotmigrations
CLUSTER GETSLOTMIGRATIONS returns an array of information about in-progress
and recently completed
atomic slot migrations.
Each job previously started by CLUSTER MIGRATESLOTS
creates a single entry. The number of visible slot migration entries depends on
the configured cluster-slot-migration-log-max-len. After the limit is reached,
the oldest inactive entry is removed. Note that active slot migrations will
always be visible through CLUSTER GETSLOTMIGRATIONS, even if there are more
entries than the configured limit.
Information about the slot migration operations is stored in-memory and is not persisted across restarts. Slot migration entries are visible on the primary node of both the target and source shard and the replica nodes of the target shard.
The following information is reported for each slot migration entry:
name: A unique 40 byte name for the slot migrationoperation: The operation performed by the slot migration job on this node (eitherEXPORTorIMPORT)slot_ranges: The range(s) of slots being migrated, with both start and end inclusive. The start and end slot are separated by-in each range, and multiple ranges are joined together with a space ("").target_node: The primary node receiving the slot ownership as part of the migration. This information is only supplied on the primary node of the participating shards.source_node: The primary node sending the slot ownership as part of the migration. This information is only supplied on the primary node of the participating shards.create_time: The Unix timestamp (in seconds) when the slot migration was started.last_update_time: The Unix timestamp (in seconds) when the slot migration's status was last changed.last_ack_time: The Unix timestamp (in seconds) when the slot migration last received a heartbeat.state: The current state of the slot migration. The terminal states aresuccessif completed successfully,failedif some unexpected failure occurred, andcancelledif aCLUSTER CANCELSLOTMIGRATIONSrequest was received during the migration. Any other state denotes an active slot migration.message: Either a human readable status message, if there is more information to display about the state, or empty string if no message is available.cow_size: The copy-on-write overhead accumulated while the migration was in progress, in bytes.remaining_repl_size: The number of bytes remaining in the source node's output buffer that are pending to be sent to the target node during slot migration. Added in Valkey 9.1.
Examples
Response in RESP 2
127.0.0.1:30001> CLUSTER GETSLOTMIGRATIONS
1) 1) "name"
2) "5371b28997de6fd0bbe813ad8ebdfdf2faadb308"
3) "operation"
4) "EXPORT"
5) "slot_ranges"
6) "0-10"
7) "target_node"
8) "4b4f12fdfb58d5e30fef7b9ad3f1651dacbbaba9"
9) "source_node"
10) "93941e777e17fcbc92d4398cc957ffea888f472b"
11) "create_time"
12) (integer) 1754870400
13) "last_update_time"
14) (integer) 1754870400
15) "last_ack_time"
16) (integer) 1754870400
17) "state"
18) "success"
19) "message"
20) ""
21) "cow_size"
22) (integer) 0
23) "remaining_repl_size"
24) (integer) 0
Response in RESP 3
127.0.0.1:30001> CLUSTER GETSLOTMIGRATIONS
1) 1# "name" => "5371b28997de6fd0bbe813ad8ebdfdf2faadb308"
2# "operation" => "EXPORT"
3# "slot_ranges" => "0-10"
4# "target_node" => "4b4f12fdfb58d5e30fef7b9ad3f1651dacbbaba9"
5# "source_node" => "93941e777e17fcbc92d4398cc957ffea888f472b"
6# "create_time" => (integer) 1754870400
7# "last_update_time" => (integer) 1754870400
8# "last_ack_time" => (integer) 1754870400
9# "state" => "success"
10# "message" => ""
11# "cow_size" => (integer) 0
12# "remaining_repl_size" => (integer) 0
cluster-help
The CLUSTER HELP command returns a helpful text describing the different subcommands.
cluster-info
CLUSTER INFO provides INFO style information about Valkey Cluster vital parameters.
The following fields are always present in the reply:
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_nodes_pfail:0
cluster_nodes_fail:0
cluster_voting_nodes_pfail:0
cluster_voting_nodes_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:2
cluster_stats_messages_sent:1483972
cluster_stats_messages_received:1483968
total_cluster_links_buffer_limit_exceeded:0
cluster_state: State isokif the node is able to receive queries.failif there is at least one hash slot which is unbound (no node associated), in error state (node serving it is flagged with FAIL flag), or if the majority of primaries can't be reached by this node.cluster_slots_assigned: Number of slots which are associated to some node (not unbound). This number should be 16384 for the node to work properly, which means that each hash slot should be mapped to a node.cluster_slots_ok: Number of hash slots mapping to a node not inFAILorPFAILstate.cluster_slots_pfail: Number of hash slots mapping to a node inPFAILstate. Note that those hash slots still work correctly, as long as thePFAILstate is not promoted toFAILby the failure detection algorithm.PFAILonly means that we are currently not able to talk with the node, but may be just a transient error.cluster_slots_fail: Number of hash slots mapping to a node inFAILstate. If this number is not zero the node is not able to serve queries unlesscluster-require-full-coverageis set tonoin the configuration.cluster_nodes_pfail: Number of nodes inPFAILstate. A non-zero value indicates one or more nodes have been detected as unreachable but have not yet been confirmed as failed by a quorum of voting nodes.cluster_nodes_fail: Number of nodes inFAILstate. A non-zero value indicates one or more nodes are unreachable and have been marked as failed by a quorum of voting nodes.cluster_voting_nodes_pfail: Number of voting nodes inPFAILstate. A non-zero value indicates one or more primary nodes serving at least one slot are unreachable but not yet confirmed as failed by a quorum of voting nodes.cluster_voting_nodes_fail: Number of voting nodes inFAILstate. A non-zero value indicates one or more primary nodes serving at least one slot have been marked as failed by a quorum of voting nodes.cluster_known_nodes: The total number of known nodes in the cluster, including nodes inHANDSHAKEstate that may not currently be proper members of the cluster.cluster_size: The number of primary nodes serving at least one hash slot in the cluster.cluster_current_epoch: The local Current Epoch. This is used in order to create unique increasing version numbers during fail overs.cluster_my_epoch: The Config Epoch of the node we are talking with. This is the current configuration version assigned to this node.cluster_stats_messages_sent: Number of messages sent via the cluster node-to-node binary bus.cluster_stats_messages_received: Number of messages received via the cluster node-to-node binary bus.total_cluster_links_buffer_limit_exceeded: Accumulated count of cluster links freed due to exceeding thecluster-link-sendbuf-limitconfiguration.
The following message-related fields may be included in the reply if the value is not 0: Each message type includes statistics on the number of messages sent and received. Here are the explanation of these fields: ]
cluster_stats_messages_ping_sentandcluster_stats_messages_ping_received: Cluster bus PING (not to be confused with the client commandPING.cluster_stats_messages_pong_sentandcluster_stats_messages_pong_received: PONG (reply to PING).cluster_stats_messages_meet_sentandcluster_stats_messages_meet_received: Handshake message sent to a new node, either through gossip orCLUSTER MEET.cluster_stats_messages_fail_sentandcluster_stats_messages_fail_received: Mark node xxx as failing.cluster_stats_messages_publish_sentandcluster_stats_messages_publish_received: Pub/Sub Publish propagation, see Pubsub.cluster_stats_messages_auth-req_sentandcluster_stats_messages_auth-req_received: Replica initiated leader election to replace its primary.cluster_stats_messages_auth-ack_sentandcluster_stats_messages_auth-ack_received: Message indicating a vote during leader election.cluster_stats_messages_update_sentandcluster_stats_messages_update_received: Another node slots configuration.cluster_stats_messages_mfstart_sentandcluster_stats_messages_mfstart_received: Pause clients for manual failover.cluster_stats_messages_module_sentandcluster_stats_messages_module_received: Module cluster API message.cluster_stats_messages_publishshard_sentandcluster_stats_messages_publishshard_received: Pub/Sub Publish shard propagation, see Sharded Pubsub.
More information about the Current Epoch and Config Epoch variables are available in the Valkey Cluster specification document.
cluster-keyslot
Returns an integer identifying the hash slot the specified key hashes to. This command is mainly useful for debugging and testing, since it exposes via an API the underlying Valkey implementation of the hashing algorithm. Example use cases for this command:
- Client libraries may use Valkey in order to test their own hashing algorithm, generating random keys and hashing them with both their local implementation and using Valkey
CLUSTER KEYSLOTcommand, then checking if the result is the same. - Humans may use this command in order to check what is the hash slot, and then the associated Valkey Cluster node, responsible for a given key.
Example
> CLUSTER KEYSLOT somekey
(integer) 11058
> CLUSTER KEYSLOT foo{hash_tag}
(integer) 2515
> CLUSTER KEYSLOT bar{hash_tag}
(integer) 2515
Note that the command implements the full hashing algorithm, including support for hash tags, that is the special property of Valkey Cluster key hashing algorithm, of hashing just what is between { and } if such a pattern is found inside the key name, in order to force multiple keys to be handled by the same node.
cluster-links
Each node in a Valkey Cluster maintains a pair of long-lived TCP link with each peer in the cluster: One for sending outbound messages towards the peer and one for receiving inbound messages from the peer.
CLUSTER LINKS outputs information of all such peer links as an array, where each array element is a map that contains attributes and their values for an individual link.
Examples
The following is an example output:
> CLUSTER LINKS
1) 1) "direction"
2) "to"
3) "node"
4) "8149d745fa551e40764fecaf7cab9dbdf6b659ae"
5) "create-time"
6) (integer) 1639442739375
7) "events"
8) "rw"
9) "send-buffer-allocated"
10) (integer) 4512
11) "send-buffer-used"
12) (integer) 0
2) 1) "direction"
2) "from"
3) "node"
4) "8149d745fa551e40764fecaf7cab9dbdf6b659ae"
5) "create-time"
6) (integer) 1639442739411
7) "events"
8) "r"
9) "send-buffer-allocated"
10) (integer) 0
11) "send-buffer-used"
12) (integer) 0
Each map is composed of the following attributes of the corresponding cluster link and their values:
direction: This link is established by the local nodetothe peer, or accepted by the local nodefromthe peer.node: The node id of the peer.create-time: Creation time of the link. (In the case of atolink, this is the time when the TCP link is created by the local node, not the time when it is actually established.)events: Events currently registered for the link.rmeans readable event,wmeans writable event.send-buffer-allocated: Allocated size of the link's send buffer, which is used to buffer outgoing messages toward the peer.send-buffer-used: Size of the portion of the link's send buffer that is currently holding data(messages).
cluster-meet
CLUSTER MEET is used in order to connect different Valkey nodes with cluster
support enabled, into a working cluster.
The basic idea is that nodes by default don't trust each other, and are considered unknown, so that it is unlikely that different cluster nodes will mix into a single one because of system administration errors or network addresses modifications.
So in order for a given node to accept another one into the list of nodes composing a Valkey Cluster, there are only two ways:
- The system administrator sends a
CLUSTER MEETcommand to force a node to meet another one. - An already known node sends a list of nodes in the gossip section that we are not aware of. If the receiving node trusts the sending node as a known node, it will process the gossip section and send a handshake to the nodes that are still not known.
Note that Valkey Cluster needs to form a full mesh (each node is connected with each other node), but in order to create a cluster, there is no need to send all the CLUSTER MEET commands needed to form the full mesh. What matter is to send enough CLUSTER MEET messages so that each node can reach each other node through a chain of known nodes. Thanks to the exchange of gossip information in heartbeat packets, the missing links will be created.
So, if we link node A with node B via CLUSTER MEET, and B with C, A and C will find their ways to handshake and create a link.
Another example: if we imagine a cluster formed of the following four nodes called A, B, C and D, we may send just the following set of commands to A:
CLUSTER MEET B-ip B-portCLUSTER MEET C-ip C-portCLUSTER MEET D-ip D-port
As a side effect of A knowing and being known by all the other nodes, it will send gossip sections in the heartbeat packets that will allow each other node to create a link with each other one, forming a full mesh in a matter of seconds, even if the cluster is large.
Moreover CLUSTER MEET does not need to be reciprocal. If I send the command to A in order to join B, I don't need to also send it to B in order to join A.
If the optional cluster_bus_port argument is not provided, the default of port + 10000 will be used.
Implementation details: MEET and PING packets
When a given node receives a CLUSTER MEET message, the node specified in the
command still does not know the node we sent the command to. So in order for
the node to force the receiver to accept it as a trusted node, it sends a
MEET packet instead of a PING packet. The two packets have exactly the
same format, but the former forces the receiver to acknowledge the node as
trusted.
cluster-migrateslots
CLUSTER MIGRATESLOTS initiates an asynchronous migration of the designated
slot range(s) to the specified target node using
atomic slot migration.
This command allows for many slot ranges in a single migration through repeated
start and end slot pairs within the SLOTSRANGE block. It also supports
multiple migrations in one command, through repeated SLOTSRANGE and NODE
blocks. For example:
CLUSTER MIGRATESLOTS SLOTSRANGE 0 9 20 29 NODE <target A> SLOTSRANGE 10 19 NODE <target B>
Initiates two slot migration jobs, one to <target A> with 20 slots (0-9
inclusive, 20-29 inclusive) and another to <target B> with 10 slots (10-19
inclusive).
OK is returned if all slot migrations are successfully initiated, otherwise an
error message is returned and no slot migrations are initiated.
To check on the progress of the slot migration, use the
CLUSTER GETSLOTMIGRATIONS command.
To cancel the slot migration jobs, use the CLUSTER CANCELSLOTMIGRATIONS command.
Because slot migrations may move keys belonging to any database, the caller
must have ACL access to all databases (the alldbs rule). See
database permissions.
cluster-myid
Returns the node's id.
The CLUSTER MYID command returns the unique, auto-generated identifier that is associated with the connected cluster node.
cluster-myshardid
Returns the node's shard id.
The CLUSTER MYSHARDID command returns the unique, auto-generated identifier that is associated with the shard to which the connected cluster node belongs.
cluster-nodes
Each node in a Valkey Cluster has its view of the current cluster configuration, given by the set of known nodes, the state of the connection we have with such nodes, their flags, properties and assigned slots, and so forth.
CLUSTER NODES provides all this information, that is, the current cluster
configuration of the node we are contacting, in a serialization format which
happens to be exactly the same as the one used by the Valkey Cluster itself in
order to store on disk the cluster state (however the on disk cluster state
has a few additional info appended at the end).
Note that normally clients willing to fetch the map between Cluster
hash slots and node addresses should use CLUSTER SLOTS instead.
CLUSTER NODES, that provides more information, should be used for
administrative tasks, debugging, and configuration inspections.
It is also used by valkey-cli in order to manage a cluster.
Serialization format
The output of the command is just a space-separated CSV string, where each line represents a node in the cluster. The following is an example of output on Valkey 7.2.4.
07c37dfeb235213a872192d90877d0cd55635b91 127.0.0.1:30004@31004,hostname4 slave e7d1eecce10fd6bb5eb35b9f99a514335d9ba9ca 0 1426238317239 4 connected
67ed2db8d677e59ec4a4cefb06858cf2a1a89fa1 127.0.0.1:30002@31002,hostname2 master - 0 1426238316232 2 connected 5461-10922
292f8b365bb7edb5e285caf0b7e6ddc7265d2f4f 127.0.0.1:30003@31003,hostname3 master - 0 1426238318243 3 connected 10923-16383
6ec23923021cf3ffec47632106199cb7f496ce01 127.0.0.1:30005@31005,hostname5 slave 67ed2db8d677e59ec4a4cefb06858cf2a1a89fa1 0 1426238316232 5 connected
824fe116063bc5fcf9f4ffd895bc17aee7731ac3 127.0.0.1:30006@31006,hostname6 slave 292f8b365bb7edb5e285caf0b7e6ddc7265d2f4f 0 1426238317741 6 connected
e7d1eecce10fd6bb5eb35b9f99a514335d9ba9ca 127.0.0.1:30001@31001,hostname1 myself,master - 0 0 1 connected 0-5460
Each line is composed of the following fields:
<id> <ip:port@cport[,hostname]> <flags> <master> <ping-sent> <pong-recv> <config-epoch> <link-state> <slot> <slot> ... <slot>
The meaning of each field is the following:
id: The node ID, a 40-character globally unique string generated when a node is created and never changed again (unlessCLUSTER RESET HARDis used).ip:port@cport: The node address that clients should contact to run queries, along with the used cluster bus port.:0@0can be expected when the address is no longer known for this node ID, hence flagged withnoaddr. Note thatipcan be an IPv6 address, which can contain multiple colons. Here, an IPv6 address is not enclosed in square brackets as it would be in other contexts such as URIs. To properly split theip:port@cportintoipandport@cport, you need to locate the last colon.hostname: A human readable string that can be configured via thecluster-annouce-hostnamesetting. The max length of the string is 256 characters, excluding the null terminator. The name can contain ASCII alphanumeric characters, '-', and '.' only.flags: A list of comma separated flags:myself,master,slave,fail?,fail,handshake,noaddr,nofailover,noflags. Flags are explained below.master: If the node is a replica, and the primary is known, the primary node ID, otherwise the "-" character.ping-sent: Unix time at which the currently active ping was sent, or zero if there are no pending pings, in milliseconds.pong-recv: Unix time the last pong was received, in milliseconds.config-epoch: The configuration epoch (or version) of the current node (or of the current primary if the node is a replica). Each time there is a failover, a new, unique, monotonically increasing configuration epoch is created. If multiple nodes claim to serve the same hash slots, the one with the higher configuration epoch wins.link-state: The state of the link used for the node-to-node cluster bus. Use this link to communicate with the node. Can beconnectedordisconnected.slot: A hash slot number or range. Starting from argument number 9, but there may be up to 16384 entries in total (limit never reached). This is the list of hash slots served by this node. If the entry is just a number, it is parsed as such. If it is a range, it is in the formstart-end, and means that the node is responsible for all the hash slots fromstarttoendincluding the start and end values.
Flags are:
myself: The node you are contacting.master: Node is a primary.slave: Node is a replica.fail?: Node is inPFAILstate. Not reachable for the node you are contacting, but still logically reachable (not inFAILstate).fail: Node is inFAILstate. It was not reachable for multiple nodes that promoted thePFAILstate toFAIL.handshake: Untrusted node, we are handshaking.noaddr: No address known for this node.nofailover: Replica will not try to failover.noflags: No flags at all.
Notes on published config epochs
Replicas broadcast their primary's config epochs (in order to get an UPDATE
message if they are found to be stale), so the real config epoch of the
replica (which is meaningless more or less, since they don't serve hash slots)
can be only obtained checking the node flagged as myself, which is the entry
of the node we are asking to generate CLUSTER NODES output. The other
replicas epochs reflect what they publish in heartbeat packets, which is, the
configuration epoch of the primaries they are currently replicating.
Special slot entries
Normally hash slots associated to a given node are in one of the following formats, as already explained above:
- Single number: 3894
- Range: 3900-4000
However node hash slots can be in a special state, used in order to communicate errors after a node restart (mismatch between the keys in the AOF/RDB file, and the node hash slots configuration), or when there is a resharding operation in progress. This two states are importing and migrating.
The meaning of the two states is explained in the Valkey Specification, however the gist of the two states is the following:
- Importing slots are yet not part of the nodes hash slot, there is a migration in progress. The node will accept queries about these slots only if the
ASKcommand is used. - Migrating slots are assigned to the node, but are being migrated to some other node. The node will accept queries if all the keys in the command exist already, otherwise it will emit what is called an ASK redirection, to force new keys creation directly in the importing node.
Importing and migrating slots are emitted in the CLUSTER NODES output as follows:
- Importing slot:
[slot_number-<-importing_from_node_id] - Migrating slot:
[slot_number->-migrating_to_node_id]
The following are a few examples of importing and migrating slots:
[93-<-292f8b365bb7edb5e285caf0b7e6ddc7265d2f4f][1002-<-67ed2db8d677e59ec4a4cefb06858cf2a1a89fa1][77->-e7d1eecce10fd6bb5eb35b9f99a514335d9ba9ca][16311->-292f8b365bb7edb5e285caf0b7e6ddc7265d2f4f]
Note that the format does not have any space, so CLUSTER NODES output format is plain CSV with space as separator even when these special slots are emitted. However a complete parser for the format should be able to handle them.
Note that:
- Migration and importing slots are only added to the node flagged as
myself. This information is local to a node, for its own slots. - Importing and migrating slots are provided as additional info. If the node has a given hash slot assigned, it will be also a plain number in the list of hash slots, so clients that don't have a clue about hash slots migrations can just skip these special fields.
NOTE: If not for backward compatibility, the Valkey project no longer uses the words "master" and "slave". Unfortunately, in the given commands these words are part of the protocol, so we'll be able to remove such occurrences only when this API is naturally deprecated.
cluster-replicas
The command provides a list of replica nodes replicating from the specified
primary node. The list is provided in the same format used by CLUSTER NODES (please refer to its documentation for the specification of the format).
The command will fail if the specified node is not known or if it is not a primary according to the node table of the node receiving the command.
Note that if a replica is added, moved, or removed from a given primary node,
and we ask CLUSTER REPLICAS to a node that has not yet received the
configuration update, it may show stale information. However eventually
(in a matter of seconds if there are no network partitions) all the nodes
will agree about the set of nodes associated with a given primary.
cluster-replicate
The command reconfigures a node as a replica of the specified primary. If the node receiving the command is an empty primary, as a side effect of the command, the node role is changed from primary to replica.
Once a node is turned into the replica of another primary node, there is no need to inform the other cluster nodes about the change: heartbeat packets exchanged between nodes will propagate the new configuration automatically.
A replica will always accept the command, assuming that:
- The specified node ID exists in its nodes table.
- The specified node ID does not identify the instance we are sending the command to.
- The specified node ID is a primary.
If the node receiving the command is not already a replica, but is a primary, the command will only succeed, and the node will be converted into a replica, only if the following additional conditions are met:
- The node is not serving any hash slots.
- The node is empty, no keys are stored at all in the key space.
If the command succeeds the new replica will immediately try to contact its primary in order to replicate from it.
cluster-reset
Reset a Valkey Cluster node, in a more or less drastic way depending on the
reset type, that can be hard or soft. Note that this command
does not work for primaries if they hold one or more keys, in that case
to completely reset a primary node keys must be removed first, e.g. by using FLUSHALL first,
and then CLUSTER RESET.
Effects on the node:
- All the other nodes in the cluster are forgotten.
- All the assigned / open slots are reset, so the slots-to-nodes mapping is totally cleared.
- If the node is a replica it is turned into an (empty) primary. Its dataset is flushed, so at the end the node will be an empty primary.
- Hard reset only: a new Node ID is generated.
- Hard reset only:
currentEpochandconfigEpochvars are set to 0. - The new configuration is persisted on disk in the node cluster configuration file.
This command is mainly useful to re-provision a Valkey Cluster node in order to be used in the context of a new, different cluster. The command is also extensively used by the Valkey Cluster testing framework in order to reset the state of the cluster every time a new test unit is executed.
If no reset type is specified, the default is soft.
cluster-saveconfig
Forces a node to save the nodes.conf configuration on disk. Before returning,
the command calls fsync(2) in order to make sure the configuration is
flushed on the computer disk.
This command is mainly used in the event a nodes.conf node state file
gets lost / deleted for some reason, and we want to generate it again from
scratch. It can also be useful in case of mundane alterations of a node cluster
configuration via the CLUSTER command in order to ensure the new configuration
is persisted on disk, however all the commands should normally be able to
auto schedule to persist the configuration on disk when it is important
to do so for the correctness of the system in the event of a restart.
cluster-set-config-epoch
This command sets a specific config epoch in a fresh node. It only works when:
- The nodes table of the node is empty.
- The node current config epoch is zero.
These prerequisites are needed since usually, manually altering the configuration epoch of a node is unsafe, we want to be sure that the node with the higher configuration epoch value (that is the last that failed over) wins over other nodes in claiming the hash slots ownership.
However there is an exception to this rule, and it is when a new cluster is created from scratch. Valkey Cluster config epoch collision resolution algorithm can deal with new nodes all configured with the same configuration at startup, but this process is slow and should be the exception, only to make sure that whatever happens, two more nodes eventually always move away from the state of having the same configuration epoch.
So, using CLUSTER SET-CONFIG-EPOCH, when a new cluster is created, we can
assign a different progressive configuration epoch to each node before
joining the cluster together.
cluster-setslot
CLUSTER SETSLOT is responsible for changing the state of a hash slot in the receiving node in different ways. It is part of the legacy mechanism for cluster resharding.
Note: For live resharding, the newer atomic slot migration mechanism using CLUSTER MIGRATESLOTS is recommended as it is faster, more reliable, and has less impact on client applications.
CLUSTER SETSLOT can, depending on the subcommand used:
MIGRATINGsubcommand: Set a hash slot in migrating state.IMPORTINGsubcommand: Set a hash slot in importing state.STABLEsubcommand: Clear any importing / migrating state from hash slot.NODEsubcommand: Bind the hash slot to a different node.
The command with its set of subcommands is useful in order to start and end cluster live resharding operations, which are accomplished by setting a hash slot in migrating state in the source node, and importing state in the destination node.
Each subcommand is documented below. At the end you'll find a description of how live resharding is performed using this command and other related commands.
CLUSTER SETSLOT <slot> MIGRATING <destination-node-id>
This subcommand sets a slot to migrating state. In order to set a slot in this state, the node receiving the command must be the hash slot owner, otherwise an error is returned.
When a slot is set in migrating state, the node changes behavior in the following way:
- If a command is received about an existing key, the command is processed as usually.
- If a command is received about a key that does not exists, an
ASKredirection is emitted by the node, asking the client to retry only that specific query intodestination-node. In this case the client should not update its hash slot to node mapping. - If the command contains multiple keys, in case none exist, the behavior is the same as point 2, if all exist, it is the same as point 1, however if only a partial number of keys exist, the command emits a
TRYAGAINerror in order for the keys interested to finish being migrated to the target node, so that the multi keys command can be executed.
CLUSTER SETSLOT <slot> IMPORTING <source-node-id>
This subcommand is the reverse of MIGRATING, and prepares the destination
node to import keys from the specified source node. The command only works if
the node is not already owner of the specified hash slot.
When a slot is set in importing state, the node changes behavior in the following way:
- Commands about this hash slot are refused and a
MOVEDredirection is generated as usually, but in the case the command follows anASKINGcommand, in this case the command is executed.
In this way when a node in migrating state generates an ASK redirection, the client contacts the target node, sends ASKING, and immediately after sends the command. This way commands about non-existing keys in the old node or keys already migrated to the target node are executed in the target node, so that:
- New keys are always created in the target node. During a hash slot migration we'll have to move only old keys, not new ones.
- Commands about keys already migrated are correctly processed in the context of the node which is the target of the migration, the new hash slot owner, in order to guarantee consistency.
- Without
ASKINGthe behavior is the same as usually. This guarantees that clients with a broken hash slots mapping will not write for error in the target node, creating a new version of a key that has yet to be migrated.
CLUSTER SETSLOT <slot> STABLE
This subcommand just clears migrating / importing state from the slot. It is
mainly used to fix a cluster stuck in a wrong state by valkey-cli --cluster fix.
Normally the two states are cleared automatically at the end of the migration
using the SETSLOT ... NODE ... subcommand as explained in the next section.
CLUSTER SETSLOT <slot> NODE <node-id>
The NODE subcommand is the one with the most complex semantics. It
associates the hash slot with the specified node, however the command works
only in specific situations and has different side effects depending on the
slot state. The following is the set of pre-conditions and side effects of the
command:
- If the current hash slot owner is the node receiving the command, but for effect of the command the slot would be assigned to a different node, the command will return an error if there are still keys for that hash slot in the node receiving the command.
- If the slot is in migrating state, the state gets cleared when the slot is assigned to another node.
- If the slot was in importing state in the node receiving the command, and the command assigns the slot to this node (which happens in the target node at the end of the resharding of a hash slot from one node to another), the command has the following side effects: A) the importing state is cleared. B) If the node config epoch is not already the greatest of the cluster, it generates a new one and assigns the new config epoch to itself. This way its new hash slot ownership will win over any past configuration created by previous failovers or slot migrations.
It is important to note that step 3 is the only time when a Valkey Cluster node will create a new config epoch without agreement from other nodes. This only happens when a manual configuration is operated. However it is impossible that this creates a non-transient setup where two nodes have the same config epoch, since Valkey Cluster uses a config epoch collision resolution algorithm.
Valkey Cluster live resharding explained
The CLUSTER SETSLOT command is an important piece used by Valkey Cluster in order to migrate all the keys contained in one hash slot from one node to another. This is how the migration is orchestrated, with the help of other commands as well. We'll call the node that has the current ownership of the hash slot the source node, and the node where we want to migrate the destination node.
- Set the destination node slot to importing state using
CLUSTER SETSLOT <slot> IMPORTING <source-node-id>. - Set the source node slot to migrating state using
CLUSTER SETSLOT <slot> MIGRATING <destination-node-id>. - Get keys from the source node with
CLUSTER GETKEYSINSLOTcommand and move them into the destination node using theMIGRATEcommand. - Send
CLUSTER SETSLOT <slot> NODE <destination-node-id>to the destination node. - Send
CLUSTER SETSLOT <slot> NODE <destination-node-id>to the source node. - Send
CLUSTER SETSLOT <slot> NODE <destination-node-id>to the other primary nodes (optional).
Notes:
-
The order of step 1 and 2 is important. We want the destination node to be ready to accept
ASKredirections when the source node is configured to redirect. -
The order of step 4 and 5 is important. The destination node is responsible for propagating the change to the rest of the cluster. If the source node is informed before the destination node and the destination node crashes before it is set as new slot owner, the slot is left with no owner, even after a successful failover.
-
Step 6, sending
SETSLOTto the nodes not involved in the resharding, is not technically necessary since the configuration will eventually propagate itself. However, it is a good idea to do so in order to stop nodes from pointing to the wrong node for the hash slot moved as soon as possible, resulting in less redirections to find the right node. -
Starting from Valkey 8.0,
CLUSTER SETSLOTis synchronously replicated to all healthy replicas running Valkey version 8.0+. By default, this synchronous replication must complete within 2 seconds. If the replication fails, the primary does not execute the command, and the client receives aNOREPLICAS Not enough good replicas to writeerror. Operators can retry the command or customize the timeout using theTIMEOUTparameter to further increase the reliability of live reconfiguration:CLUSTER SETSLOT slot [MIGRATING|IMPORTING|NODE] node-id [TIMEOUT timeout]Here,
timeoutis measured in seconds, with 0 meaning to wait indefinitely.
cluster-shards
CLUSTER SHARDS returns details about the shards of the cluster.
A shard is defined as a collection of nodes that serve the same set of slots and that replicate from each other.
A shard may only have a single primary at a given time, but may have multiple or no replicas.
It is possible for a shard to not be serving any slots while still having replicas.
The command is suitable to be used by Valkey Cluster client libraries in order to understand the topology of the cluster. A client should issue this command on startup in order to retrieve the map associating cluster hash slots with actual node information. This map should be used to direct commands to the node that is likely serving the slot associated with a given command. In the event the command is sent to the wrong node, in that it received a '-MOVED' redirect, this command can then be used to update the topology of the cluster.
The command returns an array of shards, with each shard containing three fields, 'slots', 'nodes' and 'id'.
The 'slots' field is a list of slot ranges served by this shard, stored as pair of integers representing the inclusive start and end slots of the ranges. For example, if a node owns the slots 1, 2, 3, 5, 7, 8 and 9, the slots ranges would be stored as [1-3], [5-5], [7-9]. The slots field would therefore be represented by the following list of integers.
1) 1) "slots"
2) 1) (integer) 1
2) (integer) 3
3) (integer) 5
4) (integer) 5
5) (integer) 7
6) (integer) 9
The 'nodes' field contains a list of all nodes within the shard. Each individual node is a map of attributes that describe the node. Some attributes are optional and more attributes may be added in the future. The current list of attributes:
- id: The unique node id for this particular node.
- endpoint: The preferred endpoint to reach the node, see below for more information about the possible values of this field.
- ip: The IP address to send requests to for this node.
- hostname (optional): The announced hostname to send requests to for this node.
- port (optional): The TCP (non-TLS) port of the node. At least one of port or tls-port will be present.
- tls-port (optional): The TLS port of the node. At least one of port or tls-port will be present.
- role: The replication role of this node.
- replication-offset: The replication offset of this node. This information can be used to send commands to the most up to date replicas.
- health: Either
online,fail, orloading. This information should be used to determine which nodes should be sent traffic. Theloadinghealth state should be used to know that a node is not currently eligible to serve traffic, but may be eligible in the future. - availability-zone (optional): The availability zone configured for this node. This field is returned only when the node has a non-empty
availability-zoneconfiguration value, and is omitted otherwise.
The endpoint, along with the port, defines the location that clients should use to send requests for a given slot.
A NULL value for the endpoint indicates the node has an unknown endpoint and the client should connect to the same endpoint it used to send the CLUSTER SHARDS command but with the port returned from the command.
This unknown endpoint configuration is useful when the Valkey nodes are behind a load balancer that Valkey doesn't know the endpoint of.
Which endpoint is set is determined by the cluster-preferred-endpoint-type config.
An empty string "" is another abnormal value of the endpoint field, as well as for the ip field, which is returned if the node doesn't know its own IP address.
This can happen in a cluster that consists of only one node or the node has not yet been joined with the rest of the cluster.
The value ? is displayed if the node is incorrectly configured to use announced hostnames but no hostname is configured using cluster-announce-hostname.
Clients may treat the empty string in the same way as NULL, that is the same endpoint it used to send the current command to, while "?" should be treated as an unknown node, not necessarily the same node as the one serving the current command.
The 'id' field is the unique id of the shard, which is randomly generated and 40 characters long.
Examples
> CLUSTER SHARDS
1) 1) "slots"
2) 1) (integer) 0
2) (integer) 5460
3) "nodes"
4) 1) 1) "id"
2) "e10b7051d6bf2d5febd39a2be297bbaea6084111"
3) "port"
4) (integer) 30001
5) "ip"
6) "127.0.0.1"
7) "endpoint"
8) "127.0.0.1"
9) "role"
10) "master"
11) "replication-offset"
12) (integer) 72156
13) "health"
14) "online"
15) "availability-zone"
16) "zone-a"
2) 1) "id"
2) "1901f5962d865341e81c85f9f596b1e7160c35ce"
3) "port"
4) (integer) 30006
5) "ip"
6) "127.0.0.1"
7) "endpoint"
8) "127.0.0.1"
9) "role"
10) "replica"
11) "replication-offset"
12) (integer) 72156
13) "health"
14) "online"
15) "availability-zone"
16) "zone-a"
5) "id"
6) "cd7688ca959bf54a32569ccf260b26715b82a6e3"
2) 1) "slots"
2) 1) (integer) 10923
2) (integer) 16383
3) "nodes"
4) 1) 1) "id"
2) "fd20502fe1b32fc32c15b69b0a9537551f162f1f"
3) "port"
4) (integer) 30003
5) "ip"
6) "127.0.0.1"
7) "endpoint"
8) "127.0.0.1"
9) "role"
10) "master"
11) "replication-offset"
12) (integer) 72156
13) "health"
14) "online"
15) "availability-zone"
16) "zone-a"
2) 1) "id"
2) "6daa25c08025a0c7e4cc0d1ab255949ce6cee902"
3) "port"
4) (integer) 30005
5) "ip"
6) "127.0.0.1"
7) "endpoint"
8) "127.0.0.1"
9) "role"
10) "replica"
11) "replication-offset"
12) (integer) 72156
13) "health"
14) "online"
15) "availability-zone"
16) "zone-a"
5) "id"
6) "0d77234c440a6b05c2d77d1b9f37ac63585fc747"
3) 1) "slots"
2) 1) (integer) 5461
2) (integer) 10922
3) "nodes"
4) 1) 1) "id"
2) "a4a3f445ead085eb3eb9ee7d8c644ec4481ec9be"
3) "port"
4) (integer) 30002
5) "ip"
6) "127.0.0.1"
7) "endpoint"
8) "127.0.0.1"
9) "role"
10) "master"
11) "replication-offset"
12) (integer) 72156
13) "health"
14) "online"
15) "availability-zone"
16) "zone-a"
2) 1) "id"
2) "da6d5847aa019e9b9d2a8aa24a75f856fd3456cc"
3) "port"
4) (integer) 30004
5) "ip"
6) "127.0.0.1"
7) "endpoint"
8) "127.0.0.1"
9) "role"
10) "replica"
11) "replication-offset"
12) (integer) 72156
13) "health"
14) "online"
15) "availability-zone"
16) "zone-a"
5) "id"
6) "a96f023185ea6d7f5e9a0d6ada6f112741217e6a"
cluster-slaves
A note about the word slave used in this man page and command name: the Valkey project no longer uses the words "master" and "slave". Please use the new command CLUSTER REPLICAS. The command CLUSTER SLAVES will continue to work for backward compatibility.
The command provides a list of replica nodes replicating from the specified
primary node. The list is provided in the same format used by CLUSTER NODES (please refer to its documentation for the specification of the format).
The command will fail if the specified node is not known or if it is not a primary according to the node table of the node receiving the command.
Note that if a replica is added, moved, or removed from a given primary node,
and we ask CLUSTER SLAVES to a node that has not yet received the
configuration update, it may show stale information. However eventually
(in a matter of seconds if there are no network partitions) all the nodes
will agree about the set of nodes associated with a given primary.
cluster-slot-stats
Returns an array of slot usage statistics for slots assigned to the current shard. The command is suitable for Valkey Cluster users aiming to assess general slot usage trends, identify hot / cold slots, migrate slots for a balanced cluster workload, and / or re-write application logic to better utilize slots.
The following statistics are supported:
key-count-- Number of keys residing in a given slot.cpu-usec-- Amount of CPU time (in microseconds) spent on a given slot.network-bytes-in-- Amount of network ingress (in bytes) received for given slot.network-bytes-out-- Amount of network egress (in bytes) sent out for given slot.
Note: By default, only key-count is returned. To enable cpu-usec, network-bytes-in, and network-bytes-out statistics, set cluster-slot-stats-enabled yes in the configuration.
Options
ORDERBY-- Returns an ordered slot statistics based on the specified statistic and sub-arguments to identify hot / cold slots across the cluster. EitherASCorDESCmodifiers can be used. In the event of a tie in the stats, ascending slot number is used as a tie breaker.SLOTSRANGE-- Returns slot statistics based on the slots range provided for pagination. The range is inclusive. The response is ordered in ascending slot number.
Examples
Response in RESP2
For ORDERBY:
> CLUSTER SLOT-STATS ORDERBY KEY-COUNT LIMIT 2 DESC
1) 1) (integer) 12426
2) 1) "key-count"
2) (integer) 45
3) "cpu-usec"
4) (integer) 0
5) "network-bytes-in"
6) (integer) 0
7) "network-bytes-out"
8) (integer) 0
2) 1) (integer) 13902
2) 1) "key-count"
2) (integer) 20
3) "cpu-usec"
4) (integer) 0
5) "network-bytes-in"
6) (integer) 0
7) "network-bytes-out"
8) (integer) 0
For SLOTSRANGE:
> CLUSTER SLOT-STATS SLOTSRANGE 0 1
1) 1) (integer) 0
2) 1) "key-count"
2) (integer) 0
3) "cpu-usec"
4) (integer) 0
5) "network-bytes-in"
6) (integer) 0
7) "network-bytes-out"
8) (integer) 0
2) 1) (integer) 1
2) 1) "key-count"
2) (integer) 0
3) "cpu-usec"
4) (integer) 0
5) "network-bytes-in"
6) (integer) 0
7) "network-bytes-out"
8) (integer) 0
Response in RESP3
For ORDERBY:
> CLUSTER SLOT-STATS ORDERBY KEY-COUNT LIMIT 2 DESC
1) 1) (integer) 12426
2) 1# "key-count" => (integer) 45
2# "cpu-usec" => (integer) 0
3# "network-bytes-in" => (integer) 0
4# "network-bytes-out" => (integer) 0
2) 1) (integer) 13902
2) 1# "key-count" => (integer) 20
2# "cpu-usec" => (integer) 0
3# "network-bytes-in" => (integer) 0
4# "network-bytes-out" => (integer) 0
For SLOTSRANGE:
> CLUSTER SLOT-STATS SLOTSRANGE 0 1
1) 1) (integer) 0
2) 1# "key-count" => (integer) 0
2# "cpu-usec" => (integer) 0
3# "network-bytes-in" => (integer) 0
4# "network-bytes-out" => (integer) 0
2) 1) (integer) 1
2) 1# "key-count" => (integer) 0
2# "cpu-usec" => (integer) 0
3# "network-bytes-in" => (integer) 0
4# "network-bytes-out" => (integer) 0
cluster-slots
CLUSTER SLOTS returns details about which cluster slots map to which Valkey instances.
The command is suitable to be used by Valkey Cluster client libraries implementations in order to retrieve (or update when a redirection is received) the map associating cluster hash slots with actual nodes network information, so that when a command is received, it can be sent to what is likely the right instance for the keys specified in the command.
The networking information for each node is an array containing the following elements:
- Preferred endpoint (Either an IP address, hostname, or NULL)
- Port number
- The node ID
- A map of additional networking metadata
The preferred endpoint, along with the port, defines the location that clients should use to send requests for a given slot.
A NULL value for the endpoint indicates the node has an unknown endpoint and the client should connect to the same endpoint it used to send the CLUSTER SLOTS command but with the port returned from the command.
This unknown endpoint configuration is useful when the Valkey nodes are behind a load balancer that Valkey doesn't know the endpoint of.
Which endpoint is set as preferred is determined by the cluster-preferred-endpoint-type config.
An empty string "" is another abnormal value of the endpoint field, as well as for the ip field, which is returned if the node doesn't know its own IP address.
This can happen in a cluster that consists of only one node or the node has not yet been joined with the rest of the cluster.
The value ? is displayed if the node is incorrectly configured to use announced hostnames but no hostname is configured using cluster-announce-hostname.
Clients may treat the empty string in the same way as NULL, that is the same endpoint it used to send the current command to, while "?" should be treated as an unknown node, not necessarily the same node as the one serving the current command.
Additional networking metadata is provided as a map on the fourth argument for each node. The following networking metadata may be returned:
ip: When the preferred endpoint is not set to IP.hostname: When a node has an announced hostname but the primary endpoint is not set to hostname.availability-zone: When the node has a non-emptyavailability-zoneconfiguration value. This key is omitted when the value is empty.
Nested Result Array
Each nested result is:
- Start slot range
- End slot range
- Primary for slot range represented as nested networking information
- First replica of primary for slot range
- Second replica
- ...continues until all replicas for this primary are returned.
Each result includes all active replicas of the primary instance for the listed slot range. Failed replicas are not returned.
The command response is deterministic across all nodes in a cluster, which means that if two nodes return the same response they have the same view of the cluster. Primaries are ordered by the slots they serve and then replicas are ordered lexicographically by the node-id they were assigned by the cluster. The third nested reply is guaranteed to be the networking information of the primary instance for the slot range. All networking information after the third nested reply are replicas of the primary.
If a cluster instance has non-contiguous slots (e.g. 1-400,900,1800-6000) then primary and replica networking information results will be duplicated for each top-level slot range reply.
> CLUSTER SLOTS
1) 1) (integer) 0
2) (integer) 5460
3) 1) "127.0.0.1"
2) (integer) 30001
3) "09dbe9720cda62f7865eabc5fd8857c5d2678366"
4) 1) hostname
2) "host-1.valkey.example.com"
3) availability-zone
4) "zone-a"
4) 1) "127.0.0.1"
2) (integer) 30004
3) "821d8ca00d7ccf931ed3ffc7e3db0599d2271abf"
4) 1) hostname
2) "host-2.valkey.example.com"
3) availability-zone
4) "zone-a"
2) 1) (integer) 5461
2) (integer) 10922
3) 1) "127.0.0.1"
2) (integer) 30002
3) "c9d93d9f2c0c524ff34cc11838c2003d8c29e013"
4) 1) hostname
2) "host-3.valkey.example.com"
3) availability-zone
4) "zone-a"
4) 1) "127.0.0.1"
2) (integer) 30005
3) "faadb3eb99009de4ab72ad6b6ed87634c7ee410f"
4) 1) hostname
2) "host-4.valkey.example.com"
3) availability-zone
4) "zone-a"
3) 1) (integer) 10923
2) (integer) 16383
3) 1) "127.0.0.1"
2) (integer) 30003
3) "044ec91f325b7595e76dbcb18cc688b6a5b434a1"
4) 1) hostname
2) "host-5.valkey.example.com"
3) availability-zone
4) "zone-a"
4) 1) "127.0.0.1"
2) (integer) 30006
3) "58e6e48d41228013e5d9c1c37c5060693925e97e"
4) 1) hostname
2) "host-6.valkey.example.com"
3) availability-zone
4) "zone-a"
Warning: In future versions there could be more elements describing the node better. In general a client implementation should just rely on the fact that certain parameters are at fixed positions as specified, but more parameters may follow and should be ignored. Similarly a client library should try if possible to cope with the fact that older versions may just have the primary endpoint and port parameter.
cluster-syncslots
Internal command to allow navigation of the atomic slot migration state machine.
For more information about atomic slot migration in Valkey please check the atomic slot migration page.
cluster
This is a container command for Valkey Cluster commands.
To see the list of available commands you can call CLUSTER HELP.
clusterscan
CLUSTERSCAN iterates over keys across a Valkey Cluster.
It walks through every hash slot in the cluster, one slot at a time.
Similar to SCAN, it is cursor-based. You start by passing 0 as the cursor and keep calling until the returned cursor is 0 again.
The cursor format is fingerprint-{hashtag}-localcursor.
The fingerprint is an opaque string that identifies how the node will return cursor, which currently includes information about the engine version and the hash-seed config value.
Mismatches in the fingerprint will result in the cursor restarting the current slot.
The hash tag represents the current slot (e.g., {06S}), so cluster-aware clients will route each call to the right node automatically.
The local cursor helps resume the scan from where it left off.
127.0.0.1:6379> CLUSTERSCAN 0
1) "0-{06S}-0"
2) (empty list or set)
127.0.0.1:6379> CLUSTERSCAN 0-{06S}-0
1) "0B3a21-{06S}-96"
2) 1) "key:1"
2) "key:2"
3) "key:3"
127.0.0.1:6379> CLUSTERSCAN 0B3a21-{06S}-96
1) "0-{Qi}-0"
2) 1) "key:4"
In this example, the first call returns an initial cursor for slot 0 with no keys.
The next call scans through slot 0 and returns keys.
Once slot 0 is done, the cursor moves on to slot 1 (you can see the hash tag change from {06S} to {Qi}).
Since the cursor carries the hash tag, the client naturally routes the next call to whichever node owns slot 1.
This continues until all slots have been visited and the cursor comes back as 0.
The SLOT option
By default CLUSTERSCAN goes through all slots from 0 to 16383.
If you only care about keys in a particular slot, pass the SLOT option:
127.0.0.1:6379> CLUSTERSCAN 0 SLOT 0
1) "0-{06S}-0"
2) (empty list or set)
127.0.0.1:6379> CLUSTERSCAN 0-{06S}-0 SLOT 0
1) "0B3a21-{06S}-64"
2) 1) "key_in_slot0:1"
With SLOT, the scan stays within that slot and returns 0 when it's done rather than advancing to the next one.
This also makes it possible to run scans in parallel by issuing concurrent CLUSTERSCAN calls for different slots.
If the cursor already points to a different slot than the SLOT argument, you'll get an error.
You can only specify SLOT once per call.
MATCH, COUNT and TYPE options
These work the same way as in SCAN.
MATCH filters by a glob-style pattern, COUNT hints how many keys to return per call (default 10), and TYPE filters by data type.
Handling topology changes
CLUSTERSCAN is designed to keep working when the cluster topology changes mid-scan:
- Slot migration: If a slot moves to another node while you're scanning it, the old node sends back a
-MOVEDredirect. Just follow the redirect and continue with the same cursor on the new owner. - Failover and node restart: If the node's memory layout has changed since the cursor was issued, the scan restarts from the beginning of that slot instead of returning an error.
To avoid this, set
hash-seedto the same value on all nodes. - Unassigned slots: If the cursor points to a slot that no node is serving, you'll get a
-CLUSTERDOWNerror.
Guarantees
CLUSTERSCAN gives the same guarantees as SCAN:
- Every key that exists throughout the entire iteration of a slot will be returned at least once.
- Duplicates are possible, especially around topology changes, so your application should be prepared to handle them.
Return value
An array with two elements: the cursor to pass in the next call, and an array of key names.
command-count
Returns the total number of commands in this Valkey server.
Examples
127.0.0.1:6379> COMMAND COUNT
(integer) 241
command-docs
Return documentary information about commands.
By default, the reply includes all of the server's commands. You can use the optional command-name argument to specify the names of one or more commands.
The reply includes a map for each returned command. The following keys may be included in the mapped reply:
- summary: short command description.
- since: the Valkey version that added the command (or for module commands, the module version).
- group: the functional group to which the command belongs.
Possible values are:
- bitmap
- cluster
- connection
- generic
- geo
- hash
- hyperloglog
- list
- module
- pubsub
- scripting
- sentinel
- server
- set
- sorted-set
- stream
- string
- transactions
- complexity: a short explanation about the command's time complexity.
- doc_flags: an array of documentation flags.
Possible values are:
- deprecated: the command is deprecated.
- syscmd: a system command that isn't meant to be called by users.
- deprecated_since: the Valkey version that deprecated the command (or for module commands, the module version)..
- replaced_by: the alternative for a deprecated command.
- history: an array of historical notes describing changes to the command's output or arguments. It should not contain information about behavioral changes.
Each entry is an array itself, made up of two elements:
- The Valkey version that the entry applies to.
- The description of the change.
- arguments: an array of maps that describe the command's arguments. Please refer to the Valkey command arguments page for more information.
Examples
127.0.0.1:6379> COMMAND DOCS SET
1) "set"
2) 1) "summary"
2) "Sets the string value of a key, ignoring its type. The key is created if it doesn't exist."
3) "since"
4) "1.0.0"
5) "group"
6) "string"
7) "complexity"
8) "O(1)"
9) "history"
10) 1) 1) "2.6.12"
2) "Added the `EX`, `PX`, `NX` and `XX` options."
2) 1) "6.0.0"
2) "Added the `KEEPTTL` option."
3) 1) "6.2.0"
2) "Added the `GET`, `EXAT` and `PXAT` option."
4) 1) "7.0.0"
2) "Allowed the `NX` and `GET` options to be used together."
11) "arguments"
12) 1) 1) "name"
2) "key"
3) "type"
4) "key"
5) "display_text"
6) "key"
7) "key_spec_index"
8) (integer) 0
2) 1) "name"
2) "value"
3) "type"
4) "string"
5) "display_text"
6) "value"
3) 1) "name"
2) "condition"
3) "type"
4) "oneof"
5) "since"
6) "2.6.12"
7) "flags"
8) 1) optional
9) "arguments"
10) 1) 1) "name"
2) "nx"
3) "type"
4) "pure-token"
5) "display_text"
6) "nx"
7) "token"
8) "NX"
2) 1) "name"
2) "xx"
3) "type"
4) "pure-token"
5) "display_text"
6) "xx"
7) "token"
8) "XX"
4) 1) "name"
2) "get"
3) "type"
4) "pure-token"
5) "display_text"
6) "get"
7) "token"
8) "GET"
9) "since"
10) "6.2.0"
11) "flags"
12) 1) optional
5) 1) "name"
2) "expiration"
3) "type"
4) "oneof"
5) "flags"
6) 1) optional
7) "arguments"
8) 1) 1) "name"
2) "seconds"
3) "type"
4) "integer"
5) "display_text"
6) "seconds"
7) "token"
8) "EX"
9) "since"
10) "2.6.12"
2) 1) "name"
2) "milliseconds"
3) "type"
4) "integer"
5) "display_text"
6) "milliseconds"
7) "token"
8) "PX"
9) "since"
10) "2.6.12"
3) 1) "name"
2) "unix-time-seconds"
3) "type"
4) "unix-time"
5) "display_text"
6) "unix-time-seconds"
7) "token"
8) "EXAT"
9) "since"
10) "6.2.0"
4) 1) "name"
2) "unix-time-milliseconds"
3) "type"
4) "unix-time"
5) "display_text"
6) "unix-time-milliseconds"
7) "token"
8) "PXAT"
9) "since"
10) "6.2.0"
5) 1) "name"
2) "keepttl"
3) "type"
4) "pure-token"
5) "display_text"
6) "keepttl"
7) "token"
8) "KEEPTTL"
9) "since"
10) "6.0.0"
command-getkeys
Returns @array-reply of keys from a full Valkey command.
COMMAND GETKEYS is a helper command to let you find the keys
from a full Valkey command.
COMMAND provides information on how to find the key names of each command (see firstkey, key specifications, and movablekeys),
but in some cases it's not possible to find keys of certain commands and then the entire command must be parsed to discover some / all key names.
You can use COMMAND GETKEYS or COMMAND GETKEYSANDFLAGS to discover key names directly from how Valkey parses the commands.
Examples
127.0.0.1:6379> COMMAND GETKEYS MSET a b c d e f
1) "a"
2) "c"
3) "e"
127.0.0.1:6379> COMMAND GETKEYS EVAL "not consulted" 3 key1 key2 key3 arg1 arg2 arg3 argN
1) "key1"
2) "key2"
3) "key3"
127.0.0.1:6379> COMMAND GETKEYS SORT mylist ALPHA STORE outlist
1) "mylist"
2) "outlist"
command-getkeysandflags
Returns @array-reply of keys from a full Valkey command and their usage flags.
COMMAND GETKEYSANDFLAGS is a helper command to let you find the keys from a full Valkey command together with flags indicating what each key is used for.
COMMAND provides information on how to find the key names of each command (see firstkey, key specifications, and movablekeys),
but in some cases it's not possible to find keys of certain commands and then the entire command must be parsed to discover some / all key names.
You can use COMMAND GETKEYS or COMMAND GETKEYSANDFLAGS to discover key names directly from how Valkey parses the commands.
Refer to key specifications for information about the meaning of the key flags.
Examples
127.0.0.1:6379> COMMAND GETKEYS MSET a b c d e f
1) "a"
2) "c"
3) "e"
127.0.0.1:6379> COMMAND GETKEYS EVAL "not consulted" 3 key1 key2 key3 arg1 arg2 arg3 argN
1) "key1"
2) "key2"
3) "key3"
127.0.0.1:6379> COMMAND GETKEYSANDFLAGS LMOVE mylist1 mylist2 left left
1) 1) "mylist1"
2) 1) RW
2) access
3) delete
2) 1) "mylist2"
2) 1) RW
2) insert
command-help
The COMMAND HELP command returns a helpful text describing the different subcommands.
command-info
Returns @array-reply of details about multiple Valkey commands.
Same result format as COMMAND except you can specify which commands
get returned.
If you request details about non-existing commands, their return position will be nil.
Examples
127.0.0.1:6379> COMMAND INFO get set eval
1) 1) "get"
2) (integer) 2
3) 1) readonly
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @string
3) @fast
8) (empty array)
9) 1) 1) "flags"
2) 1) RO
2) access
3) "begin_search"
4) 1) "type"
2) "index"
3) "spec"
4) 1) "index"
2) (integer) 1
5) "find_keys"
6) 1) "type"
2) "range"
3) "spec"
4) 1) "lastkey"
2) (integer) 0
3) "keystep"
4) (integer) 1
5) "limit"
6) (integer) 0
10) (empty array)
2) 1) "set"
2) (integer) -3
3) 1) write
2) denyoom
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @string
3) @slow
8) (empty array)
9) 1) 1) "notes"
2) "RW and ACCESS due to the optional `GET` argument"
3) "flags"
4) 1) RW
2) access
3) update
4) variable_flags
5) "begin_search"
6) 1) "type"
2) "index"
3) "spec"
4) 1) "index"
2) (integer) 1
7) "find_keys"
8) 1) "type"
2) "range"
3) "spec"
4) 1) "lastkey"
2) (integer) 0
3) "keystep"
4) (integer) 1
5) "limit"
6) (integer) 0
10) (empty array)
3) 1) "eval"
2) (integer) -3
3) 1) noscript
2) stale
3) skip_monitor
4) no_mandatory_keys
5) movablekeys
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @slow
2) @scripting
8) (empty array)
9) 1) 1) "notes"
2) "We cannot tell how the keys will be used so we assume the worst, RW and UPDATE"
3) "flags"
4) 1) RW
2) access
3) update
5) "begin_search"
6) 1) "type"
2) "index"
3) "spec"
4) 1) "index"
2) (integer) 2
7) "find_keys"
8) 1) "type"
2) "keynum"
3) "spec"
4) 1) "keynumidx"
2) (integer) 0
3) "firstkey"
4) (integer) 1
5) "keystep"
6) (integer) 1
10) (empty array)
127.0.0.1:6379> COMMAND INFO foo evalsha config bar
1) (nil)
2) 1) "evalsha"
2) (integer) -3
3) 1) noscript
2) stale
3) skip_monitor
4) no_mandatory_keys
5) movablekeys
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @slow
2) @scripting
8) (empty array)
9) 1) 1) "flags"
2) 1) RW
2) access
3) update
3) "begin_search"
4) 1) "type"
2) "index"
3) "spec"
4) 1) "index"
2) (integer) 2
5) "find_keys"
6) 1) "type"
2) "keynum"
3) "spec"
4) 1) "keynumidx"
2) (integer) 0
3) "firstkey"
4) (integer) 1
5) "keystep"
6) (integer) 1
10) (empty array)
3) 1) "config"
2) (integer) -2
3) (empty array)
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @slow
8) (empty array)
9) (empty array)
10) 1) 1) "config|rewrite"
2) (integer) 2
3) 1) admin
2) noscript
3) loading
4) stale
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @admin
2) @slow
3) @dangerous
8) 1) "request_policy:all_nodes"
2) "response_policy:all_succeeded"
9) (empty array)
10) (empty array)
2) 1) "config|resetstat"
2) (integer) 2
3) 1) admin
2) noscript
3) loading
4) stale
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @admin
2) @slow
3) @dangerous
8) 1) "request_policy:all_nodes"
2) "response_policy:all_succeeded"
9) (empty array)
10) (empty array)
3) 1) "config|help"
2) (integer) 2
3) 1) loading
2) stale
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @slow
8) (empty array)
9) (empty array)
10) (empty array)
4) 1) "config|get"
2) (integer) -3
3) 1) admin
2) noscript
3) loading
4) stale
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @admin
2) @slow
3) @dangerous
8) (empty array)
9) (empty array)
10) (empty array)
5) 1) "config|set"
2) (integer) -4
3) 1) admin
2) noscript
3) loading
4) stale
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @admin
2) @slow
3) @dangerous
8) 1) "request_policy:all_nodes"
2) "response_policy:all_succeeded"
9) (empty array)
10) (empty array)
4) (nil)
command-list
Return an array of the server's command names.
You can use the optional FILTERBY modifier to apply one of the following filters:
- MODULE module-name: get the commands that belong to the module specified by module-name.
- ACLCAT category: get the commands in the ACL category specified by category.
- PATTERN pattern: get the commands that match the given glob-like pattern.
command
Return an array with details about every Valkey command.
The COMMAND command is introspective.
Its reply describes all commands that the server can process.
Valkey clients can call it to obtain the server's runtime capabilities during the handshake.
COMMAND also has several subcommands.
Please refer to its subcommands for further details.
Cluster note:
this command is especially beneficial for cluster-aware clients.
Such clients must identify the names of keys in commands to route requests to the correct shard.
Although most commands accept a single key as their first argument, there are many exceptions to this rule.
You can call COMMAND and then keep the mapping between commands and their respective key specification rules cached in the client.
The reply it returns is an array with an element per command. Each element that describes a Valkey command is represented as an array by itself.
The command's array consists of a fixed number of elements. The exact number of elements in the array depends on the server's version.
- Name
- Arity
- Flags
- First key
- Last key
- Step
- ACL categories
- Tips
- Key specifications
- Subcommands
Name
This is the command's name in lowercase.
Note: Valkey command names are case-insensitive.
Arity
Arity is the number of arguments a command expects. It follows a simple pattern:
- A positive integer means a fixed number of arguments.
- A negative integer means a minimal number of arguments.
Command arity always includes the command's name itself (and the subcommand when applicable).
Examples:
- The arity of
GETis 2 since the command only accepts one argument and always has the formatGET _key_. - The arity of
MGETis -2 since the command accepts at least one argument, but possibly multiple ones:MGET _key1_ [key2] [key3] ....
Flags
Command flags are an array. It can contain the following simple strings (status reply):
- admin: the command is an administrative command.
- asking: the command is allowed even during hash slot migration. This flag is relevant in Valkey Cluster deployments.
- blocking: the command may block the requesting client.
- denyoom: the command is rejected if the server's memory usage is too high (see the maxmemory configuration directive).
- fast: the command operates in constant or log(N) time.
This flag is used for monitoring latency with the
LATENCYcommand. - loading: the command is allowed while the database is loading.
- movablekeys: the first key, last key, and step values don't determine all key positions.
Clients need to use
COMMAND GETKEYSor key specifications in this case. See below for more details. - no_auth: executing the command doesn't require authentication.
- no_async_loading: the command is denied during asynchronous loading (that is when a replica uses disk-less
SWAPDBSYNC, and allows access to the old dataset). - no_mandatory_keys: the command may accept key name arguments, but these aren't mandatory.
- no_multi: the command isn't allowed inside the context of a transaction.
- noscript: the command can't be called from scripts or functions.
- pubsub: the command is related to Valkey Pub/Sub.
- random: the command returns random results, which is a concern with verbatim script replication. This flag is a command tip.
- readonly: the command doesn't modify data.
- sort_for_script: the command's output is sorted when called from a script.
- skip_monitor: the command is not shown in the output of the
MONITORcommand. - skip_slowlog: the command is not shown in the output of the
SLOWLOGcommand. This flag is a command tip. - stale: the command is allowed while a replica has stale data.
- write: the command may modify data.
Movablekeys
Consider SORT:
1) 1) "sort"
2) (integer) -2
3) 1) write
2) denyoom
3) movablekeys
4) (integer) 1
5) (integer) 1
6) (integer) 1
...
Some Valkey commands have no predetermined key locations or are not easy to find. For those commands, the movablekeys flag indicates that the first key, last key, and step values are insufficient to find all the keys.
Here are several examples of commands that have the movablekeys flag:
SORT: the optional STORE, BY, and GET modifiers are followed by names of keys.ZUNION: the numkeys argument specifies the number key name arguments.MIGRATE: the keys appear KEYS keyword and only when the second argument is the empty string.
Valkey Cluster clients need to use other measures, as follows, to locate the keys for such commands.
You can use the COMMAND GETKEYS command and have your Valkey server report all keys of a given command's invocation.
Clients can use the key specifications to identify the positions of key names.
The only commands that require using COMMAND GETKEYS are SORT and MIGRATE for clients that parse keys' specifications.
For more information, please refer to the key specifications page.
First key
The position of the command's first key name argument. For most commands, the first key's position is 1. Position 0 is always the command name itself.
Last key
The position of the command's last key name argument. Valkey commands usually accept one, two or multiple number of keys.
Commands that accept a single key have both first key and last key set to 1.
Commands that accept two key name arguments, e.g. BRPOPLPUSH, SMOVE and RENAME, have this value set to the position of their second key.
Multi-key commands that accept an arbitrary number of keys, such as MSET, use the value -1.
Step
The step, or increment, between the first key and the position of the next key.
Consider the following two examples:
1) 1) "mset"
2) (integer) -3
3) 1) write
2) denyoom
4) (integer) 1
5) (integer) -1
6) (integer) 2
...
1) 1) "mget"
2) (integer) -2
3) 1) readonly
2) fast
4) (integer) 1
5) (integer) -1
6) (integer) 1
...
The step count allows us to find keys' positions.
For example MSET: Its syntax is MSET _key1_ _val1_ [key2] [val2] [key3] [val3]..., so the keys are at every other position (step value of 2).
Unlike MGET, which uses a step value of 1.
ACL categories
This is an array of simple strings that are the ACL categories to which the command belongs. Please refer to the Access Control List page for more information.
Command tips
Helpful information about the command. To be used by clients/proxies.
Please check the Command tips page for more information.
Key specifications
This is an array consisting of the command's key specifications. Each element in the array is a map describing a method for locating keys in the command's arguments.
For more information please check the key specifications page.
Subcommands
This is an array containing all of the command's subcommands, if any.
Some Valkey commands have subcommands (e.g., the REWRITE subcommand of CONFIG).
Each element in the array represents one subcommand and follows the same specifications as those of COMMAND's reply.
Examples
The following is COMMAND's output for the GET command:
1) 1) "get"
2) (integer) 2
3) 1) readonly
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @string
3) @fast
8) (empty array)
9) 1) 1) "flags"
2) 1) read
3) "begin_search"
4) 1) "type"
2) "index"
3) "spec"
4) 1) "index"
2) (integer) 1
5) "find_keys"
6) 1) "type"
2) "range"
3) "spec"
4) 1) "lastkey"
2) (integer) 0
3) "keystep"
4) (integer) 1
5) "limit"
6) (integer) 0
10) (empty array)
...
commandlog-get
The COMMANDLOG GET command returns entries from the command log of specified type in chronological order.
The Command Log system is used to record commands that consume significant resources during server operation, including CPU, memory, and network bandwidth. These commands and the data they access may lead to abnormal instance operations, the command log can help users quickly and intuitively locate issues.
Currently, three types of command logs are supported:
-
SLOW: Logs commands that exceed a specified execution time. This excludes time spent on I/O operations like client communication and focuses solely on the command's processing time, where the main thread is blocked.
-
LARGE-REQUEST: Logs commands with requests exceeding a defined size. This helps identify potentially problematic commands that send excessive data to the server.
-
LARGE-REPLY: Logs commands that generate replies exceeding a defined size. This helps identify commands that return unusually large amounts of data, which may impact network performance or client processing.
Each log type has two key parameters:
- A threshold value that determines when a command is logged. This threshold is specific to the type of log (e.g., execution time, request size, or reply size). A negative value disables logging. A value of 0 logs all commands.
- A maximum length that specifies the number of entries to retain in the log. Increasing the length allows more entries to be stored but consumes additional memory. To clear all entries for a specific log type and reclaim memory, use the
COMMANDLOG RESETsubcommand followed by the log type.
See the details of configurations in valkey.conf.
Each entry from the specific type of command log is comprised of the following six values:
- A unique progressive identifier for every entry.
- The unix timestamp at which the logged command was processed.
- Each type of command log has its own meaning, currently there are three types:
- time in microseconds for type of slow
- size in bytes for type of large-request
- size in bytes for type of large-reply
- The array composing the arguments of the command.
- Client peer information (e.g. Client IP address and port for TCP connected clients or unix path for unix sockets).
- Client name if set via the
CLIENT SETNAMEcommand.
The entry's unique ID can be used in order to avoid processing command log entries multiple times (for instance you may have a script sending you an email alert for every new command log entry).
The ID is never reset in the course of the Valkey server execution, even after COMMANDLOG RESET was executed. In order to reset the ID a server restart is needed.
commandlog-help
The COMMANDLOG HELP command returns a helpful text describing the different subcommands.
commandlog-len
The COMMANDLOG LEN command returns the current number of entries in the specified type of command log.
A new entry is added to the specified command log whenever a command exceeds the corresponding threshold. There are currently three different types of command log, each with an independent threshold, including commandlog-execution-slower-than, commandlog-request-larger-than, and commandlog-reply-larger-than.
The maximum number of entries in the different command log is governed by the commandlog-slow-execution-max-len, commandlog-large-request-max-len and commandlog-large-reply-max-len configurations.
Once the command log reaches its maximal size, the oldest entry is removed whenever a new entry is created.
The command log can be cleared with the COMMANDLOG RESET command.
commandlog-reset
This command resets the specified type of command log, clearing all entries in it.
Once deleted the information is lost forever.
commandlog
This is a container command for command log management commands.
To see the list of available commands you can call COMMANDLOG HELP.
config-get
The CONFIG GET command is used to read the configuration parameters of a
running Valkey server.
The symmetric command used to alter the configuration at run time is CONFIG SET.
CONFIG GET takes multiple arguments, which are glob-style patterns.
Any configuration parameter matching any of the patterns are reported as a list
of key-value pairs.
In Valkey 9.0 and later, the list is sorted alphabetically by keys.
Example:
127.0.0.1:6379> config get *max-*-entries* maxmemory
1) "hash-max-listpack-entries"
2) "512"
3) "hash-max-ziplist-entries"
4) "512"
5) "maxmemory"
6) "0"
7) "set-max-intset-entries"
8) "512"
9) "set-max-listpack-entries"
10) "128"
11) "zset-max-listpack-entries"
12) "128"
13) "zset-max-ziplist-entries"
14) "128"
You can obtain a list of all the supported configuration parameters by typing
CONFIG GET * in an open valkey-cli prompt.
All the supported parameters have the same meaning of the equivalent configuration parameter used in the valkey.conf file:
Note that you should look at the valkey.conf file relevant to the version you're working with as configuration options might change between versions. The link above is to the latest development version.
config-help
The CONFIG HELP command returns a helpful text describing the different subcommands.
config-resetstat
Resets the statistics reported by Valkey using the INFO and LATENCY HISTOGRAM commands.
The following is a non-exhaustive list of values that are reset:
- Keyspace hits and misses
- Number of expired keys
- Command and error statistics
- Connections received, rejected and evicted
- Persistence statistics
- Active defragmentation statistics
config-rewrite
The CONFIG REWRITE command rewrites the valkey.conf file the server was started with, applying the minimal changes needed to make it reflect the configuration currently used by the server, which may be different compared to the original one because of the use of the CONFIG SET command.
The rewrite is performed in a very conservative way:
- Comments and the overall structure of the original valkey.conf are preserved as much as possible.
- If an option already exists in the old valkey.conf file, it will be rewritten at the same position (line number).
- If an option was not already present, but it is set to its default value, it is not added by the rewrite process.
- If an option was not already present, but it is set to a non-default value, it is appended at the end of the file.
- Non used lines are blanked. For instance if you used to have multiple
savedirectives, but the current configuration has fewer or none as you disabled RDB persistence, all the lines will be blanked.
CONFIG REWRITE is also able to rewrite the configuration file from scratch if the original one no longer exists for some reason. However if the server was started without a configuration file at all, the CONFIG REWRITE will just return an error.
Atomic rewrite process
In order to make sure the valkey.conf file is always consistent, that is, on errors or crashes you always end with the old file, or the new one, the rewrite is performed with a single write(2) call that has enough content to be at least as big as the old file. Sometimes additional padding in the form of comments is added in order to make sure the resulting file is big enough, and later the file gets truncated to remove the padding at the end.
config-set
The CONFIG SET command is used in order to reconfigure the server at run time
without the need to restart Valkey.
You can change both trivial parameters or switch from one to another persistence
option using this command.
The list of configuration parameters supported by CONFIG SET can be obtained
issuing a CONFIG GET * command, that is the symmetrical command used to obtain
information about the configuration of a running Valkey instance.
All the configuration parameters set using CONFIG SET are immediately loaded
by Valkey and will take effect starting with the next command executed.
All the supported parameters have the same meaning of the equivalent configuration parameter used in the valkey.conf file.
Note that you should look at the valkey.conf file relevant to the version you're working with as configuration options might change between versions. The link above is to the latest development version.
It is possible to switch persistence from RDB snapshotting to append-only file
(and the other way around) using the CONFIG SET command.
For more information about how to do that please check the persistence
page.
In general what you should know is that setting the appendonly parameter to
yes will start a background process to save the initial append-only file
(obtained from the in memory data set), and will append all the subsequent
commands on the append-only file, thus obtaining exactly the same effect of a
Valkey server that started with AOF turned on since the start.
You can have both the AOF enabled with RDB snapshotting if you want, the two options are not mutually exclusive.
config
This is a container command for runtime configuration commands.
To see the list of available commands you can call CONFIG HELP.
copy
This command copies the value stored at the source key to the destination
key.
By default, the destination key is created in the logical database used by the
connection. The DB option allows specifying an alternative logical database
index for the destination key. The REPLACE option removes the destination
key before copying the value to it.
The command returns zero when the source key does not exist or when the
destination key already exists and the REPLACE option is not specified.
When the DB option is used, the caller must have ACL permission to access
the specified destination database. See
database permissions.
Examples
SET dolly "sheep"
COPY dolly clone
GET clone
dbsize
Return the number of keys in the currently-selected database.
debug
The DEBUG command is an internal command.
It is meant to be used for developing and testing Valkey.
decr
Decrements the number stored at key by one.
If the key does not exist, it is set to 0 before performing the operation.
An error is returned if the key contains a value of the wrong type or contains a
string that can not be represented as integer.
This operation is limited to 64 bit signed integers.
See INCR for extra information on increment/decrement operations.
Examples
127.0.0.1:6379> SET mykey "10"
OK
127.0.0.1:6379> DECR mykey
(integer) 9
127.0.0.1:6379> SET mykey "234293482390480948029348230948"
OK
127.0.0.1:6379> DECR mykey
(error) ERR value is not an integer or out of range
decrby
Decrements the number stored at key by decrement.
If the key does not exist, it is set to 0 before performing the operation.
An error is returned if the key contains a value of the wrong type or contains a
string that can not be represented as integer.
This operation is limited to 64 bit signed integers.
See INCR for extra information on increment/decrement operations.
Examples
127.0.0.1:6379> SET mykey "10"
OK
127.0.0.1:6379> DECRBY mykey 3
(integer) 7
del
Removes the specified keys. A key is ignored if it does not exist.
Examples
127.0.0.1:6379> SET key1 "Hello"
OK
127.0.0.1:6379> SET key2 "World"
OK
127.0.0.1:6379> DEL key1 key2 key3
(integer) 2
delex
Delete key based on condition.
Options
IFEQcomparison-value -- Delete the key only if the comparison value matches key's existing value. Error is returned if provided key or value is not string.IFNEcomparison-value -- Delete the key only if the comparison value does not matches key's existing value. Error is returned if provided key or value is not string.
Example
Delete the key if given value is equal to existing value.
127.0.0.1:6379> SET x 1
OK
127.0.0.1:6379> DELEX x IFEQ 1
(integer) 1
Delete the key if given value is not equal to existing value.
127.0.0.1:6379> SET x 1
OK
127.0.0.1:6379> DELEX x IFNE 2
(integer) 1
delifeq
Deletes the key if its value matches the given string.
This command is typically used to safely release locks in distributed systems, ensuring that only the owner of the lock (as identified by the value) can delete it.
If the key exists and the stored value is a string that exactly matches the provided value, the key is removed and 1 is returned. Otherwise, the key is left unchanged and 0 is returned.
Examples
Basic usage:
127.0.0.1:6379> SET mykey abc123
OK
127.0.0.1:6379> DELIFEQ mykey abc123
(integer) 1
127.0.0.1:6379> DELIFEQ mykey abc123
(integer) 0
Wrong value:
127.0.0.1:6379> SET mykey xyz789
OK
127.0.0.1:6379> DELIFEQ mykey abc123
(integer) 0
Wrong type:
127.0.0.1:6379> SADD mykey somevalue
(integer) 1
127.0.0.1:6379> DELIFEQ mykey somevalue
(error) WRONGTYPE Operation against a key holding the wrong kind of value
Use case: Safe lock release
DELIFEQ enables an atomic check-and-delete operation to safely release a lock only if the process still holds it. This avoids race conditions where a lock might expire and be claimed by another process before the original owner tries to delete it.
This pattern is commonly used as part of distributed locking systems like Redlock, which previously relied on Lua scripting to implement this logic. With DELIFEQ, such a use case becomes more robust and idiomatic.
Instead of:
EVAL "if redis.call('GET',KEYS[1]) == ARGV[1] then return redis.call('DEL',KEYS[1]) else return 0 end" 1 mykey abc123
You can now use:
DELIFEQ mykey abc123
See also
SET IFEQ- Sets the key only if it matches the given value.
discard
Flushes all previously queued commands in a transaction and restores the connection state to normal.
If WATCH was used, DISCARD unwatches all keys watched by the connection.
dump
Serialize the value stored at key in a Valkey-specific format and return it to
the user.
The returned value can be synthesized back into a Valkey key using the RESTORE
command.
The serialization format is opaque and non-standard, however it has a few semantic characteristics:
- It contains a 64-bit checksum that is used to make sure errors will be
detected.
The
RESTOREcommand makes sure to check the checksum before synthesizing a key using the serialized value. - Values are encoded in the same format used by RDB.
- An RDB version is encoded inside the serialized value, so that different Valkey versions with incompatible RDB formats will refuse to process the serialized value.
The serialized value does NOT contain expire information.
In order to capture the time to live of the current value the PTTL command
should be used.
If key does not exist a nil bulk reply is returned.
Examples
> SET mykey 10
OK
> DUMP mykey
"\x00\xc0\n\n\x00n\x9fWE\x0e\xaec\xbb"
echo
Returns message.
Examples
127.0.0.1:6379> ECHO "Hello World!"
"Hello World!"
eval
Invoke the execution of a server-side Lua script.
The first argument is the script's source code. Scripts are written in Lua and executed by the embedded Lua 5.1 interpreter in Valkey.
The second argument is the number of input key name arguments, followed by all the keys accessed by the script. These names of input keys are available to the script as the KEYS global runtime variable Any additional input arguments should not represent names of keys.
Important: to ensure the correct execution of scripts, both in standalone and clustered deployments, all names of keys that a script accesses must be explicitly provided as input key arguments. The script should only access keys whose names are given as input arguments. Scripts should never access keys with programmatically-generated names or based on the contents of data structures stored in the database.
Note:
in some cases, users will abuse Lua EVAL by embedding values in the script instead of providing them as argument, and thus generating a different script on each call to EVAL.
These are added to the Lua interpreter and cached to valkey-server, consuming a large amount of memory over time.
Starting from Valkey 8.0, scripts loaded with EVAL or EVAL_RO will be deleted from Valkey after a certain number (least recently used order).
The number of evicted scripts can be viewed through the evicted_scripts field in the stats section of the INFO command.
Please refer to the Valkey Programmability and Introduction to Eval Scripts for more information about Lua scripts.
Examples
The following example will run a script that returns the first argument that it gets.
> EVAL "return ARGV[1]" 0 hello
"hello"
eval_ro
This is a read-only variant of the EVAL command that cannot execute commands that modify data.
For more information about when to use this command vs EVAL, please refer to Read-only scripts.
For more information about EVAL scripts please refer to Introduction to Eval Scripts.
Examples
> SET mykey "Hello"
OK
> EVAL_RO "return server.call('GET', KEYS[1])" 1 mykey
"Hello"
> EVAL_RO "return server.call('DEL', KEYS[1])" 1 mykey
(error) ERR Error running script (call to b0d697da25b13e49157b2c214a4033546aba2104): @user_script:1: @user_script: 1: Write commands are not allowed from read-only scripts.
evalsha
Evaluate a script from the server's cache by its SHA1 digest.
The server caches scripts by using the SCRIPT LOAD command.
The command is otherwise identical to EVAL.
Please refer to the Valkey Programmability and Introduction to Eval Scripts for more information about Lua scripts.
evalsha_ro
This is a read-only variant of the EVALSHA command that cannot execute commands that modify data.
For more information about when to use this command vs EVALSHA, please refer to Read-only scripts.
For more information about EVALSHA scripts, please refer to Introduction to Eval Scripts.
exec
Executes all previously queued commands in a transaction and restores the connection state to normal.
When using WATCH, EXEC will execute commands only if the watched keys were
not modified, allowing for a check-and-set mechanism.
exists
Returns if key exists.
The user should be aware that if the same existing key is mentioned in the arguments multiple times, it will be counted multiple times. So if somekey exists, EXISTS somekey somekey will return 2.
Examples
127.0.0.1:6379> SET key1 "Hello"
OK
127.0.0.1:6379> EXISTS key1
(integer) 1
127.0.0.1:6379> EXISTS nosuchkey
(integer) 0
127.0.0.1:6379> SET key2 "World"
OK
127.0.0.1:6379> EXISTS key1 key2 nosuchkey
(integer) 2
expire
Set a timeout on key.
After the timeout has expired, the key will automatically be deleted.
A key with an associated timeout is often said to be volatile in Valkey
terminology.
The timeout will only be cleared by commands that delete or overwrite the
contents of the key, including DEL, SET, GETSET and all the *STORE
commands.
This means that all the operations that conceptually alter the value stored at
the key without replacing it with a new one will leave the timeout untouched.
For instance, incrementing the value of a key with INCR, pushing a new value
into a list with LPUSH, or altering the field value of a hash with HSET are
all operations that will leave the timeout untouched.
The timeout can also be cleared, turning the key back into a persistent key,
using the PERSIST command.
If a key is renamed with RENAME, the associated time to live is transferred to
the new key name.
If a key is overwritten by RENAME, like in the case of an existing key Key_A
that is overwritten by a call like RENAME Key_B Key_A, it does not matter if
the original Key_A had a timeout associated or not, the new key Key_A will
inherit all the characteristics of Key_B.
Note that calling EXPIRE/PEXPIRE with a non-positive timeout or
EXPIREAT/PEXPIREAT with a time in the past will result in the key being
deleted rather than expired (accordingly, the emitted key event
will be del, not expired).
Options
The EXPIRE command supports a set of options:
NX-- Set expiry only when the key has no expiryXX-- Set expiry only when the key has an existing expiryGT-- Set expiry only when the new expiry is greater than current oneLT-- Set expiry only when the new expiry is less than current one
A non-volatile key is treated as an infinite TTL for the purpose of GT and LT.
The GT, LT and NX options are mutually exclusive.
Refreshing expires
It is possible to call EXPIRE using as argument a key that already has an
existing expire set.
In this case the time to live of a key is updated to the new value.
There are many useful applications for this, an example is documented in the
Navigation session pattern section below.
EXPIRE would return 0 and not alter the timeout for a key with a timeout set.
Examples
127.0.0.1:6379> SET mykey "Hello"
OK
127.0.0.1:6379> EXPIRE mykey 10
(integer) 1
127.0.0.1:6379> TTL mykey
(integer) 10
127.0.0.1:6379> SET mykey "Hello World"
OK
127.0.0.1:6379> TTL mykey
(integer) -1
127.0.0.1:6379> EXPIRE mykey 10 XX
(integer) 0
127.0.0.1:6379> TTL mykey
(integer) -1
127.0.0.1:6379> EXPIRE mykey 10 NX
(integer) 1
127.0.0.1:6379> TTL mykey
(integer) 10
Pattern: Navigation session
Imagine you have a web service and you are interested in the latest N pages recently visited by your users, such that each adjacent page view was not performed more than 60 seconds after the previous. Conceptually you may consider this set of page views as a Navigation session of your user, that may contain interesting information about what kind of products he or she is looking for currently, so that you can recommend related products.
You can easily model this pattern in Valkey using the following strategy: every time the user does a page view you call the following commands:
MULTI
RPUSH pagewviews.user:<userid> http://.....
EXPIRE pagewviews.user:<userid> 60
EXEC
If the user will be idle more than 60 seconds, the key will be deleted and only subsequent page views that have less than 60 seconds of difference will be recorded.
This pattern is easily modified to use counters using INCR instead of lists
using RPUSH.
Appendix: Valkey expires
Keys with an expire
Normally Valkey keys are created without an associated time to live.
The key will simply live forever, unless it is removed by the user in an
explicit way, for instance using the DEL command.
The EXPIRE family of commands is able to associate an expire to a given key,
at the cost of some additional memory used by the key.
When a key has an expire set, Valkey will make sure to remove the key when the
specified amount of time elapsed.
The key time to live can be updated or entirely removed using the EXPIRE and
PERSIST command (or other strictly related commands).
Expire accuracy
The expire error is from 0 to 1 milliseconds.
Expires and persistence
Keys expiring information is stored in milliseconds. This means that the time is flowing even when the Valkey instance is not active.
For expires to work well, the computer time must be taken stable. If you move an RDB file from two computers with a big desync in their clocks, funny things may happen (like all the keys loaded to be expired at loading time).
Even running instances will always check the computer clock, so for instance if you set a key with a time to live of 1000 seconds, and then set your computer time 2000 seconds in the future, the key will be expired immediately, instead of lasting for 1000 seconds.
How Valkey reclaims expired keys
Valkey reclaims expired keys in two ways: on access and in the background in what is called the "active expire key" cycles. On access expiration is when a client tries to access a key with the expiration time which is found to be timed out. Such a key is deleted on this access attempt.
Relying solely on the on access expiration only is not enough because there are expired keys that may never be accessed again. To address this, Valkey uses the background expiration algorithm known as the "active expire key" effort. This algorithm is adaptive: it tries to use less CPU if there are few expired keys to reclaim. Otherwise, it gets more aggressive trying to free more memory by reclaiming more keys in shorter runs but using more CPU.
This is how it works:
Valkey slowly scans the keyspace to identify and reclaim expired keys. This "slow cycle" is the main way to collect expired keys and operates with the server's hertz frequency (usually 10 hertz). During the slow cycle, Valkey tolerates having not more than 10% of the expired keys in the memory and tries to use a maximum of 25% CPU power. These default values are adjusted if the user changes the active expire key effort configuration.
If the number of expired keys remains high after the slow cycle, the active expire key effort transitions into the "fast cycle", trying to do less work but more often. The fast cycle runs no longer than 1000 microseconds and repeats at the same interval. During the fast cycle, the check of every database is interrupted once the number of already expired keys in the database is estimated to be lower than 10%. This is done to avoid doing too much work to gain too little memory.
You can modify the active expire key effort with the active-expire-effort parameter in the configuration file up to the maximum value of 10. The default active-expire-effort value is 1, and it is described by the following base values:
ACTIVE_EXPIRE_CYCLE_KEYS_PER_LOOPhas a base value of 20. The number of keys for each DB loop.ACTIVE_EXPIRE_CYCLE_FAST_DURATIONhas a base value of 1000. The maximum duration of the fast cycle in microseconds.ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERChas a base value of 25. The maximum % of CPU to use during the slow cycle.ACTIVE_EXPIRE_CYCLE_ACCEPTABLE_STALEhas a base value of 10. The maximum % of expired keys to tolerate in memory.
Changing the active-expire-effort value results in a lower percentage of expired keys tolerated in memory. However, it will lead to longer cycles and increased CPU usage, which may introduce latency.
To calculate the new values, use the following formulas:
ACTIVE_EXPIRE_CYCLE_KEYS_PER_LOOP + (ACTIVE_EXPIRE_CYCLE_KEYS_PER_LOOP / 4 * (effort - 1))ACTIVE_EXPIRE_CYCLE_FAST_DURATION + (ACTIVE_EXPIRE_CYCLE_FAST_DURATION / 4 * (effort - 1))ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC + (2 * (effort - 1))ACTIVE_EXPIRE_CYCLE_ACCEPTABLE_STALE - (effort - 1)
where ACTIVE_EXPIRE_CYCLE_KEYS_PER_LOOP, ACTIVE_EXPIRE_CYCLE_FAST_DURATION, ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC, and ACTIVE_EXPIRE_CYCLE_ACCEPTABLE_STALE are the base values, and effort is the specified active-expire-effort.
How expires are handled in the replication link and AOF file
In order to obtain a correct behavior without sacrificing consistency, when a
key expires, a DEL operation is synthesized in both the AOF file and gains all
the attached replicas nodes.
This way the expiration process is centralized in the primary instance, and there
is no chance of consistency errors.
However while the replicas connected to a primary will not expire keys
independently (but will wait for the DEL coming from the primary), they'll
still take the full state of the expires existing in the dataset, so when a
replica is elected to primary it will be able to expire the keys independently,
fully acting as a primary.
expireat
EXPIREAT has the same effect and semantic as EXPIRE, but instead of
specifying the number of seconds representing the TTL (time to live), it takes
an absolute Unix timestamp (seconds since January 1, 1970). A
timestamp in the past will delete the key immediately.
Please for the specific semantics of the command refer to the documentation of
EXPIRE.
Background
EXPIREAT was introduced in order to convert relative timeouts to absolute
timeouts for the AOF persistence mode.
Of course, it can be used directly to specify that a given key should expire at
a given time in the future.
Options
The EXPIREAT command supports a set of options:
NX-- Set expiry only when the key has no expiryXX-- Set expiry only when the key has an existing expiryGT-- Set expiry only when the new expiry is greater than current oneLT-- Set expiry only when the new expiry is less than current one
A non-volatile key is treated as an infinite TTL for the purpose of GT and LT.
The GT, LT and NX options are mutually exclusive.
Examples
127.0.0.1:6379> SET mykey "Hello"
OK
127.0.0.1:6379> EXISTS mykey
(integer) 1
127.0.0.1:6379> EXPIREAT mykey 1293840000
(integer) 1
127.0.0.1:6379> EXISTS mykey
(integer) 0
expiretime
Returns the absolute Unix timestamp (since January 1, 1970) in seconds at which the given key will expire.
See also the PEXPIRETIME command which returns the same information with milliseconds resolution.
Examples
127.0.0.1:6379> SET mykey "Hello"
OK
127.0.0.1:6379> EXPIREAT mykey 33177117420
(integer) 1
127.0.0.1:6379> EXPIRETIME mykey
(integer) 33177117420
failover
This command will start a coordinated failover between the currently-connected-to primary and one of its replicas.
The failover is not synchronous, instead a background task will handle coordinating the failover.
It is designed to limit data loss and unavailability of the cluster during the failover.
This command is analogous to the CLUSTER FAILOVER command for non-clustered Valkey and is similar to the failover support provided by sentinel.
The specific details of the default failover flow are as follows:
- The primary will internally start a
CLIENT PAUSE WRITE, which will pause incoming writes and prevent the accumulation of new data in the replication stream. - The primary will monitor its replicas, waiting for a replica to indicate that it has fully consumed the replication stream. If the primary has multiple replicas, it will only wait for the first replica to catch up.
- The primary will then demote itself to a replica. This is done to prevent any dual primary scenarios. NOTE: The primary will not discard its data, so it will be able to rollback if the replica rejects the failover request in the next step.
- The previous primary will send a special PSYNC request to the target replica,
PSYNC FAILOVER, instructing the target replica to become a primary. - Once the previous primary receives acknowledgement the
PSYNC FAILOVERwas accepted it will unpause its clients. If the PSYNC request is rejected, the primary will abort the failover and return to normal.
The field master_failover_state in INFO replication can be used to track the current state of the failover, which has the following values:
no-failover: There is no ongoing coordinated failover.waiting-for-sync: The primary is waiting for the replica to catch up to its replication offset.failover-in-progress: The primary has demoted itself, and is attempting to hand off ownership to a target replica.
NOTE:
During the failover-in-progress phase, the primary first demotes itself to a replica and then notifies the replica to promote itself to primary.
These two steps are an asynchronous process, which may result in the simultaneous existence of two nodes as replicas.
In this scenario, for clients that support REDIRECT (explicitly execute CLIENT CAPA REDIRECT), the redirection result may bounce back and forth between the two replicas until the target replica completes the process of promoting itself to primary.
To avoid this situation, during the failover-in-progress phase, we temporarily suspend the clients that need to be redirected until the replica truly becomes the primary, and then resume the execution.
If the previous primary had additional replicas attached to it, they will continue replicating from it as chained replicas. You will need to manually execute a REPLICAOF on these replicas to start replicating directly from the new primary.
Optional arguments
The following optional arguments exist to modify the behavior of the failover flow:
-
TIMEOUTmilliseconds -- This option allows specifying a maximum time a primary will wait in thewaiting-for-syncstate before aborting the failover attempt and rolling back. This is intended to set an upper bound on the write outage the Valkey cluster can experience. Failovers typically happen in less than a second, but could take longer if there is a large amount of write traffic or the replica is already behind in consuming the replication stream. If this value is not specified, the timeout can be considered to be "infinite". -
TOHOST PORT -- This option allows designating a specific replica, by its host and port, to failover to. The primary will wait specifically for this replica to catch up to its replication offset, and then failover to it. -
FORCE-- If both theTIMEOUTandTOoptions are set, the force flag can also be used to designate that that once the timeout has elapsed, the primary should failover to the target replica instead of rolling back. This can be used for a best-effort attempt at a failover without data loss, but limiting write outage.
NOTE: The primary will always rollback if the PSYNC FAILOVER request is rejected by the target replica.
Failover abort
The failover command is intended to be safe from data loss and corruption, but can encounter some scenarios it can not automatically remediate from and may get stuck.
For this purpose, the FAILOVER ABORT command exists, which will abort an ongoing failover and return the primary to its normal state.
The command has no side effects if issued in the waiting-for-sync state but can introduce multi-primary scenarios in the failover-in-progress state.
If a multi-primary scenario is encountered, you will need to manually identify which primary has the latest data and designate it as the primary and have the other replicas.
NOTE: REPLICAOF is disabled while a failover is in progress, this is to prevent unintended interactions with the failover that might cause data loss.
fcall
Invoke a function.
Functions are loaded to the server with the FUNCTION LOAD command.
The first argument is the name of a loaded function.
The second argument is the number of input key name arguments, followed by all the keys accessed by the function. In Lua, these names of input keys are available to the function as a table that is the callback's first argument.
Important: To ensure the correct execution of functions, both in standalone and clustered deployments, all names of keys that a function accesses must be explicitly provided as input key arguments. The function should only access keys whose names are given as input arguments. Functions should never access keys with programmatically-generated names or based on the contents of data structures stored in the database.
Any additional input argument should not represent names of keys. These are regular arguments and are passed in a Lua table as the callback's second argument.
For more information please refer to the Valkey Programmability and Introduction to Valkey Functions pages.
Examples
The following example will create a library named mylib with a single function, myfunc, that returns the first argument it gets.
127.0.0.1:6379> FUNCTION LOAD "#!lua name=mylib \n server.register_function('myfunc', function(keys, args) return args[1] end)"
"mylib"
127.0.0.1:6379> FCALL myfunc 0 hello
"hello"
fcall_ro
This is a read-only variant of the FCALL command that cannot execute commands that modify data.
For more information about when to use this command vs FCALL, please refer to Read-only scripts.
For more information please refer to Introduction to Valkey Functions.
flushall
Delete all the keys of all the existing databases, not just the currently selected one. This command never fails.
By default, FLUSHALL will synchronously flush all the databases.
Setting the lazyfree-lazy-user-flush configuration directive to "yes" changes the default flush mode to asynchronous.
It is possible to use one of the following modifiers to dictate the flushing mode explicitly:
ASYNC: flushes the databases asynchronouslySYNC: flushes the databases synchronously
Note: an asynchronous FLUSHALL command only deletes keys that were present at the time the command was invoked. Keys created during an asynchronous flush will be unaffected.
Because FLUSHALL operates on every database, the caller must have ACL access
to all databases (the alldbs rule). See
database permissions.
flushdb
Delete all the keys of the currently selected DB. This command never fails.
By default, FLUSHDB will synchronously flush all keys from the database.
Setting the lazyfree-lazy-user-flush configuration directive to "yes" changes the default flush mode to asynchronous.
It is possible to use one of the following modifiers to dictate the flushing mode explicitly:
ASYNC: flushes the database asynchronously!SYNC: flushes the database synchronously
Note: an asynchronous FLUSHDB command only deletes keys that were present at the time the command was invoked. Keys created during an asynchronous flush will be unaffected.
ft._list
Lists the currently defined indexes for the current data base.
FT._LIST
Response
An array of strings. Each string is the name of an index in the current database. The index names are in no particular order.
Example
ft._list
1) index
2) products
3) users
4) transactions
ft.aggregate
The FT.AGGREGATE command extends the query capabilities of the FT.SEARCH command with substantial server-side data processing capabilities.
The first step of the command is to use the index name and query string to locate a list of Valkey keys. This process is identical to the FT.SEARCH command.
The second step is executed once for each key found in the first step. The contents of the key are extracted as directed by the LOAD clause, resulting in a set of name/value pairs which are collected into a record. Thus the output of this step is the working set of records, one record for each key found in the first step. If the query is a KNN query then the initial working set will be sorted by distance, otherwise the working set will be in no particular order.
The next steps are to execute the list of stages provided on the command, sequentially one at a time. Each step takes as input the working set of records and performs some transformation on it, i.e., the output of one stage is fed into the input of the next stage.
Once all stages have been executed, the working set of records output from the last stage is returned as the result of the command.
FT.AGGREGATE <index-name> <query>
[DIALECT <dialect>]
[INORDER]
[LOAD * | LOAD <count> <field> [AS <alias>] [<field> [AS <alias>] ...]]
[PARAMS <count> <name> <value> [ <name> <value> ...]]
[SLOP <slop>]
[TIMEOUT <timeout>]
[VERBATIM]
[WITHCURSOR [COUNT <count>] [MAXIDLE <maxidle>]]
(
| APPLY <expression> AS <field>
| FILTER <expression>
| GROUPBY <count> <field> [<field> ... ] [[REDUCE <reducer> <count> [<expression> [<expression> ...]]] [ REDUCE ...]]
| LIMIT <offset> <count>
| SORTBY <count> <expression> [ASC | DESC] [<expression [ASC | DESC] ...] [MAX <num>]
)+
-
<index>(required): This index name you want to query. -
<query>(required): The query string, see Search - query language for details. -
DIALECT <dialect>(optional): Specifies your dialect. The only supported dialect is 2. -
INORDER(optional): Indicates that proximity matching of terms must be in order. -
LOAD * | LOAD <count> <field> [AS <alias>] [<field> [AS <alias>] ...](optional): This controls which fields of those keys are loaded into the working set. A star (*) indicates that all of the fields of the keys are loaded. The key itself can be loaded by specifying@__key. For vector queries, the distance can also be loaded by using the name of that field.<count>is a count of the arguments that follow, not a count of fields. AnASkeyword and its alias each count against<count>, soLOAD 4 @a @b AS cloads two fields using four arguments.Each
<field>may be a declared attribute name (@price), or, for a JSON index, a JSON path ($.price). A JSON path that resolves to a declared attribute is loaded as that attribute.AS <alias>renames the loaded field: it is emitted under<alias>in the result and is referenced as@<alias>by later stages. Without anASclause the field is emitted under the name given in theLOADclause. An alias may reuse the name of a declared attribute, in which case it hides that attribute for the remainder of the pipeline. A singleLOADclause must not produce the same output name twice; doing so is an error.Honoring
ASin theLOADclause is a compatibility fix gated onsearch.emulate-releasebeing1.3.0or greater; under an emulated release below that,ASis treated as an ordinary field name. Accepting a JSON path as<field>is not gated, since before it was supported such a load simply failed. See COMPATIBILITY.md for details. -
PARAMS <count> <name> <value> [<name> <value> ...](optional):countis of the number of arguments, i.e., twice the number ofname/valuepairs.PARAMScan be used in both the query string as well as within an expression context. See Search - query language for usage details. -
SLOP <slop>(Optional): Specifies a slop value for proximity matching of terms. -
TIMEOUT <timeout>(optional): Lets you set a timeout value for the search command. This must be an integer in milliseconds. -
VERBATIM(Optional): If specified stemming is not applied to term searches. -
WITHCURSOR [COUNT <count>] [MAXIDLE <maxidle>](optional): Returns at most<count>records and saves the remaining records in a cursor, which is read withFT.CURSOR.<count>must be between 1 andsearch.cursor-max-count, the default is 1000.<maxidle>is the number of milliseconds the cursor may go unread before it is destroyed; it must be between 1 andsearch.cursor-max-idle-ms, the default is 300000.WITHCURSORmay appear anywhere after the query, including between stages. If it is given more than once, the last one is used. -
APPLY <expression> as <field>(optional): An expression is computed and insert into the record. See APPLY Stage below. See Search - expressions for details on the expression syntax. -
FILTER <expression>(optional): The filter expression is applied, see FILTER Stage for more details. See Search - expressions for details on the expression syntax. -
GROUPBY <count> <field> <field> ... [REDUCE <reducer> <count> [<expression> [<expression> ...]]](optional): The working set is grouped into buckets according to the input fields. One summarization record is generated for each bucket including the outputs of each reducer. See GROUPBY Stage for details. -
LIMIT <offset> <count>(optional): The working set is trimmed, see LIMIT Stage for details. -
SORTBY <count> <expression> [ASC | DESC] [<expression> [ASC | DESC] ...] [MAX <num>](optional): The working set is sorted. See SORTBY Stage for more details.
Result
The output is an array. The first element of this array is a scalar number with no particular meaning and should be ignored. The remainder of the array is one element for each record output by the final processing stage.
Each record is represented by an array which contains the field/value pairs of each record.
If WITHCURSOR is specified the output is a two element array. The first element is an array whose first element is the number of records returned, followed by one element for each returned record. The second element is the cursor id to pass to FT.CURSOR READ, or 0 if all records were returned, in which case no cursor is created.
Processing Stages
APPLY Stage
The APPLY stage processes each record of the working set in sequence. For each record the expression is computed with output being set into the record with the provided field name. It is allowed to overwrite an existing field. The apply stage does not change the number of records in the working set.
FILTER Stage
The FILTER stage processes each record of the working set in sequence. For each record the expression is computed. If the expression evaluates to zero then the record is discarded else the record remains.
LIMIT Stage
The LIMIT stage discards records from the working set based on the provided offset and count.
SORTBY Stage
The SORTBY stage reorders the records in accordance with a sort key. A sort key can be constructed using a number of expressions optionally combined with a direction.
If the MAX clause is present, then the output is trimmed after the first N records. It is more efficient to use the MAX clause than to follow the SORTBY stage with a limit stage.
GROUPBY Stage
The GROUPBY stage organizes the input records into buckets based on the values of the specified fields.
For each unique combination of values a separate bucket is created to hold all records that have that combination of values.
Each bucket of records is processed into a single output record, discarding the bucket contents. That output record has two sections. The first section has one value for each of the specified GROUPBY fields. This section provides the values that formed (named) this unique bucket.
The second section is the output of the reducers for that bucket. Reducers provide an efficient mechanism for reducing (summarizing) the contents of a bucket. Each reducer function processes each record of the bucket and generates a single output value which is inserted into the second section of GROUPBY output record for this bucket.
The output of the GROUPBYstage is one record for each unique bucket.
Reducers
The following reducer functions are available. The reducer functions that take an input expression will convert that expression into a number.
| Syntax | Function |
|---|---|
| COUNT 0 | Number of records |
| COUNT_DISTINCT 1 | The exact number of distinct values of the expression. Caution this consumes memory proportional to the number of distinct values. |
| SUM 1 | The numerical sum of the values of the expression. |
| MIN 1 | The smallest numerical values of the expression. |
| MAX 1 | The largest numerical values of the expression. |
| AVG 1 | The numerical average of the values of the expression. |
| STDDEV 1 | The standard deviation the values of the expression. |
| FIRST_VALUE 1 | The first value of the expression encountered in the group. Order depends on record retrieval order. Use only when order does not matter. |
| FIRST_VALUE 3 BY | The value of the first expression from the record with the smallest comparison expression (ascending). Ties broken by first-encountered order. |
| FIRST_VALUE 4 BY ASC|DESC | The value of the first expression from the record with the minimum (ASC) or maximum (DESC) comparison expression. Ties broken by first-encountered order. Invalid keyword arguments (e.g., wrong BY token or unrecognized direction) produce a parse-time error. |
| RANDOM_SAMPLE 2 <sample_size> | A random sample of values from the expression using reservoir sampling. Returns an array of up to sample_size elements (maximum 1000). Nil values are excluded. Output is non-deterministic. |
ft.create
The FT.CREATE command creates an empty index and may initiate the backfill process. Each index consists of a number of
field definitions. Each field definition specifies a field name, a field type and a path within each indexed key to
locate a value of the declared type. Some field type definitions have additional sub-type specifiers.
For indexes on HASH keys, the default path is the same as the hash member name. The optional AS clause can be used to rename
the field if desired
For indexes on JSON keys, the path is a JSON path to the data of the declared type. The AS clause is required in order to provide a field name without the special characters of a JSON path.
FT.CREATE <index-name>
[ON HASH | ON JSON]
[PREFIX <count> <prefix> [<prefix>...]]
[FILTER <expression>]
[SCORE default_value]
[SCORE_FIELD <field_name>]
[LANGUAGE <language>]
[SKIPINITIALSCAN]
[MINSTEMSIZE <min_stem_size>]
[WITHOFFSETS | NOOFFSETS]
[NOHL]
[NOSTOPWORDS | STOPWORDS <count> <word> word ...]
[PUNCTUATION <punctuation>]
SCHEMA
(
<field-identifier> [AS <field-alias>]
NUMERIC
| TAG [SEPARATOR <sep>] [CASESENSITIVE]
| TEXT [NOSTEM] [WITHSUFFIXTRIE | NOSUFFIXTRIE] [WEIGHT <weight>]
| VECTOR [HNSW | FLAT] <attr_count> [<attribute_name> <attribute_value>]+
[SORTABLE [UNF]]
)+
-
<index-name>(required): This is the name you give to your index. If an index with the same name exists already, an error is returned. -
ON HASH | ON JSON(optional): Only keys that match the specified type are included into this index. If omitted, HASH is assumed. -
PREFIX <prefix-count> <prefix>(optional): If this clause is specified, then only keys that begin with the same bytes as one or more of the specified prefixes will be included into this index. If this clause is omitted, all keys of the correct type will be included. A zero-length prefix would also match all keys of the correct type. -
FILTER <expression>(optional): A boolean expression evaluated for each candidate key during ingestion; only keys for which it evaluates to true are included in the index. A comparison involving a missing field is false, so a key that has nostatusfield is admitted by neither@status == 'active'nor@status != 'active'— a negation such as!(@status == 'active')admits it instead, because the comparison it negates is false. The number of keys excluded by the filter is reported byFT.INFOasfilter_rejected_keys.See Search - expressions for details on the expression syntax.
A field's value always reaches the expression as its stored bytes, whatever type the
SCHEMAdeclares — aNUMERICfield is not a number to aFILTER. A comparison is numeric only when one side really is a number, meaning a bare numeric literal such as5or a number-returning function such asstrlen(). So@price > 100compares numerically, while@price > '100'and@price > @costcompare the values as strings, byte by byte. In a numeric comparison a value that is not a number is unordered:@price != 5is true for it and every other comparison is false.Field references use the
@<name>syntax. For aHASHindex the expression may reference a field that is not declared in theSCHEMA; its value is read directly off the key at ingestion time (an absent field makes the comparison false). Because an undeclared field name is read verbatim from the key, a misspelled field name does not produce an error — watchfilter_rejected_keysinFT.INFOto detect this. For aJSONindex every field referenced by the expression must be declared in theSCHEMA; referencing an undeclared field is rejected when the index is created. -
LANGUAGE <language>(optional): For text fields, the language used to control lexical parsing and stemming. It selects the stemmer and the default punctuation and stop words. Supported values:ENGLISH(default),ARABIC,DUTCH,FRENCH,GERMAN,INDONESIAN,ITALIAN,PORTUGUESE,RUSSIAN,SPANISH,SWEDISH,TURKISH. Languages other than English require 1.3.0 or later. -
MINSTEMSIZE <min_stem_size>(optional): For text fields with stemming enabled. This controls the minimum length of a word, in characters (Unicode code points), required for it to be subjected to stemming. The default value is 4. On English indexes withsearch.emulate-releasebelow 1.3.0, the length is counted in bytes (see COMPATIBILITY.md). -
WITHOFFSETS | NOOFFSETS(optional): Enables/Disables the retention of per-word offsets within a text field. Offsets are required to perform exact phrase matching and slop-based proximity matching. Thus if offsets are disabled, those query operations will be rejected with an error. The default isWITHOFFSETS. -
NOHL(optional): This parameter is accepted for compatibility, but has no effect. -
NOSTOPWORDS | STOPWORDS <count> <word1> <word2>...(optional): Stop words are words which are not put into the indexes. The default value ofSTOPWORDSis language dependent. ForLANGUAGE ENGLISHthe default is: [a, an, and, are, as, at, be, but, by, for, if, in, into, is, it, no, not, of, on, or, such, that, their, then, there, these, they, this, to, was, will, with]. -
PUNCTUATION <punctuation>(optional): A string of characters that define the separation points between words, in addition to whitespace characters (spaces, tabs, newlines, carriage returns, and control characters) which always break words. Each character, including a multi-byte one such as—, is matched as a whole Unicode code point; before 1.3 each byte of a multi-byte character was matched separately, which also split unrelated characters sharing those bytes. The default value depends onLANGUAGE; for English it is,.<>{}[]"':;!@#$%^&\*()-+=~/\|?. -
SKIPINITIALSCAN(optional): If specified, this option skips the normal backfill operation for an index. If this option is specified, pre-existing keys which match thePREFIXclause will not be loaded into the index during a backfill operation. This clause has no effect on processing of key mutations after an index is created, i.e., keys which are mutated after an index is created and satisfy the data type andPREFIXclause will be inserted into that index. -
SCORE(optional): Sets the default document score used for text search ranking. The value must be between 0.0 and 1.0. WhenSCORE_FIELDis configured, this value is used as the fallback if a document's score field is missing or cannot be parsed. (default: 1.0) -
SCORE_FIELD <field_name>(optional): Specifies the name of a hash field whose numeric value is used as the per-document score. When configured, the value of this field is read during ingestion and stored as the document's relevance score for text search ranking. If the field is missing or cannot be parsed as a valid number, the index-levelSCOREdefault is used. The raw value is stored without clamping; the scoring algorithm determines how to handle values at query time.
Field types
TAG: A tag field is a string that contains one or more tag values.
SEPARATOR <sep>(optional): One of these characters,.<>{}[]"':;!@#$%^&*()-+=~used to delimit individual tags. If omitted the default value is,.CASESENSITIVE(optional): If present, tag comparisons will be case sensitive. The default is that tag comparisons are NOT case sensitive.
See Tag Field Format for more details and examples.
TEXT: A text field is a string that contains words
NOSTEM(optional): If specified, stemming of words on ingestion is disabled.WITHSUFFIXTRIE | NOSUFFIXTRIE(optional): Enables/Disables the use of a suffix trie to implement suffix-based wildcard queries. IfNOSUFFIXTRIEis specified, query strings which specify suffix-based wildcard matching will be rejected with an error. The default isWITHSUFFIXTRIE.WEIGHT <weight>(optional): The current implementation only allows the value to be 1.0. This parameter is accepted to make valkey-search more interoperable with RediSearch. (default: 1.0)
See Text Field Format for more details and examples.
NUMERIC: A numeric field contains a number.
See Numeric Field Format for details and examples.
VECTOR: A vector field contains a vector. Two vector indexing algorithms are currently supported: HNSW (Hierarchical Navigable Small World) and FLAT (brute force). Each algorithm has a set of additional attributes, some required and other optional.
FLAT:This algorithm provides exact answers, but has runtime proportional to the number of indexed vectors and thus may not be appropriate for large data sets.DIM <number>(required): Specifies the number of dimensions in a vector.TYPE [FLOAT32 | FLOAT16 | BFLOAT16](required): Element data type.FLOAT16andBFLOAT16halve the memory used per vector at some cost in precision; see Supported Data Types.DISTANCE_METRIC [L2 | IP | COSINE](required): Specifies the distance algorithmINITIAL_CAP <size>(optional): Initial index size.
HNSW:The HNSW algorithm provides approximate answers, but operates substantially faster thanFLAT.DIM <number>(required): Specifies the number of dimensions in a vector.TYPE [FLOAT32 | FLOAT16 | BFLOAT16](required): Element data type.FLOAT16andBFLOAT16halve the memory used per vector at some cost in precision; see Supported Data Types.INITIAL_CAP <size>(optional): Initial index size.M <number>(optional): Number of maximum allowed outgoing edges for each node in the graph in each layer. on layer zero the maximal number of outgoing edges will be 2*M. Default is 16, the maximum is 512.EF_CONSTRUCTION <number>(optional): controls the number of vectors examined during index construction. Higher values for this parameter will improve recall ratio at the expense of longer index creation times. The default value is 200. Maximum value is 4096.EF_RUNTIME <number>(optional): controls the number of vectors to be examined during a query operation. The default is 10, and the max is 4096. You can set this parameter value for each query you run. Higher values increase query times, but improve query recall.DISTANCE_METRIC [L2 | IP | COSINE](required): Specifies the distance algorithm.
See Vector Field Format for more details and examples.
The KNN search algorithm operates to locate vectors that are the nearest to the query vector, i.e., looking for the smallest distance value. The computation of the distance metrics is adjusted from their classical definitions in order to posses this property. This table shows the actual computation that Search uses when computing the distance between two vectors: $X$ and $Y$.
| Classical Name | Valkey Search Distance Metric Name | Classical Distance Formula Definition | Valkey Search Distance Formula |
|---|---|---|---|
| Inner Product | IP | dot(X,Y) | 1 - dot(X,Y) |
| Euclidean | L2 | sqrt(sum((x[i]-y[i])^2)) | sum((x[i]-y[i])^2) |
| Cosine | COSINE | dot(x,y) / (magnitude(X) * magnitude(Y)) | 1 - (dot(X,Y) / (magnitude(X) * magnitude(Y))) |
Field options
SORTABLE (optional): This parameter is not required. Any field may be used with SORTBY whether or not it is declared SORTABLE. It is recorded on the attribute and reported by FT.INFO, but does not otherwise affect indexing or query behavior.
UNF(optional): Only valid immediately afterSORTABLE. In RediSearch this keeps the sort value of aSORTABLEfield in its original form instead of converting it to lowercase.SORTBYalready compares the stored field value directly, so this has no effect beyond being reported byFT.INFO.
Examples
HNSW example:
FT.CREATE my_index_name SCHEMA my_hash_field_key VECTOR HNSW 10 TYPE FLOAT32 DIM 20 DISTANCE_METRIC COSINE M 4 EF_CONSTRUCTION 100
Result:
OK
FLAT example:
FT.CREATE my_index_name SCHEMA my_hash_field_key VECTOR Flat TYPE FLOAT32 DIM 20 DISTANCE_METRIC COSINE INITIAL_CAP 15000
Result:
OK
HNSW example with a numeric field:
FT.CREATE my_index_name SCHEMA my_vector_field_key VECTOR HNSW 10 TYPE FLOAT32 DIM 20 DISTANCE_METRIC COSINE M 4 EF_CONSTRUCTION 100 my_numeric_field_key NUMERIC
Result:
OK
HNSW example with multiple tag and numeric fields
FT.CREATE my_index_name SCHEMA my_vector_field_key VECTOR HNSW \
10 TYPE FLOAT32 DIM 20 DISTANCE_METRIC COSINE M 4 EF_CONSTRUCTION \
100 my_tag_field_key_1 TAG SEPARATOR '@' CASESENSITIVE \
my_numeric_field_key_1 NUMERIC my_numeric_field_key_2 NUMERIC my_tag_field_key_2 TAG
Result:
OK
ft.cursor
Reads more rows from, or deletes, a cursor created by the WITHCURSOR option of FT.AGGREGATE, FT.HYBRID or FT.SEARCH.
FT.CURSOR READ <index-name> <cursor-id> [COUNT <count>]
FT.CURSOR DEL <index-name> <cursor-id>
<index-name>(required): The name of an existing index. As in Redis, it need not be the index the cursor was created on.<cursor-id>(required): The cursor id returned by the command that created the cursor, or by a previousFT.CURSOR READ.COUNT <count>(optional): The maximum number of rows to return. It must be between 1 andsearch.cursor-max-count. Without it the cursor's current read size is used, which starts as theCOUNTof theWITHCURSORclause that created the cursor (itself 1000 when that clause gave noCOUNT). Giving aCOUNTreplaces that read size for later reads of this cursor, as in Redis.
A cursor holds the rows of a query result that have not yet been returned to the client, as of when the query ran: later changes to the data are not visible. A cursor belongs to the database it was created in: it can only be read or deleted by a connection whose currently selected database is that database. If SWAPDB moves the cursor's index to another database, its cursors move with it. In cluster mode a cursor exists only on the node that executed the query.
Reading or deleting a cursor requires the same key permissions as querying its index: a user who could not run the query that created the cursor cannot read or delete it either.
A cursor is destroyed when its last row has been read, when it is deleted with FT.CURSOR DEL, when it has not been read for longer than its MAXIDLE time, or when its index is removed (FT.DROPINDEX, FLUSHDB, FLUSHALL, or a replica synchronizing with its primary). Reading a cursor restarts its idle time.
RESPONSE
FT.CURSOR READ returns a two element array. The same format is used for cursors created by FT.AGGREGATE, FT.HYBRID and FT.SEARCH.
- An array whose first element is the number of rows returned, followed by one element for each row. A row of an
FT.AGGREGATEorFT.HYBRIDcursor is an array of field/value pairs. A row of anFT.SEARCHcursor is an array containing the elements for one key of a non-cursorFT.SEARCHresponse, i.e. the key name followed by the optional score, the optional sort key and the array of field/value pairs. - The cursor id to use for the next
FT.CURSOR READ, or 0 if all rows have been returned, in which case the cursor has been destroyed.
FT.CURSOR DEL returns OK. It applies the same checks as FT.CURSOR READ: <index-name> must name an existing index, which need not be the cursor's own, the cursor must belong to the currently selected database, and the user must have permission to read the cursor's index.
Errors:
Index with name '<index-name>' not found in database <db>(READandDEL): the named index does not exist.Cursor not found, id: <cursor-id>(READ) /Cursor does not exist(DEL): there is no such cursor in this database, including a cursor discarded because its index was removed.The user does not have permission to access the key prefix...(READandDEL): the user may not read the cursor's index.The index was dropped while the cursor was idle(READonly): the cursor's index was replaced between the cursor's creation and this read.
Example
> FT.AGGREGATE idx @price:[-inf inf] LOAD 1 @price SORTBY 2 @price ASC WITHCURSOR COUNT 2
1) 1) (integer) 2
2) 1) "price"
2) "10"
3) 1) "price"
2) "20"
2) (integer) 8481957688249417729
> FT.CURSOR READ idx 8481957688249417729 COUNT 2
1) 1) (integer) 2
2) 1) "price"
2) "30"
3) 1) "price"
2) "40"
2) (integer) 8481957688249417729
> FT.CURSOR READ idx 8481957688249417729
1) 1) (integer) 1
2) 1) "price"
2) "50"
2) (integer) 0
ft.dropindex
Drop the index created earlier by FT.CREATE command. It is an error if the index doesn't exist.
FT.DROPINDEX <index-name>
<index-name>(required): The name of the index to delete.
RESPONSE OK or Error.
ft.hybrid
The FT.HYBRID command runs two searches over one index and combines their results into a single ranked list.
The first search is the SEARCH arm: a text, tag or numeric query, scored for relevance the way FT.SEARCH scores one. The second is the VSIM arm: a vector similarity search, scored by distance. Each arm ranks its own matches independently.
The two ranked lists are then fused into one. Fusion is what makes this a hybrid search rather than two searches: a document that both arms found is rewarded for appearing in both, and the COMBINE clause decides how the two arms' scores are weighed against each other.
The fused list is then fed through the same processing stages as FT.AGGREGATE, so the result can be projected, filtered, grouped, sorted and trimmed before it is returned.
FT.HYBRID <index-name>
SEARCH <query> [SCORER <scorer>] [YIELD_SCORE_AS <alias>]
VSIM <field> <vector> [KNN <count> [K <k>] [EF_RUNTIME <ef>] [SHARD_K_RATIO <ratio>]]
[FILTER [<count>] <expression>
[POLICY (ADHOC | BATCHES [BATCH_SIZE <n>])]]
[YIELD_SCORE_AS <alias>]
[COMBINE
( RRF <count> [CONSTANT <c>] [WINDOW <w>] [YIELD_SCORE_AS <alias>]
| LINEAR <count> [ALPHA <a> BETA <b>] [WINDOW <w>] [YIELD_SCORE_AS <alias>]
| FUNCTION <count> EXPR <expression> [WINDOW <w>] [YIELD_SCORE_AS <alias>]
)]
[DIALECT <dialect>]
[LOAD * | LOAD <count> <field> [AS <alias>] [<field> [AS <alias>] ...]]
[PARAMS <count> <name> <value> [ <name> <value> ...]]
[TIMEOUT <timeout>]
[WITHCURSOR [COUNT <count>] [MAXIDLE <maxidle>]]
(
| APPLY <expression> AS <field>
| FILTER <expression>
| GROUPBY <count> <field> [<field> ... ] [[REDUCE <reducer> <count> [<expression> [<expression> ...]]] [ REDUCE ...]]
| LIMIT <offset> <count>
| SORTBY <count> <expression> [ASC | DESC] [<expression> [ASC | DESC] ...] [MAX <num>]
)*
<index-name>(required): The index to query. Both arms search the same index.SEARCH <query>(required): The non-vector arm.<query>is any query the search parser accepts, see Search - query language. A vector query is rejected here — the vector search is theVSIMclause's job.SCORER <scorer>(optional): The relevance scorer for this arm. The only supported scorer isBM25STD, which is also the default.YIELD_SCORE_AS <alias>(optional): Emits this arm's score under<alias>, making it available toCOMBINE FUNCTIONand to the processing stages.
VSIM <field> <vector>(required): The vector arm.<field>is a declared vector attribute and<vector>is a binary blob, supplied throughPARAMS.KNN <count> [K <k>] [EF_RUNTIME <ef>] [SHARD_K_RATIO <ratio>](optional): The vector search parameters.<count>is a count of the arguments that follow within the block, not a count of parameters.Kis the number of nearest neighbors to retrieve, between 1 and 10000, and defaults to 10. Omitting the whole block, or writingKNN 0, is the same as taking every default.EF_RUNTIMEtunes the HNSW search breadth.SHARD_K_RATIOis accepted for compatibility and ignored.FILTER [<count>] <expression> [POLICY ...](optional): Restricts which documents the vector search considers. The filter decides membership only; this arm's score remains the vector distance. WithoutPOLICY, the existing count-optional form remains supported. A policy must be inside a counted FILTER block, where<count>includes the expression and every policy token.POLICY ADHOCforces exact filter-first execution.POLICY BATCHESforces vector-search-first execution with inline filtering. A wildcard expression (FILTER 3 * POLICY ...) has no restriction to apply, so both policies use standard unfiltered KNN, matching Redis. Policy values are literal command tokens, notPARAMSreferences.EF_RUNTIMEis rejected withADHOCand accepted withBATCHES.BATCH_SIZE <n>is accepted only afterPOLICY BATCHES; its value remains unsupported and is ignored. See Search - query languageYIELD_SCORE_AS <alias>(optional): As for theSEARCHarm.
COMBINE(optional): How the two arms' results are fused. Defaults toRRFwith its own defaults when the clause is absent. In every form,<count>is a count of the arguments that follow within the clause, not a count of sub-arguments; sub-arguments may appear in any order. See Fusion methods below.DIALECT <dialect>(optional): Specifies your dialect. The only supported dialect is 2.LOAD * | LOAD <count> <field> [AS <alias>] [...](optional): Which fields of the matched keys are loaded into the working set, exactly as forFT.AGGREGATE. Without aLOADclause the result carries the key, the fused score, and any per-arm scores that were named.AS <alias>requiressearch.emulate-releaseto be at least1.3.0; below that theASkeyword is read as another field name and the load fails.PARAMS <count> <name> <value> [...](optional):<count>is the number of arguments, i.e. twice the number of name/value pairs. Used to supply theVSIMquery vector. A$namereference inside either arm's query text is not substituted — the same limitationFT.SEARCHandFT.AGGREGATEhave.TIMEOUT <timeout>(optional): A timeout for the command, in milliseconds, between 1 and 60000.WITHCURSOR [COUNT <count>] [MAXIDLE <maxidle>](optional): Returns at most<count>records and saves the remaining records in a cursor, which is read withFT.CURSOR, exactly as forFT.AGGREGATE.<count>must be between 1 andsearch.cursor-max-count, the default is 1000.<maxidle>is the number of milliseconds the cursor may go unread before it is destroyed; it must be between 1 andsearch.cursor-max-idle-ms, the default is 300000.WITHCURSORmay appear anywhere among the clauses that followSEARCH,VSIMandCOMBINE, and ends any of those three clauses the wayLOADdoes. If it is given more than once, the last one is used. A cursor is no exception to the cancellation rules: a query cancelled by itsTIMEOUTis an error, as it is withoutWITHCURSOR.APPLY,FILTER,GROUPBY,LIMIT,SORTBY(optional): TheFT.AGGREGATEprocessing stages, applied to the fused list in the order written. See FT.AGGREGATE for what each stage does.
Result
The output is an array. The first element is a scalar that repeats the number of records returned and carries no other information — in particular it is not the total number of matches. The remainder is one element per record.
Each record is an array of field/value pairs. Without a LOAD clause every record carries __key and the fused score, under __score or under the alias given by COMBINE ... YIELD_SCORE_AS. A LOAD clause replaces those two implicit columns with the fields it names: load @__key to keep the key, and name the fused score with COMBINE ... YIELD_SCORE_AS to keep it. Per-arm scores appear under their own YIELD_SCORE_AS aliases either way.
If WITHCURSOR is specified the output is a two element array, as for FT.AGGREGATE. The first element is an array whose first element is the number of records returned, followed by one element for each returned record. The second element is the cursor id to pass to FT.CURSOR READ, or 0 if all records were returned, in which case no cursor is created. The cursor pages through the records the command would have returned without WITHCURSOR, so the default LIMIT of 10 described below still applies.
Unlike FT.AGGREGATE, which returns every record, FT.HYBRID returns at most 10 records when the command writes no LIMIT clause. An explicit LIMIT stays where it is written in the pipeline; only the default is appended, so it runs after every other stage.
Fusion methods
Fusion sees each arm's results ranked best-first, and every arm's score in the same direction: higher is better. The VSIM arm's distance is converted to a similarity before fusion, so a nearer document scores higher.
RRF
COMBINE RRF <count> [CONSTANT <c>] [WINDOW <w>] [YIELD_SCORE_AS <alias>]
Reciprocal Rank Fusion scores a document by its rank in each arm rather than by the arm's score, which makes it insensitive to the two arms producing scores on entirely different scales. A document at rank r in an arm contributes 1 / (c + r + 1), and the contributions from both arms are summed.
CONSTANT <c>(optional, default60): Thecabove. A larger constant flattens the difference between ranks. Must be a non-negative finite number; fractional values are honored.WINDOW <w>(optional, default20): How many of each arm's top results take part in fusion.
This is the default method: a command with no COMBINE clause fuses with RRF using these defaults.
LINEAR
COMBINE LINEAR <count> [ALPHA <a> BETA <b>] [WINDOW <w>] [YIELD_SCORE_AS <alias>]
A weighted sum of the arms' raw scores: a * search_score + b * vector_similarity. A document absent from an arm contributes nothing from it.
ALPHA <a>(optional, default0.3): The weight applied to theSEARCHarm.BETA <b>(optional, default0.7): The weight applied to theVSIMarm.WINDOW <w>(optional, default20): As forRRF.
The two weights are optional together, not individually. Writing neither takes the defaults above, so COMBINE LINEAR 0 fuses exactly as COMBINE LINEAR 4 ALPHA 0.3 BETA 0.7 does. Writing exactly one is an error: the other is not defaulted for it, because a half-written pair is much more likely to be a typo than a request for a default.
Any finite value is accepted, including negative values and values greater than 1.
The scores are used as they stand, with no per-arm normalization. Normalizing would make a document's fused score depend on which other documents happened to come back in the same arm, so the same document against the same query would score differently as the corpus around it changed. Use ALPHA and BETA to balance the arms instead.
FUNCTION
COMBINE FUNCTION <count> EXPR <expression> [WINDOW <w>] [YIELD_SCORE_AS <alias>]
The fused score is whatever your expression computes from the arms' scores. This is a valkey-search extension.
EXPR <expression>(required): An expression over the per-arm scores. See Search - expressions for the syntax.WINDOW <w>(optional): Defaults to the widest window allowed rather than to 20, because a user expression is normally expected to see every candidate.
Each arm's score is reachable from the expression three ways: by the arm's own YIELD_SCORE_AS alias, by position as @__arm0_score and @__arm1_score, and — for the standard two-arm shape — as @__search_score and @__vector_score.
FT.HYBRID idx
SEARCH "@title:running shoes" YIELD_SCORE_AS s
VSIM @embedding $q KNN 2 K 10 YIELD_SCORE_AS v
COMBINE FUNCTION 4 EXPR "@s * 10 + @v" YIELD_SCORE_AS score
PARAMS 2 q <blob>
An arm that did not return a given document has no score for it, and an expression that reads a missing arm score evaluates to 0 for that document as a whole — not merely for that term. @v * 0 + 100 yields 0, not 100, for a document the vector arm did not return. Guard with exists(@alias), which is 0 for a missing score and 1 otherwise, if such a document should keep a non-zero fused score.
WINDOW
WINDOW bounds how many of each arm's top results take part in fusion. It is a per-arm count, so with two arms the fused list can hold up to twice the window before the processing stages run.
WINDOW 0 means "as wide as allowed" and resolves to the ceiling set by the search.max-combine-window configuration, which defaults to 1,000,000. Values above that ceiling are rejected.
The ceiling bounds a window the command asks for, and the window FUNCTION takes when it asks for none. It does not clamp the RRF and LINEAR default of 20: lowering the configuration below 20 rejects an explicit WINDOW 20 while leaving the default untouched.
Score naming
The fused score is emitted under __score unless COMBINE ... YIELD_SCORE_AS names it otherwise.
__key is reserved and cannot be used as a score alias anywhere.
__score cannot be used by COMBINE ... YIELD_SCORE_AS when the command has no LOAD clause, because that is already the name of the default score column; give the score a different name, or add a LOAD clause. A per-arm YIELD_SCORE_AS cannot use __score at all, with or without a LOAD clause, since it would collide with the fused score's own column.
Notes
VSIM RANGEis not implemented. The clause parses, so a command written for another engine is checked rather than misread, but executing one returns an error. UseKNN.POLICYis active inside a counted VSIMFILTER.ADHOCforces exact filter-first execution andBATCHESforces vector-search-first execution with inline filtering. Other values, duplicate declarations, and placement outside the counted FILTER block are rejected.BATCH_SIZEis accepted but ignored. It is valid only afterPOLICY BATCHES; fixed-size batch iteration is tracked separately.NOCONTENTis rejected.FT.HYBRIDalways returns records; a query wanting keys only can ask for noLOADclause.FT.HYBRIDcannot run insideMULTI/EXECor a Lua script, and is unavailable when the reader thread pool is disabled. All three force synchronous execution, which cannot revalidate the two arms' results against concurrent writes.
ft.info
The FT.INFO command provides information about an index. Variants of the command are available in cluster mode to aggregate index information across the cluster.
FT.INFO <index-name>
[LOCAL | PRIMARY | CLUSTER]
[ALLSHARDS | SOMESHARDS]
[CONSISTENT | INCONSISTENT]
-
<index-name>(required): The name of the index to return information about. -
LOCAL(optional): Only the executing (local) node provides index information. This is the default. -
PRIMARY(optional): The primary nodes of every shard in the cluster are queried to generate index information. This is only valid when cluster mode is enabled. -
CLUSTER(optional): All nodes, primary or replica, are queried to generate index information. This is only valid when cluster mode is enabled. -
ALLSHARDS(optional): If specified, a response is required from every shard in the system. If all responses are not received within a time window the command is terminated with an error. This is the default. -
SOMESHARDS(optional): If specified, a response is NOT required from every shard in the system. If all responses are not received within the time window, only the received responses are returned and no error is generated. -
CONSISTENT(optional): If specified, the command is terminated with an error if any received response isn't from a consistent version of the index. This is the default. -
INCONSISTENT(optional): If specified, a command result is generated using only the responses from nodes with a consistent version of the index.
RESPONSE
Response when LOCAL is specified
The LOCAL response contains both the definition of the index as well as the status of that index on the node that executes the command.
An array of key value pairs.
-
index_name(string) The index name -
index_definition(an array of key/value pairs)key_type(string)HASHorJSONprefixes(array of strings) The declared prefixes for this indexfilter(string) The index'sFILTERexpression. Only present when the index was created withFILTER.default_score(double) The index's configuredSCOREvaluescore_field(string) The index's configuredSCORE_FIELD, or an empty string if none
The two fields above require
search.emulate-releaseto be1.3.0or later. Below that — including at the default setting —index_definitionomitsscore_fieldand reportsdefault_scoreas the bulk string"1". See COMPATIBILITY.md. -
attributes(array of arrays) One entry per declared attribute of the index.identifier(string) identifier for this attributeattribute(string) The name used to refer to this index in query and aggregation expressions.user_indexed_memory(integer) Number of bytes of user data ingested into this field.type(string) One ofNUMERIC,TAG,TEXTorVECTOR- Type-specific extension (see below)
SORTABLE(string)1if the attribute was declaredSORTABLE,0otherwise. Not reported forVECTORattributes, which cannot be declaredSORTABLE. RediSearch reports this as a bare token present only when declared.UNF(string)1if the attribute was declaredSORTABLE UNF,0otherwise. Reported only forTAGandTEXTattributes, the only types whose sort value is normalized. RediSearch reports this as a bare token present only when declared.
-
num_docs(integer) Total keys in the index -
num_records(integer) Total number of fields indexed. -
total_term_occurrences(integer) Total number of terms in all text fields in this index. -
num_terms(integer) Total number of unique terms in all text fields in this index. -
hash_indexing_failures(string) INTEGER. Count of unsuccessful indexing attempts -
filter_rejected_keys(string) INTEGER. Number of filter-rejection events: each time a key is evaluated against the indexFILTERexpression and does not satisfy it, the count increases by one. A key can be rejected more than once (for example, when it is rewritten, or when it is written while the initial backfill is in progress), so this is not a count of distinct keys. For aHASHindex aFILTERmay reference a field that is not declared in the schema, in which case the field is read directly off the key; a misspelled field name therefore does not fail the command but instead behaves as a missing field. Afilter_rejected_keysvalue that unexpectedly matches, nearly matches, or exceeds the number of ingested keys is the primary signal that a field name in theFILTERexpression is misspelled. -
backfill_in_progress(string). "1" if a backfill is currently running. "0" if not. -
backfill_complete_percent(string) Estimated progress of background indexing. Percentage is expressed as a fractional value from 0 to 1.0. -
mutation_queue_size(string) Number of keys contained in the mutation queue. -
recent_mutations_queue_delay(string)0 secif the mutation queue is empty. Otherwise it is the elapsed time, from scheduling through completion of processing, recorded by the last sampled mutation to update this statistic, in whole seconds rounded down, in the form<seconds> sec. One in every 1000 scheduled mutations is sampled; mutations processed inline are not sampled. -
state(string) Current backfill state.readyindicates not backfill is in progress.backfill_in_progressbackfill operation proceeding normally.backfill_paused_by_oombackfill is paused because the Valkey instance is out of memory.
The following four fields are only present when the index has at least one TEXT attribute.
punctuation(string) list of punctuation characters.stop_words(array of strings) list of stop words. Empty if the index was created withNOSTOPWORDS.with_offsets(string) "1" if offsets are included. "0" if offsets are not includedmin_stem_size(integer) Minimum stemming size for this index.
The following field is always present:
language(string) The index'sLANGUAGE, reported in lowercase (for example,english).englishif the index was created withoutLANGUAGE.
NUMERIC Field Type Extension
size(string) INTEGER. Number of keys that have this numeric attribute present.
TAG Field Type Extension
SEPARATOR(string) The actual separator character.CASESENSITIVE(string) "0" or "1".size(string) INTEGER. Number of keys that have this tag attribute present.
TEXT Field Type Extension
WITH_SUFFIX_TRIE(string) "0" or "1".NO_STEM(string) "0" or "1".WEIGHT(string) The attribute'sWEIGHT. Currently always "1".
VECTOR Field Type Extension
index(array)capacity(integer) The current capacity for the total number of vectors that the index can store.dimensions(integer) Dimension countdistance_metric(string) Possible values areL2,IPorCOSINEsize(string) INTEGER. Number of valid vectors for this attributedata_type(string) Element data type of the vector. Possible values areFLOAT32,FLOAT16orBFLOAT16algorithm(array of key/value pairs) Extended information about the vector indexing algorithm for this attribute.
FLAT VECTOR Field Type Extension.
name(string)FLAT.block_size(number) block size for this attribute.
HNSW VECTOR Field Type Extension.
name(string)HNSW.m(integer) The count of maximum permitted outgoing edges for each node in the graph in each layer. The maximum number of outgoing edges is 2*M for layer 0. The Default is 16. The maximum is 512.ef_construction(integer) The count of vectors in the index. The default is 200, and the max is 4096. Higher values increase the time needed to create indexes, but improve the recall ratio.ef_runtime(integer) The count of vectors to be examined during a query operation. The default is 10, and the max is 4096.
Response when the PRIMARY option is specified.
An array of key value pairs
Totals are summed over the primaries that responded. With SOMESHARDS, a primary that does not respond is omitted, so totals may be lower than the full cluster's.
Inside MULTI/EXEC or a Lua script, no other nodes are queried and the LOCAL response is returned instead.
mode(string) Will have the valueprimary.index_name(string) The index namenum_docs(string) INTEGER. Total keys in the indexnum_records(string) INTEGER. Total records in the indexhash_indexing_failures(string) INTEGER. Count of unsuccessful indexing attemptsattributes(array of arrays) One entry per declared attribute of the index.identifier(string) identifier for this attributeattribute(string) The name used to refer to this index in query and aggregation expressions.user_indexed_memory(integer) Number of bytes of user data ingested into this field, summed across the primaries.num_records(integer) Number of records indexed for this attribute, summed across the primaries.
index_fingerprint(integer) Fingerprint of the index definition on the node that executes the command. Only present whensearch.info-developer-visibleisyes; intended for debugging.index_version(integer) Version of the index definition on the node that executes the command. Only present whensearch.info-developer-visibleisyes; intended for debugging.
Response when the CLUSTER option is specified
An array of key value pairs
Totals, minimums and maximums are computed over the nodes that responded. With SOMESHARDS, a node that does not respond is omitted, so totals may be lower than the full cluster's.
Inside MULTI/EXEC or a Lua script, no other nodes are queried and the LOCAL response is returned instead.
mode(string) Will have the valuecluster.index_name(string) The index namebackfill_in_progress(string) 0 or 1. Is backfill in progressbackfill_complete_percent_max(string) FLOAT32. Maximum backfill complete percent in all nodesbackfill_complete_percent_min(string) FLOAT32. Minimum backfill complete percent in all nodesstate(string) The current state of the index, one of:ready,backfill_in_progressorbackfill_paused_by_oomattributes(array of arrays) One entry per declared attribute of the index.identifier(string) identifier for this attributeattribute(string) The name used to refer to this index in query and aggregation expressions.user_indexed_memory(integer) Number of bytes of user data ingested into this field, summed across all nodes, primaries and replicas.
ft.search
Performs a search of the specified index. The keys which match the query expression are returned.
FT.SEARCH <index> <query>
[ALLSHARDS | SOMESHARDS]
[CONSISTENT | INCONSISTENT]
[DIALECT <dialect>]
[INKEYS <count> <key> [<key> ...]]
[INORDER]
[LIMIT <offset> <num>]
[NOCONTENT]
[PARAMS <count> <name> <value> [ <name> <value> ...]]
[RETURN <count> <field> [AS <name>] <field> [AS <name>]...]
[SCORER <scorer>]
[SLOP <slop>]
[SORTBY <field> [ ASC | DESC]]
[TIMEOUT <timeout>]
[VERBATIM]
[WITHCURSOR [COUNT <count>] [MAXIDLE <maxidle>]]
[WITHSCORES]
[WITHSORTKEYS]
<index>(required): This index name you want to query.<query>(required): The query string, see Search - query language for details.ALLSHARDS(Optional): If specified, the command is terminated with a timeout error if a valid response from all shards is not received within the timeout interval. This is the default whensearch.enable-partial-resultsisno; otherwiseSOMESHARDSis the default.CONSISTENT(Optional): If specified, the command is terminated with an error if the cluster is in an inconsistent state. This is the default whensearch.enable-consistent-resultsisyes; otherwiseINCONSISTENTis the default.DIALECT <dialect>(optional): Specifies your dialect. The only supported dialect is 2.INCONSISTENT(Optional): If specified, the command will generate a best-effort reply if the cluster remains inconsistent within the timeout interval.INKEYS <count> <key> [<key> ...](optional): Restricts results to the specified set of document keys.<count>is the number of keys that follow and must be a non-negative integer. Duplicate keys are deduplicated. If<count>is 0, no results are returned. The filter is applied as a post-filter after the search, sototal_countin the response reflects only the keys that matched both the query and the INKEYS set.LIMIT <offset> <count>(optional): Lets you choose a portion of the result. The first<offset>keys are skipped and only a maximum of<count>keys are included. The default is LIMIT 0 10, which returns at most 10 keys.NOCONTENT(optional): When present, only the resulting key names are returned, no key values are included.PARAMS <count> <name> <value> [<name> <value> ...](optional):countis of the number of arguments, i.e., twice the number of value/name pairs. Search - query language for details.RETURN <count> <field> [AS <name>] <field> [AS <name>] ...(options):countis the number of fields to return. Specifies the fields you want to retrieve from your documents, along with any renaming for the returned values. By default, all fields are returned unless theNOCONTENToption is set, in which case no fields are returned. If num is set to 0, it behaves the same asNOCONTENT.INORDER(optional): Indicates that proximity matching of text terms in the query must be in order.SLOP <slop>(Optional): Specifies a slop value for proximity matching of text terms in the query.VERBATIM(Optional): If specified, stemming is not applied to text terms in the query.SOMESHARDS(Optional): If specified, the command will generate a best-effort reply if all shards have not responded within the timeout interval.SORTBY <field> [ASC | DESC](Optional): If present, results are sorted according the value of the specified field and the optional sort-direction instruction. By default, KNN results are sorted in distance order and other results are not sorted in any particular order. Sorting is applied before theLIMITclause is applied.TIMEOUT <timeout>(optional): Lets you set a timeout value for the search command. This must be an integer in milliseconds.SCORER <scorer>(Optional): Selects the relevance scoring function used to rank text results.WITHCURSOR [COUNT <count>] [MAXIDLE <maxidle>](Optional): Returns at most<count>of the keys selected by theLIMITclause and saves the remaining keys in a cursor, which is read withFT.CURSOR.<count>must be between 1 andsearch.cursor-max-count, the default is 1000.<maxidle>is the number of milliseconds the cursor may go unread before it is destroyed; it must be between 1 andsearch.cursor-max-idle-ms, the default is 300000. If it is given more than once, the last one is used. This option is a Valkey extension.WITHSCORES(Optional): Augments the output with the relevance score computed for each returned key.WITHSORTKEYS(Optional): IfSORTBYis specified then enabling this option augments the output with the value of the field used for sorting.
Response
The shape and contents of the response depend on the options specified in the command.
In all cases, the response is an array with the first element being a count of the number of keys which match the query.
The value of this count is unaffected by the presence of the LIMIT clause.
The LIMIT clause trims the list of matched keys to generate a list of returned keys. The remainder of the response array is for the returned keys.
NOCONTENT or RETURN 0 was specified.
The remainder of the response array is one entry per returned key, consisting of the key name.
RETURN with arguments was specified.
The remainder of the response array is two entries per returned key. The first entry is the key name and
the second entry is an array of name/value pairs. The array of name/value pairs is driven by the RETURN clause.
Each of the named fields in the RETURN clause is returned along with the value of that field for this particular key. If the named field isn't present in this key then it won't be included.
In addition, if this is a vector search, then one additional name/value pair will be included which is the computed vector distance for this returned key -- see Search - query language for details on how to control the name of that field.
For a vector range query, the distance is included only if the query names it with $YIELD_DISTANCE_AS and the RETURN clause lists that name.
Neither NOCONTENT nor RETURN was specified.
If the index is on HASH keys, then the result is the same as if a RETURN clause had been present that listed all of the fields of a key.
If the index is on JSON keys, then one name/value pair is inserted with name $ and the value being the entire JSON key as a string.
In addition, if this is a vector search, then one additional name/value pair will be included which is the computed vector distance for this returned key -- see Search - query language for details on how to control the name of that field.
For a vector range query, the distance is included only if the query names it with $YIELD_DISTANCE_AS.
WITHCURSOR was specified.
The response is a three element array:
- The count of the number of keys which match the query, as above.
- An array with one element per returned key. Each element is an array holding the entries for that key described above, e.g. the key name and its array of name/value pairs.
- The cursor id to pass to
FT.CURSOR READ, or 0 if all keys were returned, in which case no cursor is created.
Examples
Non-vector Queries On Hash Index
For these queries the following index and data definitions were used:
FT.CREATE index on hash SCHEMA color TAG city TAG
hset key1 color blue city London
hset key2 color black city Paris
hset key3 color green city Berlin
hset key4 color white city Tokyo
hset key5 color blend
A simple query returning all data of matched keys
FT.SEARCH index @color:{bl*}
1) (integer) 3
2) "key1"
3) 1) "city"
2) "London"
3) "color"
4) "blue"
4) "key5"
5) 1) "color"
2) "blend"
3) "cityextra"
4) "Unknown"
6) "key2"
7) 1) "city"
2) "Paris"
3) "color"
4) "black"
The same query with the NOCONTENT clause.
FT.SEARCH index @color:{bl*} NOCONTENT
1) (integer) 3
2) "key1"
3) "key5"
4) "key2"
The same query with a RETURN clause.
FT.SEARCH index @color:{bl*} RETURN 2 color city
1) (integer) 3
2) "key1"
3) 1) "color"
2) "blue"
3) "city"
4) "London"
4) "key5"
5) 1) "color"
2) "blend"
6) "key2"
7) 1) "color"
2) "black"
3) "city"
4) "Paris"
Non-vector Queries On JSON Index
Repeating the queries above, except the data is JSON
FT.CREATE index on json SCHEMA $.color as color TAG $.city as city TAG
json.set key1 . {"color":"blue","city":"London"}
json.set key2 . {"color":"black","city":"Paris"}
json.set key3 . {"color":"green","city":"Berlin"}
json.set key4 . {"color":"white","city":"Tokyo"}
json.set key5 . {"color":"blend","cityextra":"Unknown"}
A simple query returning all data of matched keys
FT.SEARCH index @color:{bl*}
1) (integer) 3
2) "key2"
3) 1) "$"
2) "{\"color\":\"black\",\"city\":\"Paris\"}"
4) "key5"
5) 1) "$"
2) "{\"color\":\"blend\",\"cityextra\":\"Unknown\"}"
6) "key1"
7) 1) "$"
2) "{\"color\":\"blue\",\"city\":\"London\"}"
The same query with NOCONTENT
FT.SEARCH index @color:{bl*} NOCONTENT
1) (integer) 3
2) "key2"
3) "key5"
4) "key1"
The same query with a RETURN clause.
FT.SEARCH index @color:{bl*} RETURN 2 color city
1) (integer) 3
2) "key2"
3) 1) "color"
2) "black"
3) "city"
4) "Paris"
4) "key5"
5) 1) "color"
2) "blend"
6) "key1"
7) 1) "color"
2) "blue"
3) "city"
4) "London"
Pure vector search query
For this example, assume we're building a property searching index where customers can search properties based on some features. Assume we have a list of properties with the following attributes:
- Description - vector embedding for given property.
- Other fields - each property can have other metadata as well. However, for simplicity, other fields are ignored in this example.
At first, we create an HNSW index with the description as a vector field using the FT.CREATE command:
FT.CREATE idx SCHEMA description VECTOR HNSW 6 TYPE FLOAT32 DIM 3 DISTANCE_METRIC L2
Now we can insert a few properties (this can be done prior to index creation as well) using the HSET command:
HSET p1 description "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80?"
HSET p2 description "\x00\x00\x00\x00\x00\x00\x80?\x00\x00\x00\x00"
HSET p3 description "\x00\x00\x80?\x00\x00\x00\x00\x00\x00\x00\x00"
HSET p4 description "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80?"
HSET p5 description "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80?"
Now we can perform queries using the FT.SEARCH command. The following query returns up to five of the most similar
properties to the provided query vector:
FT.SEARCH idx "*=>[KNN 5 @description $query_vector]" PARAMS 2 query_vector "\xcd\xccL?\x00\x00\x00\x00\x00\x00\x00\x00" DIALECT 2
Returned result:
1) (integer) 5
2) p5
3) 1) __description_score
2) 1.6400001049
3) description
4) \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80?
4) p4
5) 1) __description_score
2) 1.6400001049
3) description
4) \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80?
6) p2
7) 1) __description_score
2) 1.6400001049
3) description
4) \x00\x00\x00\x00\x00\x00\x80?\x00\x00\x00\x00
8) p1
9) 1) __description_score
2) 1.6400001049
3) description
4) \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80?
10) p3
11) 1) __description_score
2) 0.0399999953806
3) description
4) \x00\x00\x80?\x00\x00\x00\x00\x00\x00\x00\x00
Query On JSON Index without RETURN clause
Simple query showing the JSON output
Simple Query with RETURN Clause
Simple query showing selecting return of additional fields
Query showing NOCONTENT
Query showing SORTBY
function-delete
Delete a library and all its functions.
This command deletes the library called library-name and all functions in it. If the library doesn't exist, the server returns an error.
For more information please refer to Introduction to Valkey Functions.
Examples
127.0.0.1:6379> FUNCTION LOAD "#!lua name=mylib \n server.register_function('myfunc', function(keys, args) return 'hello' end)"
"mylib"
127.0.0.1:6379> FCALL myfunc 0
"hello"
127.0.0.1:6379> FUNCTION DELETE mylib
OK
127.0.0.1:6379> FCALL myfunc 0
(error) ERR Function not found
function-dump
Return the serialized payload of loaded libraries.
You can restore the serialized payload later with the FUNCTION RESTORE command.
For more information please refer to Introduction to Valkey Functions.
Examples
The following example shows how to dump loaded libraries using FUNCTION DUMP and then it calls FUNCTION FLUSH deletes all the libraries.
Then, it restores the original libraries from the serialized payload with FUNCTION RESTORE.
127.0.0.1:6379> FUNCTION LOAD "#!lua name=mylib \n server.register_function('myfunc', function(keys, args) return args[1] end)"
"mylib"
127.0.0.1:6379> FUNCTION DUMP
"\xf5\xc3@X@]\x1f#!lua name=mylib \n server.registe\rr_function('my@\x0b\x02', @\x06`\x12\nkeys, args) 6\x03turn`\x0c\a[1] end)\x0c\x00\xba\x98\xc2\xa2\x13\x0e$\a"
127.0.0.1:6379> FUNCTION FLUSH
OK
127.0.0.1:6379> FUNCTION RESTORE "\xf5\xc3@X@]\x1f#!lua name=mylib \n server.registe\rr_function('my@\x0b\x02', @\x06`\x12\nkeys, args) 6\x03turn`\x0c\a[1] end)\x0c\x00\xba\x98\xc2\xa2\x13\x0e$\a"
OK
127.0.0.1:6379> FUNCTION LIST
1) 1) "library_name"
2) "mylib"
3) "engine"
4) "LUA"
5) "functions"
6) 1) 1) "name"
2) "myfunc"
3) "description"
4) (nil)
5) "flags"
6) (empty array)
function-flush
Deletes all the libraries.
Unless called with the optional mode argument, the lazyfree-lazy-user-flush configuration directive sets the effective behavior. Valid modes are:
ASYNC: Asynchronously flush the libraries.!SYNC: Synchronously flush the libraries.
For more information please refer to Introduction to Valkey Functions.
function-help
The FUNCTION HELP command returns a helpful text describing the different subcommands.
function-kill
Kill a function that is currently executing.
The FUNCTION KILL command can be used only on functions that did not modify the dataset during their execution (since stopping a read-only function does not violate the scripting engine's guaranteed atomicity).
For more information please refer to Introduction to Valkey Functions.
function-list
Return information about the functions and libraries.
You can use the optional LIBRARYNAME argument to specify a pattern for matching library names.
The optional WITHCODE modifier will cause the server to include the libraries source implementation in the reply.
The following information is provided for each of the libraries in the response:
- library_name: the name of the library.
- engine: the engine of the library.
- functions: the list of functions in the library.
Each function has the following fields:
- name: the name of the function.
- description: the function's description.
- flags: an array of function flags.
- library_code: the library's source code (when given the
WITHCODEmodifier).
For more information please refer to Introduction to Valkey Functions.
function-load
Load a library to Valkey.
The command receives a single mandatory parameter which is the source code that implements the library.
The library payload must start with Shebang statement that provides a metadata about the library (like the engine to use and the library name).
Shebang format: #!<engine name> name=<library name>. Currently engine name must be lua.
For the Lua engine, the implementation should declare one or more entry points to the library with the server.register_function() API.
Once loaded, you can call the functions in the library with the FCALL (or FCALL_RO when applicable) command.
When attempting to load a library with a name that already exists, the Valkey server returns an error.
The REPLACE modifier changes this behavior and overwrites the existing library with the new contents.
The command will return an error in the following circumstances:
- An invalid engine-name was provided.
- The library's name already exists without the
REPLACEmodifier. - A function in the library is created with a name that already exists in another library (even when
REPLACEis specified). - The engine failed in creating the library's functions (due to a compilation error, for example).
- No functions were declared by the library.
For more information please refer to Introduction to Valkey Functions.
Examples
The following example will create a library named mylib with a single function, myfunc, that returns the first argument it gets.
127.0.0.1:6379> FUNCTION LOAD "#!lua name=mylib \n server.register_function('myfunc', function(keys, args) return args[1] end)"
mylib
127.0.0.1:6379> FCALL myfunc 0 hello
"hello"
function-restore
Restore libraries from the serialized payload.
You can use the optional policy argument to provide a policy for handling existing libraries. The following policies are allowed:
- APPEND: appends the restored libraries to the existing libraries and aborts on collision. This is the default policy.
- FLUSH: deletes all existing libraries before restoring the payload.
- REPLACE: appends the restored libraries to the existing libraries, replacing any existing ones in case of name collisions. Note that this policy doesn't prevent function name collisions, only libraries.
For more information please refer to Introduction to Valkey Functions.
function-stats
Return information about the function that's currently running and information about the available execution engines.
The reply is map with two keys:
running_script: information about the running script. If there's no in-flight function, the server replies with a nil. Otherwise, this is a map with the following keys:
- name: the name of the function.
- command: the command and arguments used for invoking the function.
- duration_ms: the function's runtime duration in milliseconds.
engines: this is a map of maps. Each entry in the map represent a single engine. Engine map contains statistics about the engine like number of functions and number of libraries.
You can use this command to inspect the invocation of a long-running function and decide whether kill it with the FUNCTION KILL command.
For more information please refer to Introduction to Valkey Functions.
function
This is a container command for function commands.
To see the list of available commands you can call FUNCTION HELP.
geoadd
Adds the specified geospatial items (longitude, latitude, name) to the specified key. Data is stored into the key as a sorted set, in a way that makes it possible to query the items with the GEOSEARCH command.
The command takes arguments in the standard format x,y so the longitude must be specified before the latitude. There are limits to the coordinates that can be indexed: areas very near to the poles are not indexable.
The exact limits, as specified by EPSG:900913 / EPSG:3785 / OSGEO:41001 are the following:
- Valid longitudes are from -180 to 180 degrees.
- Valid latitudes are from -85.05112878 to 85.05112878 degrees.
The command will report an error when the user attempts to index coordinates outside the specified ranges.
Note: there is no GEODEL command because you can use ZREM to remove elements. The Geo index structure is just a sorted set.
GEOADD options
GEOADD also provides the following options:
- XX: Only update elements that already exist. Never add elements.
- NX: Don't update already existing elements. Always add new elements.
- CH: Modify the return value from the number of new elements added, to the total number of elements changed (CH is an abbreviation of changed). Changed elements are new elements added and elements already existing for which the coordinates was updated. So elements specified in the command line having the same score as they had in the past are not counted. Note: normally, the return value of
GEOADDonly counts the number of new elements added.
Note: The XX and NX options are mutually exclusive.
How does it work?
The way the sorted set is populated is using a technique called Geohash. Latitude and Longitude bits are interleaved to form a unique 52-bit integer. We know that a sorted set double score can represent a 52-bit integer without losing precision.
This format allows for bounding box and radius querying by checking the 1+8 areas needed to cover the whole shape and discarding elements outside it. The areas are checked by calculating the range of the box covered, removing enough bits from the less significant part of the sorted set score, and computing the score range to query in the sorted set for each area.
What Earth model does it use?
The model assumes that the Earth is a sphere since it uses the Haversine formula to calculate distance. This formula is only an approximation when applied to the Earth, which is not a perfect sphere. The introduced errors are not an issue when used, for example, by social networks and similar applications requiring this type of querying. However, in the worst case, the error may be up to 0.5%, so you may want to consider other systems for error-critical applications.
Examples
127.0.0.1:6379> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
127.0.0.1:6379> GEODIST Sicily Palermo Catania
"166274.1516"
127.0.0.1:6379> GEORADIUS Sicily 15 37 100 km
1) "Catania"
127.0.0.1:6379> GEORADIUS Sicily 15 37 200 km
1) "Palermo"
2) "Catania"
geodist
Return the distance between two members in the geospatial index represented by the sorted set.
Given a sorted set representing a geospatial index, populated using the GEOADD command, the command returns the distance between the two specified members in the specified unit.
If one or both the members are missing, the command returns NULL.
The unit must be one of the following, and defaults to meters:
- m for meters.
- km for kilometers.
- mi for miles.
- ft for feet.
The distance is computed assuming that the Earth is a perfect sphere, so errors up to 0.5% are possible in edge cases.
Examples
127.0.0.1:6379> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
127.0.0.1:6379> GEODIST Sicily Palermo Catania
"166274.1516"
127.0.0.1:6379> GEODIST Sicily Palermo Catania km
"166.2742"
127.0.0.1:6379> GEODIST Sicily Palermo Catania mi
"103.3182"
127.0.0.1:6379> GEODIST Sicily Foo Bar
(nil)
geohash
Return valid Geohash strings representing the position of one or more elements in a sorted set value representing a geospatial index (where elements were added using GEOADD).
Normally Valkey represents positions of elements using a variation of the Geohash technique where positions are encoded using 52 bit integers. The encoding is also different compared to the standard because the initial min and max coordinates used during the encoding and decoding process are different. This command however returns a standard Geohash in the form of a string as described in the Wikipedia article and compatible with the geohash.org web site.
Geohash string properties
The command returns 11 characters Geohash strings, so no precision is lost compared to the Valkey internal 52 bit representation. The returned Geohashes have the following properties:
- They can be shortened removing characters from the right. It will lose precision but will still point to the same area.
- It is possible to use them in
geohash.orgURLs such ashttp://geohash.org/<geohash-string>. This is an example of such URL. - Strings with a similar prefix are nearby, but the contrary is not true, it is possible that strings with different prefixes are nearby too.
Examples
127.0.0.1:6379> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
127.0.0.1:6379> GEOHASH Sicily Palermo Catania
1) "sqc8b49rny0"
2) "sqdtr74hyu0"
geopos
Return the positions (longitude,latitude) of all the specified members of the geospatial index represented by the sorted set at key.
Given a sorted set representing a geospatial index, populated using the GEOADD command, it is often useful to obtain back the coordinates of specified members. When the geospatial index is populated via GEOADD the coordinates are converted into a 52 bit geohash, so the coordinates returned may not be exactly the ones used in order to add the elements, but small errors may be introduced.
The command can accept a variable number of arguments so it always returns an array of positions even when a single element is specified.
Examples
127.0.0.1:6379> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
127.0.0.1:6379> GEOPOS Sicily Palermo Catania NonExisting
1) 1) "13.36138933897018433"
2) "38.11555639549629859"
2) 1) "15.08726745843887329"
2) "37.50266842333162032"
3) (nil)
georadius
Return the members of a sorted set populated with geospatial information using GEOADD, which are within the borders of the area specified with the center location and the maximum distance from the center (the radius).
This manual page also covers the GEORADIUS_RO and GEORADIUSBYMEMBER_RO variants (see the section below for more information).
The common use case for this command is to retrieve geospatial items near a specified point not farther than a given amount of meters (or other units). This allows, for example, to suggest mobile users of an application nearby places.
The radius is specified in one of the following units:
- m for meters.
- km for kilometers.
- mi for miles.
- ft for feet.
The command optionally returns additional information using the following options:
WITHDIST: Also return the distance of the returned items from the specified center. The distance is returned in the same unit as the unit specified as the radius argument of the command.WITHCOORD: Also return the longitude,latitude coordinates of the matching items.WITHHASH: Also return the raw geohash-encoded sorted set score of the item, in the form of a 52 bit unsigned integer. This is only useful for low level hacks or debugging and is otherwise of little interest for the general user.
The command default is to return unsorted items. Two different sorting methods can be invoked using the following two options:
ASC: Sort returned items from the nearest to the farthest, relative to the center.DESC: Sort returned items from the farthest to the nearest, relative to the center.
By default all the matching items are returned. It is possible to limit the results to the first N matching items by using the COUNT <count> option.
When ANY is provided the command will return as soon as enough matches are found,
so the results may not be the ones closest to the specified point, but on the other hand, the effort invested by the server is significantly lower.
When ANY is not provided, the command will perform an effort that is proportional to the number of items matching the specified area and sort them,
so to query very large areas with a very small COUNT option may be slow even if just a few results are returned.
By default the command returns the items to the client. It is possible to store the results with one of these options:
STORE: Store the items in a sorted set populated with their geospatial information.STOREDIST: Store the items in a sorted set populated with their distance from the center as a floating point number, in the same unit specified in the radius.
Read-only variants
Since GEORADIUS and GEORADIUSBYMEMBER have a STORE and STOREDIST option they are technically flagged as writing commands in the Valkey command table. For this reason read-only replicas will flag them, and Valkey Cluster replicas will redirect them to the primary instance even if the connection is in read-only mode (see the READONLY command of Valkey Cluster).
Two read-only variants of the commands were added. They are exactly like the original commands but refuse the STORE and STOREDIST options. The two variants are called GEORADIUS_RO and GEORADIUSBYMEMBER_RO, and can safely be used in replicas.
Alternative
GEOSEARCH and GEOSEARCHSTORE with the BYRADIUS argument.
Examples
127.0.0.1:6379> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
127.0.0.1:6379> GEORADIUS Sicily 15 37 200 km WITHDIST
1) 1) "Palermo"
2) "190.4424"
2) 1) "Catania"
2) "56.4413"
127.0.0.1:6379> GEORADIUS Sicily 15 37 200 km WITHCOORD
1) 1) "Palermo"
2) 1) "13.36138933897018433"
2) "38.11555639549629859"
2) 1) "Catania"
2) 1) "15.08726745843887329"
2) "37.50266842333162032"
127.0.0.1:6379> GEORADIUS Sicily 15 37 200 km WITHDIST WITHCOORD
1) 1) "Palermo"
2) "190.4424"
3) 1) "13.36138933897018433"
2) "38.11555639549629859"
2) 1) "Catania"
2) "56.4413"
3) 1) "15.08726745843887329"
2) "37.50266842333162032"
georadius_ro
Read-only variant of the GEORADIUS command.
This command is identical to the GEORADIUS command, except that it doesn't support the optional STORE and STOREDIST parameters.
Alternative
GEOSEARCH with the BYRADIUS argument.
georadiusbymember
This command is exactly like GEORADIUS with the sole difference that instead
of taking, as the center of the area to query, a longitude and latitude value, it takes the name of a member already existing inside the geospatial index represented by the sorted set.
The position of the specified member is used as the center of the query.
Please check the example below and the GEORADIUS documentation for more information about the command and its options.
Note that GEORADIUSBYMEMBER_RO was added to provide a read-only command that can be used in replicas. See the GEORADIUS page for more information.
Alternative
GEOSEARCH and GEOSEARCHSTORE with the BYRADIUS and FROMMEMBER arguments.
Examples
127.0.0.1:6379> GEOADD Sicily 13.583333 37.316667 "Agrigento"
(integer) 1
127.0.0.1:6379> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
127.0.0.1:6379> GEORADIUSBYMEMBER Sicily Agrigento 100 km
1) "Agrigento"
2) "Palermo"
georadiusbymember_ro
Read-only variant of the GEORADIUSBYMEMBER command.
This command is identical to the GEORADIUSBYMEMBER command, except that it doesn't support the optional STORE and STOREDIST parameters.
Alternative
GEOSEARCH with the BYRADIUS and FROMMEMBER arguments.
geosearch
Return the members of a sorted set populated with geospatial information using GEOADD, which are within the borders of the area specified by a given shape. This command extends the GEORADIUS command, so in addition to searching within circular areas, it supports searching within rectangular areas and polygon shaped areas.
This command should be used in place of the deprecated GEORADIUS and GEORADIUSBYMEMBER commands.
The query's shape is provided by one of these mandatory options:
BYRADIUS: Similar toGEORADIUS, search inside circular area according to given<radius>.BYBOX: Search inside an axis-aligned rectangle, determined by<height>and<width>.BYPOLYGON: Search within an area enclosed by the polygon vertices, determined by<num-vertices> <lon> <lat> [<lon> <lat> ...].
For BYBOX and BYRADIUS based queries, the center point is provided by one of these mandatory options:
FROMMEMBER: Use the position of the given existing<member>in the sorted set.FROMLONLAT: Use the given<longitude>and<latitude>position.
In case of BYPOLYGON based queries, the center point and the bounding box are computed based on the polygon vertices of the command.
With this option, providing FROMMEMBER or FROMLONLAT is invalid.
The command optionally returns additional information using the following options:
WITHDIST: Also return the distance of the returned items from the specified center point. The distance is returned in the same unit as specified for the radius or height and width arguments.WITHCOORD: Also return the longitude and latitude of the matching items.WITHHASH: Also return the raw geohash-encoded sorted set score of the item, in the form of a 52 bit unsigned integer. This is only useful for low level hacks or debugging and is otherwise of little interest for the general user.
Matching items are returned unsorted by default. To sort them, use one of the following two options:
ASC: Sort returned items from the nearest to the farthest, relative to the center point.DESC: Sort returned items from the farthest to the nearest, relative to the center point.
All matching items are returned by default. To limit the results to the first N matching items, use the COUNT <count> option.
When the ANY option is used, the command returns as soon as enough matches are found. This means that the results returned may not be the ones closest to the specified point, but the effort invested by the server to generate them is significantly less.
When ANY is not provided, the command will perform an effort that is proportional to the number of items matching the specified area and sort them,
so to query very large areas with a very small COUNT option may be slow even if just a few results are returned.
Examples
127.0.0.1:6379> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
127.0.0.1:6379> GEOADD Sicily 12.758489 38.788135 "edge1" 17.241510 38.788135 "edge2"
(integer) 2
127.0.0.1:6379> GEOSEARCH Sicily FROMLONLAT 15 37 BYRADIUS 200 km ASC
1) "Catania"
2) "Palermo"
127.0.0.1:6379> GEOSEARCH Sicily FROMLONLAT 15 37 BYBOX 400 400 km ASC WITHCOORD WITHDIST
1) 1) "Catania"
2) "56.4413"
3) 1) "15.08726745843887329"
2) "37.50266842333162032"
2) 1) "Palermo"
2) "190.4424"
3) 1) "13.36138933897018433"
2) "38.11555639549629859"
3) 1) "edge2"
2) "279.7403"
3) 1) "17.24151045083999634"
2) "38.78813451624225195"
4) 1) "edge1"
2) "279.7405"
3) 1) "12.7584877610206604"
2) "38.78813451624225195"
127.0.0.1:6379> GEOSEARCH Sicily BYPOLYGON 5 12.41098696654226 38.05033923003755 15.107936245794182 38.00616649901906 18.148439288534455 38.63804787603499 17.80831874257693 39.50316813110968 12.458468633214036 38.57719533463012
1) "Palermo"
2) "edge2"
127.0.0.1:6379> GEOSEARCH Sicily BYPOLYGON 5 12.41098696654226 38.05033923003755 15.107936245794182 38.00616649901906 18.148439288534455 38.63804787603499 17.80831874257693 39.50316813110968 12.458468633214036 38.57719533463012 ASC WITHCOORD WITHDIST
1) 1) "Palermo"
2) "166482.0159"
3) 1) "13.36138933897018433"
2) "38.11555639549629859"
2) 1) "edge2"
2) "180861.7725"
3) 1) "17.24151045083999634"
2) "38.78813451624225195"
geosearchstore
This command is like GEOSEARCH, but stores the result in destination key.
This command replaces the now deprecated GEORADIUS and GEORADIUSBYMEMBER.
By default, it stores the results in the destination sorted set with their geospatial information.
When using the STOREDIST option, the command stores the items in a sorted set populated with their distance from the center of the circle, box or polygon, as a floating-point number, in the same unit specified for that shape.
Examples
127.0.0.1:6379> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
127.0.0.1:6379> GEOADD Sicily 12.758489 38.788135 "edge1" 17.241510 38.788135 "edge2"
(integer) 2
127.0.0.1:6379> GEOSEARCHSTORE key1 Sicily FROMLONLAT 15 37 BYBOX 400 400 km ASC COUNT 3
(integer) 3
127.0.0.1:6379> GEOSEARCH key1 FROMLONLAT 15 37 BYBOX 400 400 km ASC WITHCOORD WITHDIST WITHHASH
1) 1) "Catania"
2) "56.4413"
3) (integer) 3479447370796909
4) 1) "15.08726745843887329"
2) "37.50266842333162032"
2) 1) "Palermo"
2) "190.4424"
3) (integer) 3479099956230698
4) 1) "13.36138933897018433"
2) "38.11555639549629859"
3) 1) "edge2"
2) "279.7403"
3) (integer) 3481342659049484
4) 1) "17.24151045083999634"
2) "38.78813451624225195"
127.0.0.1:6379> GEOSEARCHSTORE key2 Sicily FROMLONLAT 15 37 BYBOX 400 400 km ASC COUNT 3 STOREDIST
(integer) 3
127.0.0.1:6379> ZRANGE key2 0 -1 WITHSCORES
1) "Catania"
2) "56.4412578701582"
3) "Palermo"
4) "190.44242984775784"
5) "edge2"
6) "279.7403417843143"
get
Get the value of key.
If the key does not exist the special value nil is returned.
An error is returned if the value stored at key is not a string, because GET
only handles string values.
Examples
127.0.0.1:6379> GET nonexisting
(nil)
127.0.0.1:6379> SET mykey "Hello"
OK
127.0.0.1:6379> GET mykey
"Hello"
getbit
Returns the bit value at offset in the string value stored at key.
When offset is beyond the string length, the string is assumed to be a contiguous space with 0 bits. When key does not exist it is assumed to be an empty string, so offset is always out of range and the value is also assumed to be a contiguous space with 0 bits.
Examples
127.0.0.1:6379> SETBIT mykey 7 1
(integer) 0
127.0.0.1:6379> GETBIT mykey 0
(integer) 0
127.0.0.1:6379> GETBIT mykey 7
(integer) 1
127.0.0.1:6379> GETBIT mykey 100
(integer) 0
getdel
Get the value of key and delete the key.
This command is similar to GET, except for the fact that it also deletes the key on success (if and only if the key's value type is a string).
Examples
127.0.0.1:6379> SET mykey "Hello"
OK
127.0.0.1:6379> GETDEL mykey
"Hello"
127.0.0.1:6379> GET mykey
(nil)
getex
Get the value of key and optionally set its expiration.
GETEX is similar to GET, but is a write command with additional options.
Options
The GETEX command supports a set of options that modify its behavior:
EXseconds -- Set the specified expire time, in seconds.PXmilliseconds -- Set the specified expire time, in milliseconds.EXATtimestamp-seconds -- Set the specified Unix time at which the key will expire, in seconds.PXATtimestamp-milliseconds -- Set the specified Unix time at which the key will expire, in milliseconds.PERSIST-- Remove the time to live associated with the key.
Examples
127.0.0.1:6379> SET mykey "Hello"
OK
127.0.0.1:6379> GETEX mykey
"Hello"
127.0.0.1:6379> TTL mykey
(integer) -1
127.0.0.1:6379> GETEX mykey EX 60
"Hello"
127.0.0.1:6379> TTL mykey
(integer) 60
getrange
Returns the substring of the string value stored at key, determined by the
offsets start and end (both are inclusive).
Negative offsets can be used in order to provide an offset starting from the end
of the string.
So -1 means the last character, -2 the penultimate and so forth.
The function handles out of range requests by limiting the resulting range to the actual length of the string.
Examples
127.0.0.1:6379> SET mykey "This is a string"
OK
127.0.0.1:6379> GETRANGE mykey 0 3
"This"
127.0.0.1:6379> GETRANGE mykey -3 -1
"ing"
127.0.0.1:6379> GETRANGE mykey 0 -1
"This is a string"
127.0.0.1:6379> GETRANGE mykey 10 100
"string"
getset
Atomically sets key to value and returns the old value stored at key.
Returns an error when key exists but does not hold a string value. Any
previous time to live associated with the key is discarded on successful
SET operation.
Design pattern
GETSET can be used together with INCR for counting with atomic reset.
For example: a process may call INCR against the key mycounter every time
some event occurs, but from time to time we need to get the value of the counter
and reset it to zero atomically.
This can be done using GETSET mycounter "0":
127.0.0.1:6379> INCR mycounter
(integer) 1
127.0.0.1:6379> GETSET mycounter "0"
"1"
127.0.0.1:6379> GET mycounter
"0"
Alternative
SET with the GET argument.
Examples
127.0.0.1:6379> SET mykey "Hello"
OK
127.0.0.1:6379> GETSET mykey "World"
"Hello"
127.0.0.1:6379> GET mykey
"World"
hdel
Removes the specified fields from the hash stored at key.
Specified fields that do not exist within this hash are ignored.
If key does not exist, it is treated as an empty hash and this command returns
0.
Examples
127.0.0.1:6379> HSET myhash field1 "foo"
(integer) 1
127.0.0.1:6379> HDEL myhash field1
(integer) 1
127.0.0.1:6379> HDEL myhash field2
(integer) 0
hello
Switch to a different protocol, optionally authenticating and setting the connection's name, or provide a contextual client report.
Valkey supports two protocols: RESP2 and RESP3. RESP3 has certain advantages since
when the connection is in this mode, Valkey is able to reply with more semantical
replies: for instance, HGETALL will return a map type, so a client library
implementation no longer requires to know in advance to translate the array into
a hash before returning it to the caller. For a full coverage of RESP3, please
check the RESP3 specification.
Valkey connections start in RESP2 mode, so clients implementing RESP2 do not need to updated or changed. There are no short term plans to drop support for RESP2, although future version may default to RESP3.
HELLO always replies with a list of current server and connection properties,
such as: versions, modules loaded, client ID, replication role and so forth.
The availability_zone field only shows up when it is set in the configs,
see availability-zone config for more details, added in Valkey 8.1.
When called without any arguments and its default use of RESP2 protocol, the reply looks like this:
> HELLO
1) "server"
2) "redis"
3) "version"
4) "255.255.255"
5) "proto"
6) (integer) 2
7) "id"
8) (integer) 5
9) "mode"
10) "standalone"
11) "role"
12) "master"
13) "modules"
14) (empty array)
15) "availability_zone"
16) "us-east-1"
Clients that want to handshake using the RESP3 mode need to call the HELLO
command and specify the value "3" as the protover argument, like so:
> HELLO 3
1# "server" => "redis"
2# "version" => "7.2.4"
3# "proto" => (integer) 3
4# "id" => (integer) 10
5# "mode" => "standalone"
6# "role" => "master"
7# "modules" => (empty array)
8# "availability_zone" => "us-east-1"
Because HELLO replies with useful information, and given that protover is
optional or can be set to "2", client library authors may consider using this
command instead of the canonical PING when setting up the connection.
When called with the optional protover argument, this command switches the
protocol to the specified version and also accepts the following options:
AUTH <username> <password>: directly authenticate the connection in addition to switching to the specified protocol version. This makes callingAUTHbeforeHELLOunnecessary when setting up a new connection. Note that theusernamecan be set to "default" to authenticate against a server that does not use ACLs, but rather the simplerrequirepassmechanism.SETNAME <clientname>: this is the equivalent of callingCLIENT SETNAME.
hexists
Returns if field is an existing field in the hash stored at key.
Examples
127.0.0.1:6379> HSET myhash field1 "foo"
(integer) 1
127.0.0.1:6379> HEXISTS myhash field1
(integer) 1
127.0.0.1:6379> HEXISTS myhash field2
(integer) 0
hexpire
The HEXPIRE command allows manipulating the expiration time for existing hash fields.
When set, the expiration time of a hash field will determine when the field will be automatically deleted.
Note, that providing a millisecond time of '0' will cause immediate expiration and deletion of the field(s).
Options
The HEXPIRE command supports a set of options that modify its behavior:
- NX — For each specified field, set expiration only when the field has no expiration.
- XX — For each specified field, set expiration only when the field has an existing expiration.
- GT — For each specified field, set expiration only when the new expiration is greater than current one.
- LT — For each specified field, set expiration only when the new expiration is less than current one.
Examples
127.0.0.1:6379> HSET myhash f1 v1 f2 v2 f3 v3
(integer) 3
127.0.0.1:6379> HEXPIRE myhash 10 FIELDS 2 f2 f3
1) (integer) 1
2) (integer) 1
127.0.0.1:6379> HTTL myhash FIELDS 3 f1 f2 f3
1) (integer) -1
2) (integer) 8
3) (integer) 8
hexpireat
HEXPIREAT has the same effect and semantic as HEXPIRE, but instead of
specifying the number of seconds representing the TTL (time to live), it takes
an absolute Unix timestamp (seconds since January 1, 1970). A
timestamp in the past will delete the key immediately.
For the specific semantics of the command refer to the documentation of
HEXPIRE.
Options
The HEXPIREAT command supports a set of options that modify its behavior:
- NX — For each specified field, set expiration only when the field has no expiration.
- XX — For each specified field, set expiration only when the field has an existing expiration.
- GT — For each specified field, set expiration only when the new expiration is greater than current one.
- LT — For each specified field, set expiration only when the new expiration is less than current one.
Examples
127.0.0.1:6379> HSET myhash f1 v1 f2 v2 f3 v3
(integer) 3
27.0.0.1:6379> HEXPIREAT myhash 1754846600 FIELDS 2 f2 f3
1) (integer) 1
2) (integer) 1
127.0.0.1:6379> HEXPIRETIME myhash FIELDS 3 f1 f2 f3
1) (integer) -1
2) (integer) 1754846600
3) (integer) 1754846600
hexpiretime
The HEXPIRETIME command returns the absolute Unix timestamp (since January 1, 1970) in seconds at which the given hash field(s) will expire or -1 if the hash field doesn't have expiration time.
See also the HPEXPIRETIME command that returns the same information with milliseconds resolution.
Examples
127.0.0.1:6379> HSET myhash f1 v1 f2 v2 f3 v3
(integer) 3
27.0.0.1:6379> HEXPIREAT myhash 1754846600 FIELDS 2 f2 f3
1) (integer) 1
2) (integer) 1
127.0.0.1:6379> HEXPIRETIME myhash FIELDS 4 f1 f2 f3 non-exist
1) (integer) -1
2) (integer) 1754846600
3) (integer) 1754846600
4) (integer) -2
hget
Returns the value associated with field in the hash stored at key.
Examples
127.0.0.1:6379> HSET myhash field1 "foo"
(integer) 1
127.0.0.1:6379> HGET myhash field1
"foo"
127.0.0.1:6379> HGET myhash field2
(nil)
hgetall
Returns all fields and values of the hash stored at key.
In the returned value, every field name is followed by its value, so the length
of the reply is twice the size of the hash.
Examples
127.0.0.1:6379> HSET myhash field1 "Hello"
(integer) 1
127.0.0.1:6379> HSET myhash field2 "World"
(integer) 1
127.0.0.1:6379> HGETALL myhash
1) "field1"
2) "Hello"
3) "field2"
4) "World"
hgetdel
The HGETDEL command returns the values associated with the specified fields in the hash stored at key and deletes those fields from the hash.
For every field that does not exist in the hash, a nil value is returned.
Because non-existing keys are treated as empty hashes, running HGETDEL against a non-existing key will return a list of nil values.
When the last field is deleted, the key is also deleted.
Examples
127.0.0.1:6379> HSET myhash f1 v1 f2 v2 f3 v3
(integer) 3
127.0.0.1:6379> HGETDEL myhash FIELDS 1 f2
1) "v2"
127.0.0.1:6379> HGETDEL myhash FIELDS 1 f2
1) (nil)
127.0.0.1:6379> HGETALL myhash
1) "f1"
2) "v1"
3) "f3"
4) "v3"
127.0.0.1:6379> HGETDEL myhash FIELDS 2 f2 f3
1) (nil)
2) "v3"
127.0.0.1:6379> HGETALL myhash
1) "f1"
2) "v1"
127.0.0.1:6379> HGETDEL myhash FIELDS 3 f1 non-exist
(error) ERR syntax error
127.0.0.1:6379> HGETDEL myhash FIELDS 2 f1 non-exist
1) "v1"
2) (nil)
127.0.0.1:6379> HGETALL myhash
(empty array)
hgetex
The HGETEX command returns the value of one or more fields of a given hash key, and optionally manipulates their expiration time.
The command will return an array in the size of the number of requested fields.
Without providing any optional flags, this command behaves exactly like a normal HMGET command.
Options
The HGETEX command supports a set of options that modify its behavior:
- EX seconds — Set the specified expiration time, in seconds.
- PX milliseconds — Set the specified expiration time, in milliseconds.
- EXAT
unix-time-seconds— Set the specified Unix time at which the fields will expire, in seconds. - PXAT
unix-time-milliseconds— Set the specified Unix time at which the fields will expire, in milliseconds. - PERSIST — Remove the expiration time associated with the fields.
Note for the following:
- The EX, PX, EXAT, PXAT, and PERSIST options are mutually exclusive.
- Providing '0' expiration TTL via
EXorPXoptional arguments will cause the specified fields to expire immediately and be removed from the hash. - Providing past expiration time via
EXATorPXAToptional arguments will cause the specified fields to expire immediately and be removed from the hash.
Examples
127.0.0.1:6379> HSET myhash f1 v1 f2 v2 f3 v3
(integer) 3
27.0.0.1:6379> HGETEX myhash EX 10 FIELDS 2 f2 f3
1) "v2"
2) "v3"
127.0.0.1:6379> HTTL myhash FIELDS 3 f1 f2 f3
1) (integer) -1
2) (integer) 8
3) (integer) 8
127.0.0.1:6379> HGETEX myhash EX 0 FIELDS 3 f1 f2 f3
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> HGETEX myhash FIELDS 3 f1 f2 f3
1) (nil)
2) (nil)
3) (nil)
hincrby
Increments the number stored at field in the hash stored at key by
increment.
If key does not exist, a new key holding a hash is created.
If field does not exist the value is set to 0 before the operation is
performed.
The range of values supported by HINCRBY is limited to 64 bit signed integers.
Examples
Since the increment argument is signed, both increment and decrement
operations can be performed:
127.0.0.1:6379> HSET myhash field 5
(integer) 1
127.0.0.1:6379> HINCRBY myhash field 1
(integer) 6
127.0.0.1:6379> HINCRBY myhash field -1
(integer) 5
127.0.0.1:6379> HINCRBY myhash field -10
(integer) -5
hincrbyfloat
Increment the specified field of a hash stored at key, and representing a
floating point number, by the specified increment. If the increment value
is negative, the result is to have the hash field value decremented instead of incremented.
If the field does not exist, it is set to 0 before performing the operation.
An error is returned if one of the following conditions occur:
- The key contains a value of the wrong type (not a hash).
- The current field content or the specified increment are not parsable as a double precision floating point number.
The exact behavior of this command is identical to the one of the INCRBYFLOAT
command, please refer to the documentation of INCRBYFLOAT for further
information.
Examples
127.0.0.1:6379> HSET mykey field 10.50
(integer) 1
127.0.0.1:6379> HINCRBYFLOAT mykey field 0.1
"10.6"
127.0.0.1:6379> HINCRBYFLOAT mykey field -5
"5.6"
127.0.0.1:6379> HSET mykey field 5.0e3
(integer) 0
127.0.0.1:6379> HINCRBYFLOAT mykey field 2.0e2
"5200"
Implementation details
The command is always propagated in the replication link and the Append Only
File as a HSET operation, so that differences in the underlying floating point
math implementation will not be sources of inconsistency.
hkeys
Returns all field names in the hash stored at key.
Examples
127.0.0.1:6379> HSET myhash field1 "Hello"
(integer) 1
127.0.0.1:6379> HSET myhash field2 "World"
(integer) 1
127.0.0.1:6379> HKEYS myhash
1) "field1"
2) "field2"
hlen
Returns the number of fields contained in the hash stored at key.
Examples
127.0.0.1:6379> HSET myhash field1 "Hello"
(integer) 1
127.0.0.1:6379> HSET myhash field2 "World"
(integer) 1
127.0.0.1:6379> HLEN myhash
(integer) 2
hmget
Returns the values associated with the specified fields in the hash stored at
key.
For every field that does not exist in the hash, a nil value is returned.
Because non-existing keys are treated as empty hashes, running HMGET against
a non-existing key will return a list of nil values.
127.0.0.1:6379> HSET myhash field1 "Hello"
(integer) 1
127.0.0.1:6379> HSET myhash field2 "World"
(integer) 1
127.0.0.1:6379> HMGET myhash field1 field2 nofield
1) "Hello"
2) "World"
3) (nil)
hmset
Sets the specified fields to their respective values in the hash stored at
key.
This command overwrites any specified fields already existing in the hash.
If key does not exist, a new key holding a hash is created.
Alternative
HSET with multiple field-value pairs.
Examples
127.0.0.1:6379> HMSET myhash field1 "Hello" field2 "World"
OK
127.0.0.1:6379> HGET myhash field1
"Hello"
127.0.0.1:6379> HGET myhash field2
"World"
hpersist
The HPERSIST remove the existing expiration on a hash key's field(s), turning the field(s) from volatile (a field with expiration set)
to persistent (a field that will never expire as no TTL (time to live) is associated).
Examples
127.0.0.1:6379> HSET myhash f1 v1 f2 v2 f3 v3
(integer) 3
27.0.0.1:6379> HEXPIRE myhash 1000 FIELDS 2 f2 f3
1) (integer) 1
2) (integer) 1
127.0.0.1:6379> HTTL myhash FIELDS 3 f1 f2 f3
1) (integer) -1
2) (integer) 998
3) (integer) 998
127.0.0.1:6379> HPERSIST myhash FIELDS 3 f1 f2 f3
1) (integer) -1
2) (integer) 1
3) (integer) 1
127.0.0.1:6379> HTTL myhash FIELDS 3 f1 f2 f3
1) (integer) -1
2) (integer) -1
3) (integer) -1
hpexpire
This command works exactly like HEXPIRE but the time to live of the field(s) is
specified in milliseconds instead of seconds.
Note, that providing a millisecond time of '0' will cause immediate expiration and reclamation of the field(s).
Options
The HPEXPIRE command supports a set of options that modify its behavior:
- NX — For each specified field, set expiration only when the field has no expiration.
- XX — For each specified field, set expiration only when the field has an existing expiration.
- GT — For each specified field, set expiration only when the new expiration is greater than current one.
- LT — For each specified field, set expiration only when the new expiration is less than current one.
Examples
127.0.0.1:6379> HSET myhash f1 v1 f2 v2 f3 v3
(integer) 3
127.0.0.1:6379> HPEXPIRE myhash 10000 FIELDS 2 f2 f3
1) (integer) 1
2) (integer) 1
127.0.0.1:6379> HPTTL myhash FIELDS 3 f1 f2 f3
1) (integer) -1
2) (integer) 9597
3) (integer) 9597
hpexpireat
HEXPIREAT has the same effect and semantic as HPEXPIRE, but instead of
specifying the number of milliseconds representing the TTL (time to live), it takes
an absolute Unix timestamp (milliseconds since January 1, 1970). A
timestamp in the past will delete the key immediately.
For the specific semantics of the command refer to the documentation of
HPEXPIRE.
Options
The HPEXPIREAT command supports a set of options that modify its behavior:
- NX — For each specified field, set expiration only when the field has no expiration.
- XX — For each specified field, set expiration only when the field has an existing expiration.
- GT — For each specified field, set expiration only when the new expiration is greater than current one.
- LT — For each specified field, set expiration only when the new expiration is less than current one.
Examples
127.0.0.1:6379> HSET myhash f1 v1 f2 v2 f3 v3
(integer) 3
127.0.0.1:6379> HPEXPIREAT myhash 1754847944000 FIELDS 2 f2 f3
1) (integer) 1
2) (integer) 1
127.0.0.1:6379> HPEXPIRETIME myhash FIELDS 3 f1 f2 f3
1) (integer) -1
2) (integer) 1754847944000
3) (integer) 1754847944000
hpexpiretime
The HPEXPIRETIME command returns the absolute Unix timestamp (since January 1, 1970) in milliseconds at which the given hash field(s) will expire.
See also the HEXPIRETIME command which returns the same information with seconds resolution.
Examples
127.0.0.1:6379> HSET myhash f1 v1 f2 v2 f3 v3
(integer) 3
27.0.0.1:6379> HPEXPIREAT myhash 1754847944000 FIELDS 2 f2 f3
1) (integer) 1
2) (integer) 1
127.0.0.1:6379> HPEXPIRETIME myhash FIELDS 4 f1 f2 f3 non-exist
1) (integer) -1
2) (integer) 1754847944000
3) (integer) 1754847944000
4) (integer) -2
hpttl
Like HTTL this command returns the remaining time to live of hash field(s) that has an associated expiration time,
with the sole difference that HTTL returns the amount of remaining
time in seconds while HPTTL returns it in milliseconds.
See also the HTTL command that returns the same information with seconds resolution.
Examples
127.0.0.1:6379> HSET myhash f1 v1 f2 v2 f3 v3
(integer) 3
27.0.0.1:6379> HPEXPIRE myhash 10000 FIELDS 2 f2 f3
1) (integer) 1
2) (integer) 1
127.0.0.1:6379> HPTTL myhash FIELDS 3 f1 f2 f3
1) (integer) -1
2) (integer) 9597
3) (integer) 9597
hrandfield
When called with just the key argument, return a random field from the hash value stored at key.
If the provided count argument is positive, return an array of distinct fields.
The array's length is either count or the hash's number of fields (HLEN), whichever is lower.
If called with a negative count, the behavior changes and the command is allowed to return the same field multiple times.
In this case, the number of returned fields is the absolute value of the specified count.
The optional WITHVALUES modifier changes the reply so it includes the respective values of the randomly selected hash fields.
Examples
127.0.0.1:6379> HSET coin heads obverse tails reverse edge null
(integer) 3
127.0.0.1:6379> HRANDFIELD coin
"heads"
127.0.0.1:6379> HRANDFIELD coin
"heads"
127.0.0.1:6379> HRANDFIELD coin -5 WITHVALUES
1) "heads"
2) "obverse"
3) "tails"
4) "reverse"
5) "edge"
6) "null"
7) "heads"
8) "obverse"
9) "edge"
10) "null"
Specification of the behavior when count is passed
When the count argument is a positive value this command behaves as follows:
- No repeated fields are returned.
- If
countis bigger than the number of fields in the hash, the command will only return the whole hash without additional fields. - The order of fields in the reply is not truly random, so it is up to the client to shuffle them if needed.
When the count is a negative value, the behavior changes as follows:
- Repeating fields are possible.
- Exactly
countfields, or an empty array if the hash is empty (non-existing key), are always returned. - The order of fields in the reply is truly random.
hscan
See SCAN for HSCAN documentation.
hset
Sets the specified fields to their respective values in the hash stored at key.
This command overwrites the values of specified fields that exist in the hash.
If key doesn't exist, a new key holding a hash is created.
Examples
127.0.0.1:6379> HSET myhash field1 "Hello"
(integer) 1
127.0.0.1:6379> HGET myhash field1
"Hello"
127.0.0.1:6379> HSET myhash field2 "Hi" field3 "World"
(integer) 2
127.0.0.1:6379> HGET myhash field2
"Hi"
127.0.0.1:6379> HGET myhash field3
"World"
127.0.0.1:6379> HGETALL myhash
1) "field1"
2) "Hello"
3) "field2"
4) "Hi"
5) "field3"
6) "World"
hsetex
The HSETEX command allows setting the value of one or more fields of a given hash key, and optionally manipulating their expiration time.
The command will return 1 in case all provided fields have been set or 0 in case FNX or FXX were provided and none of the specified fields were set.
Without providing any optional flags, this command behaves exactly like a normal HSET command.
Options
The HSETEX command supports a set of options that modify its behavior:
- FNX — Only set the fields if none of them already exist.
- FXX — Only set the fields if all of them already exist.
- EX seconds — Set the specified expiration time in seconds.
- PX milliseconds — Set the specified expiration time in milliseconds.
- EXAT
unix-time-seconds— Set the specified Unix time in seconds for when the fields will expire. - PXAT
unix-time-milliseconds— Set the specified Unix time in milliseconds at which the fields will expire. - KEEPTTL — Retain the TTL associated with the fields.
Note for the following:
- The EX, PX, EXAT, PXAT, and KEEPTTL options are mutually exclusive.
- Setting a value on a volatile hash field (A field which has an assigned expiration time) will remove the expiration for that field.
- Providing '0' expiration TTL via
EXorPXoptional arguments will result in the specified fields immediately expiring and being removed from the hash. - Providing past expiration time via
EXATorPXAToptional arguments will result in the specified fields immediately expiring and being removed from the hash.
Examples
Add 3 new items without expiration time to a 'myhash'
127.0.0.1:6379> HSETEX myhash FIELDS 3 f1 v1 f2 v2 f3 v3
(integer) 1
Unsuccessful attempt setting expiration time on EXISTING fields
127.0.0.1:6379> HSETEX myhash FNX EX 10 FIELDS 2 f2 v2 f3 v3
(integer) 0
Successful attempt setting expiration time on EXISTING fields
127.0.0.1:6379> HSETEX myhash FXX EX 10 FIELDS 2 f2 v2 f3 v3
(integer) 1
Verify hash fields expiration time:
127.0.0.1:6379> HTTL myhash FIELDS 3 f1 f2 f3
1) (integer) -1
2) (integer) 8
3) (integer) 8
Override all hash items will also persist the fields
127.0.0.1:6379> HSETEX myhash FIELDS 3 f1 v1 f2 v2 f3 v3
(integer) 1
127.0.0.1:6379> HTTL myhash FIELDS 3 f1 f2 f3
1) (integer) -1
2) (integer) -1
3) (integer) -1
Setting expiration time in the past will remove all the elements in the hash:
127.0.0.1:6379> HSETEX EX 0 myhash FIELDS 3 f1 v1 f2 v2 f3 v3
(integer) 1
127.0.0.1:6379> HTTL myhash FIELDS 3 f1 f2 f3
1) (integer) -2
2) (integer) -2
3) (integer) -2
127.0.0.1:6379> HLEN myhash
(integer) 0
127.0.0.1:6379> EXISTS myhash
(integer) 0
hsetnx
Sets field in the hash stored at key to value, only if field does not
yet exist.
If key does not exist, a new key holding a hash is created.
If field already exists, this operation has no effect.
Examples
127.0.0.1:6379> HSETNX myhash field "Hello"
(integer) 1
127.0.0.1:6379> HSETNX myhash field "World"
(integer) 0
127.0.0.1:6379> HGET myhash field
"Hello"
hstrlen
Returns the string length of the value associated with field in the hash stored at key. If the key or the field do not exist, 0 is returned.
Examples
127.0.0.1:6379> HSET myhash f1 HelloWorld f2 99 f3 -256
(integer) 3
127.0.0.1:6379> HSTRLEN myhash f1
(integer) 10
127.0.0.1:6379> HSTRLEN myhash f2
(integer) 2
127.0.0.1:6379> HSTRLEN myhash f3
(integer) 4
httl
The HTTL command returns the remaining time to live of hash field(s) with associated expiration time(s).
This introspection capability allows a Valkey client to check how many seconds a
given hash field will continue to be part of the hash object.
See also the HPTTL command that returns the same information with milliseconds resolution.
Examples
127.0.0.1:6379> HSET myhash f1 v1 f2 v2 f3 v3
(integer) 3
27.0.0.1:6379> HEXPIRE myhash 10 FIELDS 2 f2 f3
1) (integer) 1
2) (integer) 1
127.0.0.1:6379> HTTL myhash FIELDS 4 f1 f2 f3 non-exist
1) (integer) -1
2) (integer) 8
3) (integer) 8
4) (integer) -2
hvals
Returns all values in the hash stored at key.
Examples
127.0.0.1:6379> HSET myhash field1 "Hello"
(integer) 1
127.0.0.1:6379> HSET myhash field2 "World"
(integer) 1
127.0.0.1:6379> HVALS myhash
1) "Hello"
2) "World"
incr
Increments the number stored at key by one.
If the key does not exist, it is set to 0 before performing the operation.
An error is returned if the key contains a value of the wrong type or contains a
string that can not be represented as integer.
This operation is limited to 64 bit signed integers.
Note: this is a string operation because Valkey does not have a dedicated integer type. The string stored at the key is interpreted as a base-10 64 bit signed integer to execute the operation.
Valkey stores integers in their integer representation, so for string values that actually hold an integer, there is no overhead for storing the string representation of the integer.
Examples
127.0.0.1:6379> SET mykey "10"
OK
127.0.0.1:6379> INCR mykey
(integer) 11
127.0.0.1:6379> GET mykey
"11"
Pattern: Counter
The counter pattern is the most obvious thing you can do with Valkey atomic
increment operations.
The idea is simply send an INCR command to Valkey every time an operation
occurs.
For instance in a web application we may want to know how many page views this
user did every day of the year.
To do so the web application may simply increment a key every time the user performs a page view, creating the key name concatenating the User ID and a string representing the current date.
This simple pattern can be extended in many ways:
- It is possible to use
INCRandEXPIREtogether at every page view to have a counter counting only the latest N page views separated by less than the specified amount of seconds. - A client may use GETSET in order to atomically get the current counter value and reset it to zero.
- Using other atomic increment/decrement commands like
DECRorINCRBYit is possible to handle values that may get bigger or smaller depending on the operations performed by the user. Imagine for instance the score of different users in an online game.
Pattern: Rate limiter
The rate limiter pattern is a special counter that is used to limit the rate at which an operation can be performed. The classical materialization of this pattern involves limiting the number of requests that can be performed against a public API.
We provide two implementations of this pattern using INCR, where we assume
that the problem to solve is limiting the number of API calls to a maximum of
ten requests per second per IP address.
Pattern: Rate limiter 1
The more simple and direct implementation of this pattern is the following:
FUNCTION LIMIT_API_CALL(ip)
ts = CURRENT_UNIX_TIME()
keyname = ip+":"+ts
MULTI
INCR(keyname)
EXPIRE(keyname,10)
EXEC
current = RESPONSE_OF_INCR_WITHIN_MULTI
IF current > 10 THEN
ERROR "too many requests per second"
ELSE
PERFORM_API_CALL()
END
Basically we have a counter for every IP, for every different second. But these counters are always incremented setting an expire of 10 seconds so that they'll be removed by Valkey automatically when the current second is a different one.
Note the used of MULTI and EXEC in order to make sure that we'll both
increment and set the expire at every API call.
Pattern: Rate limiter 2
An alternative implementation uses a single counter, but is a bit more complex to get it right without race conditions. We'll examine different variants.
FUNCTION LIMIT_API_CALL(ip):
current = GET(ip)
IF current != NULL AND current > 10 THEN
ERROR "too many requests per second"
ELSE
value = INCR(ip)
IF value == 1 THEN
EXPIRE(ip,1)
END
PERFORM_API_CALL()
END
The counter is created in a way that it only will survive one second, starting from the first request performed in the current second. If there are more than 10 requests in the same second the counter will reach a value greater than 10, otherwise it will expire and start again from 0.
In the above code there is a race condition.
If for some reason the client performs the INCR command but does not perform
the EXPIRE the key will be leaked until we'll see the same IP address again.
This can be fixed easily turning the INCR with optional EXPIRE into a Lua
script that is send using the EVAL command (only available since Valkey version
2.6).
local current
current = server.call("incr",KEYS[1])
if current == 1 then
server.call("expire",KEYS[1],1)
end
There is a different way to fix this issue without using scripting, by using Lists instead of counters. The implementation is more complex and uses more advanced features but has the advantage of remembering the IP addresses of the clients currently performing an API call, that may be useful or not depending on the application.
FUNCTION LIMIT_API_CALL(ip)
current = LLEN(ip)
IF current > 10 THEN
ERROR "too many requests per second"
ELSE
IF EXISTS(ip) == FALSE
MULTI
RPUSH(ip,ip)
EXPIRE(ip,1)
EXEC
ELSE
RPUSHX(ip,ip)
END
PERFORM_API_CALL()
END
The RPUSHX command only pushes the element if the key already exists.
Note that we have a race here, but it is not a problem: EXISTS may return
false but the key may be created by another client before we create it inside
the MULTI / EXEC block.
However this race will just miss an API call under rare conditions, so the rate
limiting will still work correctly.
incrby
Increments the number stored at key by increment.
If the key does not exist, it is set to 0 before performing the operation.
An error is returned if the key contains a value of the wrong type or contains a
string that can not be represented as integer.
This operation is limited to 64 bit signed integers.
See INCR for extra information on increment/decrement operations.
Examples
127.0.0.1:6379> SET mykey "10"
OK
127.0.0.1:6379> INCRBY mykey 5
(integer) 15
incrbyfloat
Increment the string representing a floating point number stored at key by the
specified increment. By using a negative increment value, the result is
that the value stored at the key is decremented (by the obvious properties
of addition).
If the key does not exist, it is set to 0 before performing the operation.
An error is returned if one of the following conditions occur:
- The key contains a value of the wrong type (not a string).
- The current key content or the specified increment are not parsable as a double precision floating point number.
If the command is successful the new incremented value is stored as the new value of the key (replacing the old one), and returned to the caller as a string.
Both the value already contained in the string key and the increment argument can be optionally provided in exponential notation, however the value computed after the increment is stored consistently in the same format, that is, an integer number followed (if needed) by a dot, and a variable number of digits representing the decimal part of the number. Trailing zeroes are always removed.
The precision of the output is fixed at 17 digits after the decimal point regardless of the actual internal precision of the computation.
Examples
127.0.0.1:6379> SET mykey 10.50
OK
127.0.0.1:6379> INCRBYFLOAT mykey 0.1
"10.6"
127.0.0.1:6379> INCRBYFLOAT mykey -5
"5.6"
127.0.0.1:6379> SET mykey 5.0e3
OK
127.0.0.1:6379> INCRBYFLOAT mykey 2.0e2
"5200"
Implementation details
The command is always propagated in the replication link and the Append Only
File as a SET operation, so that differences in the underlying floating point
math implementation will not be sources of inconsistency.
info
The INFO command returns information and statistics about the server in a
format that is simple to parse by computers and easy to read by humans.
The optional parameter can be used to select a specific section of information:
server: General information about the Valkey serverclients: Client connections sectionmemory: Memory consumption related informationpersistence: RDB and AOF related informationstats: General statisticsreplication: primary/replica replication informationcpu: CPU consumption statisticscommandstats: Valkey command statisticslatencystats: Valkey command latency percentile distribution statisticssentinel: Valkey Sentinel section (only applicable to Sentinel instances)cluster: Valkey Cluster sectionmodules: Modules sectionkeyspace: Database related statisticserrorstats: Valkey error statistics
It can also take the following values:
all: Return all sections (excluding module generated ones)default: Return only the default set of sectionseverything: Includesallandmodules
When no parameter is provided, the default option is assumed.
127.0.0.1:6379> INFO
# Server
redis_version:7.2.4
server_name:valkey
valkey_version:255.255.255
redis_git_sha1:b0d5a0f5
redis_git_dirty:1
redis_build_id:1cadaf78f6168f2d
server_mode:standalone
os:Linux 6.1.0-18-amd64 x86_64
arch_bits:64
monotonic_clock:POSIX clock_gettime
multiplexing_api:epoll
atomicvar_api:c11-builtin
gcc_version:12.2.0
process_id:982599
process_supervised:no
run_id:e0abe2248cad0c6d9cb2445d8e6b73448f567f74
tcp_port:6379
server_time_usec:1714701488527373
uptime_in_seconds:94798
uptime_in_days:1
hz:10
configured_hz:10
lru_clock:3425456
executable:/home/viktor/repos/valkey/src/./valkey-server
config_file:
io_threads_active:0
availability_zone:
listener0:name=tcp,bind=*,bind=-::*,port=6379
# Clients
connected_clients:1
cluster_connections:0
maxclients:10000
client_recent_max_input_buffer:20480
client_recent_max_output_buffer:0
blocked_clients:0
tracking_clients:0
pubsub_clients:0
watching_clients:0
clients_in_timeout_table:0
total_watched_keys:0
total_blocking_keys:0
total_blocking_keys_on_nokey:0
paused_reason:none
paused_actions:none
paused_timeout_milliseconds:0
# Memory
used_memory:4757704
used_memory_human:4.54M
used_memory_rss:13221888
used_memory_rss_human:12.61M
used_memory_peak:4777616
used_memory_peak_human:4.56M
used_memory_peak_perc:99.58%
used_memory_overhead:989344
used_memory_startup:988648
used_memory_dataset:3768360
used_memory_dataset_perc:99.98%
allocator_allocated:4789624
allocator_active:5042176
allocator_resident:9252864
allocator_muzzy:0
total_system_memory:33280372736
total_system_memory_human:30.99G
used_memory_lua:31744
used_memory_vm_eval:31744
used_memory_lua_human:31.00K
used_memory_scripts_eval:0
number_of_cached_scripts:0
number_of_functions:0
number_of_libraries:0
used_memory_vm_functions:33792
used_memory_vm_total:65536
used_memory_vm_total_human:64.00K
used_memory_functions:184
used_memory_scripts:184
used_memory_scripts_human:184B
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction
allocator_frag_ratio:1.05
allocator_frag_bytes:252552
allocator_rss_ratio:1.84
allocator_rss_bytes:4210688
rss_overhead_ratio:1.43
rss_overhead_bytes:3969024
mem_fragmentation_ratio:2.80
mem_fragmentation_bytes:8504448
mem_not_counted_for_evict:0
mem_replication_backlog:0
mem_total_replication_buffers:0
mem_replicas_repl_buffer:0
mem_clients_slaves:0
mem_clients_normal:0
mem_cluster_links:0
mem_aof_buffer:0
mem_allocator:jemalloc-5.3.0
mem_overhead_db_hashtable_rehashing:0
active_defrag_running:0
lazyfree_pending_objects:0
lazyfreed_objects:0
# Persistence
loading:0
async_loading:0
current_cow_peak:0
current_cow_size:0
current_cow_size_age:0
current_fork_perc:0.00
current_save_keys_processed:0
current_save_keys_total:0
rdb_changes_since_last_save:0
rdb_bgsave_in_progress:0
rdb_last_save_time:1714701488
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:0
rdb_current_bgsave_time_sec:-1
rdb_saves:1
rdb_last_cow_size:229376
rdb_last_load_keys_expired:0
rdb_last_load_keys_loaded:0
aof_enabled:0
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:-1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_rewrites:0
aof_rewrites_consecutive_failures:0
aof_last_write_status:ok
aof_last_cow_size:0
module_fork_in_progress:0
module_fork_last_cow_size:0
# Stats
total_connections_received:3081
total_commands_processed:3080
instantaneous_ops_per_sec:91
total_net_input_bytes:134722
total_net_output_bytes:686934
total_net_repl_input_bytes:0
total_net_repl_output_bytes:0
instantaneous_input_kbps:4.14
instantaneous_output_kbps:1.55
instantaneous_input_repl_kbps:0.00
instantaneous_output_repl_kbps:0.00
rejected_connections:0
sync_full:0
sync_partial_ok:0
sync_partial_err:0
expired_keys:0
expired_stale_perc:0.00
expired_time_cap_reached_count:0
expire_cycle_cpu_milliseconds:1829
evicted_keys:0
evicted_clients:0
evicted_scripts:0
total_eviction_exceeded_time:0
current_eviction_exceeded_time:0
keyspace_hits:877
keyspace_misses:98
pubsub_channels:0
pubsub_patterns:0
pubsubshard_channels:0
latest_fork_usec:832
total_forks:5
migrate_cached_sockets:0
slave_expires_tracked_keys:0
active_defrag_hits:0
active_defrag_misses:0
active_defrag_key_hits:0
active_defrag_key_misses:0
total_active_defrag_time:0
current_active_defrag_time:0
tracking_total_keys:0
tracking_total_items:0
tracking_total_prefixes:0
unexpected_error_replies:0
total_error_replies:55
dump_payload_sanitizations:0
total_reads_processed:6160
total_writes_processed:3085
io_threaded_reads_processed:0
io_threaded_writes_processed:0
client_query_buffer_limit_disconnections:0
client_output_buffer_limit_disconnections:0
reply_buffer_shrinks:3
reply_buffer_expands:0
eventloop_cycles:710861
eventloop_duration_sum:261482066
eventloop_duration_cmd_sum:4662723
instantaneous_eventloop_cycles_per_sec:283
instantaneous_eventloop_duration_usec:595
acl_access_denied_auth:0
acl_access_denied_cmd:0
acl_access_denied_key:0
acl_access_denied_channel:0
acl_access_denied_tls_cert:0
# Replication
role:master
connected_slaves:0
replicas_waiting_psync:0
master_failover_state:no-failover
master_replid:488d931b7e08f8e091f674ea64480165971a25f1
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
# CPU
used_cpu_sys:68.476389
used_cpu_user:219.408941
used_cpu_sys_children:0.003157
used_cpu_user_children:0.008264
used_cpu_sys_main_thread:68.478353
used_cpu_user_main_thread:219.404508
used_active_time_main_thread:192.003980
# Modules
# Errorstats
errorstat_ERR:count=55
# Cluster
cluster_enabled:0
# Keyspace
Notes
Please note depending on the version of Valkey some of the fields have been added or removed. A robust client application should therefore parse the result of this command by skipping unknown properties, and gracefully handle missing fields.
Here is the description of fields.
Here is the meaning of all fields in the server section:
redis_version: Redis OSS version this Valkey server is compatible withvalkey_version: Valkey version number (e.g. 7.2.5)valkey_release_stage: The status of the Valkey version: "ga" for generally available versions; "rc1", "rc2", etc. for release candidates; "dev" for development versions. Added in 8.1.redis_git_sha1: Git SHA1redis_git_dirty: Git dirty flagredis_build_id: The build idredis_mode: The server's mode ("standalone", "sentinel" or "cluster")os: Operating system hosting the Valkey serverarch_bits: Architecture (32 or 64 bits)multiplexing_api: Event loop mechanism used by Valkeyatomicvar_api: Atomicvar API used by Valkeygcc_version: Version of the GCC compiler used to compile the Valkey serverprocess_id: PID of the server processprocess_supervised: Supervised system ("upstart", "systemd", "unknown" or "no")run_id: Random value identifying the Valkey server (to be used by Sentinel and Cluster)tcp_port: TCP/IP listen portserver_time_usec: Epoch-based system time with microsecond precisionuptime_in_seconds: Number of seconds since Valkey server startuptime_in_days: Same value expressed in dayshz: The server's current frequency settingconfigured_hz: The server's configured frequency settingclients_hz: Current frequency for client maintenancelru_clock: Clock incrementing every minute, for LRU managementexecutable: The path to the server's executableconfig_file: The path to the config fileio_threads_active: Flag indicating if I/O threads are activeavailability_zone: Inform Valkey of the Availability zone if running in a cloud environment, seeavailability-zoneconfig for more details. Added in Valkey 8.0.shutdown_in_milliseconds: The maximum time remaining for replicas to catch up the replication before completing the shutdown sequence. This field is only present during shutdown.
Here is the meaning of all fields in the clients section:
connected_clients: Number of client connections (excluding connections from replicas)cluster_connections: An approximation of the number of sockets used by the cluster's busmaxclients: The value of themaxclientsconfiguration directive. This is the upper limit for the sum ofconnected_clients,connected_slavesandcluster_connections.client_recent_max_input_buffer: Biggest input buffer among current client connectionsclient_recent_max_output_buffer: Biggest output buffer among current client connectionsblocked_clients: Number of clients pending on a blocking call (BLPOP),BRPOP,BRPOPLPUSH,BLMOVE,BZPOPMIN,BZPOPMAX)tracking_clients: Number of clients being tracked (CLIENT TRACKING)pubsub_clients: Number of clients in pubsub mode (SUBSCRIBE,PSUBSCRIBE,SSUBSCRIBE). Added in Valkey 8.0watching_clients: Number of clients in watching mode (WATCH). Added in Valkey 8.0clients_in_timeout_table: Number of clients in the clients timeout tabletotal_watched_keys: Number of watched keys. Added in Valkey 8.0.total_blocking_keys: Number of blocking keys.total_blocking_keys_on_nokey: Number of blocking keys that one or more clients that would like to be unblocked when the key is deleted.paused_reason: The current paused reason of the instance: "client_pause" means trigger byCLIENT PAUSE, "shutdown_in_progress", "failover_in_progress" and "none" means no clients are paused. Added in Valkey 8.1.paused_actions: The current paused actions of the instance: "all" means all clients are paused, "write" means clients executing write commands are paused, and "none" means no clients are paused. Added in Valkey 8.1.paused_timeout_milliseconds: The remaining time of the paused actions. Added in Valkey 8.1.
Here is the meaning of all fields in the memory section:
used_memory: Total number of bytes allocated by Valkey using its allocator (either standard libc, jemalloc, or an alternative allocator such as tcmalloc)used_memory_human: Human readable representation of previous valueused_memory_rss: Number of bytes that Valkey allocated as seen by the operating system (a.k.a resident set size). This is the number reported by tools such astop(1)andps(1)used_memory_rss_human: Human readable representation of previous valueused_memory_peak: Peak memory consumed by Valkey (in bytes)used_memory_peak_human: Human readable representation of previous valueused_memory_peak_perc: The percentage ofused_memory_peakout ofused_memoryused_memory_overhead: The sum in bytes of all overheads that the server allocated for managing its internal data structuresused_memory_startup: Initial amount of memory consumed by Valkey at startup in bytesused_memory_dataset: The size in bytes of the dataset (used_memory_overheadsubtracted fromused_memory)used_memory_dataset_perc: The percentage ofused_memory_datasetout of the net memory usage (used_memoryminusused_memory_startup)total_system_memory: The total amount of memory that the Valkey host hastotal_system_memory_human: Human readable representation of previous valueused_memory_lua: Number of bytes used by the Lua engine for EVAL scripts. Deprecated, renamed toused_memory_vm_evalused_memory_vm_eval: Number of bytes used by the script VM engines for EVAL framework (not part of used_memory).used_memory_lua_human: Human readable representation of previous value. Deprecated.used_memory_scripts_eval: Number of bytes overhead by the EVAL scripts (part of used_memory).number_of_cached_scripts: The number of EVAL scripts cached by the server.number_of_functions: The number of functions.number_of_libraries: The number of libraries.used_memory_vm_functions: Number of bytes used by the script VM engines for Functions framework (not part of used_memory).used_memory_vm_total:used_memory_vm_eval+used_memory_vm_functions(not part of used_memory).used_memory_vm_total_human: Human readable representation of previous value.used_memory_functions: Number of bytes overhead by Function scripts (part of used_memory).used_memory_scripts:used_memory_scripts_eval+used_memory_functions(part of used_memory).used_memory_scripts_human: Human readable representation of previous valuemaxmemory: The value of themaxmemoryconfiguration directivemaxmemory_human: Human readable representation of previous valuemaxmemory_policy: The value of themaxmemory-policyconfiguration directivemem_fragmentation_ratio: Ratio betweenused_memory_rssandused_memory. Note that this doesn't only includes fragmentation, but also other process overheads (see theallocator_*metrics), and also overheads like code, shared libraries, stack, etc.mem_fragmentation_bytes: Delta betweenused_memory_rssandused_memory. Note that when the total fragmentation bytes is low (few megabytes), a high ratio (e.g. 1.5 and above) is not an indication of an issue.allocator_frag_ratio:: Ratio betweenallocator_activeandallocator_allocated. This is the true (external) fragmentation metric (notmem_fragmentation_ratio).allocator_frag_bytesDelta betweenallocator_activeandallocator_allocated. See note aboutmem_fragmentation_bytes.allocator_rss_ratio: Ratio betweenallocator_residentandallocator_active. This usually indicates pages that the allocator can and probably will soon release back to the OS.allocator_rss_bytes: Delta betweenallocator_residentandallocator_activerss_overhead_ratio: Ratio betweenused_memory_rss(the process RSS) andallocator_resident. This includes RSS overheads that are not allocator or heap related.rss_overhead_bytes: Delta betweenused_memory_rss(the process RSS) andallocator_residentallocator_allocated: Total bytes allocated form the allocator, including internal-fragmentation. Normally the same asused_memory.allocator_active: Total bytes in the allocator active pages, this includes external-fragmentation.allocator_resident: Total bytes resident (RSS) in the allocator, this includes pages that can be released to the OS (byMEMORY PURGE, or just waiting).allocator_muzzy: Total bytes of 'muzzy' memory (RSS) in the allocator. Muzzy memory is memory that has been freed, but not yet fully returned to the operating system. It can be reused immediately when needed or reclaimed by the OS when system pressure increases.mem_not_counted_for_evict: Used memory that's not counted for key eviction. This is basically transient replica and AOF buffers.mem_clients_slaves: Memory used by replica clients - Replica buffers share memory with the replication backlog, so this field can show 0 when replicas don't trigger an increase of memory usage.mem_clients_normal: Memory used by normal clientsmem_cluster_links: Memory used by links to peers on the cluster bus when cluster mode is enabled.mem_aof_buffer: Transient memory used for AOF and AOF rewrite buffersmem_replication_backlog: Memory used by replication backlogmem_total_replication_buffers: Total memory consumed for replication buffers. Starting with Valkey 9.1, it also includesmem_replicas_repl_buffer.mem_replicas_repl_buffer: Total memory consumed by the replicas replication buffer on replica side during the dual channel replication. Added in Valkey 9.1.mem_allocator: Memory allocator, chosen at compile time.mem_overhead_db_hashtable_rehashing: Temporary memory overhead of database dictionaries currently being rehashed - Added in 8.0.active_defrag_running: Whenactivedefragis enabled, this indicates whether defragmentation is currently active, and the CPU percentage it intends to utilize.lazyfree_pending_objects: The number of objects waiting to be freed (as a result of callingUNLINK, orFLUSHDBandFLUSHALLwith the ASYNC option)lazyfreed_objects: The number of objects that have been lazy freed.
Ideally, the used_memory_rss value should be only slightly higher than
used_memory.
When rss >> used, a large difference may mean there is (external) memory fragmentation, which can be evaluated by checking
allocator_frag_ratio, allocator_frag_bytes.
When used >> rss, it means part of Valkey memory has been swapped off by the
operating system: expect some significant latencies.
Because Valkey does not have control over how its allocations are mapped to
memory pages, high used_memory_rss is often the result of a spike in memory
usage.
When Valkey frees memory, the memory is given back to the allocator, and the
allocator may or may not give the memory back to the system. There may be
a discrepancy between the used_memory value and memory consumption as
reported by the operating system. It may be due to the fact memory has been
used and released by Valkey, but not given back to the system. The
used_memory_peak value is generally useful to check this point.
Additional introspective information about the server's memory can be obtained
by referring to the MEMORY STATS command and the MEMORY DOCTOR.
Here is the meaning of all fields in the persistence section:
loading: Flag indicating if the load of a dump file is on-goingasync_loading: Currently loading replication data-set asynchronously while serving old data. This meansrepl-diskless-loadis enabled and set toswapdb.current_cow_peak: The peak size in bytes of copy-on-write memory while a child fork is runningcurrent_cow_size: The size in bytes of copy-on-write memory while a child fork is runningcurrent_cow_size_age: The age, in seconds, of thecurrent_cow_sizevalue.current_fork_perc: The percentage of progress of the current fork process. For AOF and RDB forks it is the percentage ofcurrent_save_keys_processedout ofcurrent_save_keys_total.current_save_keys_processed: Number of keys processed by the current save operationcurrent_save_keys_total: Number of keys at the beginning of the current save operationrdb_changes_since_last_save: Number of changes since the last RDB file saverdb_bgsave_in_progress: Flag indicating a RDB save is on-going, including a diskless replication RDB saverdb_last_save_time: Epoch-based timestamp of last successful RDB file saverdb_last_bgsave_status: Status of the last RDB file save operationrdb_last_bgsave_time_sec: Duration of the last RDB save operation in seconds, including a diskless replication RDB saverdb_current_bgsave_time_sec: Duration of the on-going RDB save operation if any, including a diskless replication RDB saverdb_last_cow_size: The size in bytes of copy-on-write memory during the last RDB save operationrdb_last_load_keys_expired: Number of volatile keys deleted during the last RDB loading.rdb_last_load_keys_loaded: Number of keys loaded during the last RDB loading.aof_enabled: Flag indicating AOF logging is activatedaof_rewrite_in_progress: Flag indicating a AOF rewrite operation is on-goingaof_rewrite_scheduled: Flag indicating an AOF rewrite operation will be scheduled once the on-going RDB save is complete.aof_last_rewrite_time_sec: Duration of the last AOF rewrite operation in secondsaof_current_rewrite_time_sec: Duration of the on-going AOF rewrite operation if anyaof_last_bgrewrite_status: Status of the last AOF rewrite operationaof_last_write_status: Status of the last write operation to the AOFaof_last_cow_size: The size in bytes of copy-on-write memory during the last AOF rewrite operationmodule_fork_in_progress: Flag indicating a module fork is on-goingmodule_fork_last_cow_size: The size in bytes of copy-on-write memory during the last module fork operationaof_rewrites: Number of AOF rewrites performed since startuprdb_saves: Number of RDB snapshots performed since startup
rdb_changes_since_last_save refers to the number of operations that produced
some kind of changes in the dataset since the last time either SAVE or
BGSAVE was called.
If AOF is activated, these additional fields will be added:
aof_current_size: AOF current file sizeaof_base_size: AOF file size on latest startup or rewriteaof_pending_rewrite: Flag indicating an AOF rewrite operation will be scheduled once the on-going RDB save is complete.aof_buffer_length: Size of the AOF bufferaof_pending_bio_fsync: Number of fsync pending jobs in background I/O queueaof_delayed_fsync: Delayed fsync counter
If a load operation is on-going, these additional fields will be added:
loading_start_time: Epoch-based timestamp of the start of the load operationloading_total_bytes: Total file sizeloading_rdb_used_mem: The memory usage of the server that had generated the RDB file at the time of the file's creationloading_loaded_bytes: Number of bytes already loadedloading_loaded_perc: Same value expressed as a percentageloading_eta_seconds: ETA in seconds for the load to be complete
Here is the meaning of all fields in the stats section:
total_connections_received: Total number of connections accepted by the servertotal_commands_processed: Total number of commands processed by the serverinstantaneous_ops_per_sec: Number of commands processed per secondtotal_net_input_bytes: The total number of bytes read from the networktotal_net_output_bytes: The total number of bytes written to the networktotal_net_repl_input_bytes: The total number of bytes read from the network for replication purposestotal_net_repl_output_bytes: The total number of bytes written to the network for replication purposesinstantaneous_input_kbps: The network's read rate per second in KB/secinstantaneous_output_kbps: The network's write rate per second in KB/secinstantaneous_input_repl_kbps: The network's read rate per second in KB/sec for replication purposesinstantaneous_output_repl_kbps: The network's write rate per second in KB/sec for replication purposesrejected_connections: Number of connections rejected because ofmaxclientslimitsync_full: The number of full resyncs with replicassync_partial_ok: The number of accepted partial resync requestssync_partial_err: The number of denied partial resync requestsexpired_keys: Total number of key expiration eventsexpired_stale_perc: The percentage of keys probably expiredexpired_time_cap_reached_count: The count of times that active expiry cycles have stopped earlyexpire_cycle_cpu_milliseconds: The cumulative amount of time spent on active expiry cyclesevicted_keys: Number of evicted keys due tomaxmemorylimitevicted_clients: Number of evicted clients due tomaxmemory-clientslimit.evicted_scripts: Number of evicted EVAL scripts due to LRU policy, seeEVALfor more details. Added in Valkey 8.0.total_eviction_exceeded_time: Total timeused_memorywas greater thanmaxmemorysince server startup, in millisecondscurrent_eviction_exceeded_time: The time passed sinceused_memorylast rose abovemaxmemory, in millisecondskeyspace_hits: Number of successful lookup of keys in the main dictionarykeyspace_misses: Number of failed lookup of keys in the main dictionarypubsub_channels: Global number of pub/sub channels with client subscriptionspubsub_patterns: Global number of pub/sub pattern with client subscriptionspubsubshard_channels: Global number of pub/sub shard channels with client subscriptions.latest_fork_usec: Duration of the latest fork operation in microsecondstotal_forks: Total number of fork operations since the server startmigrate_cached_sockets: The number of sockets open forMIGRATEpurposesslave_expires_tracked_keys: The number of keys tracked for expiry purposes (applicable only to writable replicas)active_defrag_hits: Number of value reallocations performed by active the defragmentation processactive_defrag_misses: Number of aborted value reallocations started by the active defragmentation processactive_defrag_key_hits: Number of keys that were actively defragmentedactive_defrag_key_misses: Number of keys that were skipped by the active defragmentation processtotal_active_defrag_time: Total time memory fragmentation was over the limit, in millisecondscurrent_active_defrag_time: The time passed since memory fragmentation last was over the limit, in millisecondstracking_total_keys: Number of keys being tracked by the servertracking_total_items: Number of items, that is the sum of clients number for each key, that are being trackedtracking_total_prefixes: Number of tracked prefixes in server's prefix table (only applicable for broadcast mode)unexpected_error_replies: Number of unexpected error replies, that are types of errors from an AOF load or replicationtotal_error_replies: Total number of issued error replies, that is the sum of rejected commands (errors prior command execution) and failed commands (errors within the command execution)dump_payload_sanitizations: Total number of dump payload deep integrity validations (seesanitize-dump-payloadconfig).total_reads_processed: Total number of read events processedtotal_writes_processed: Total number of write events processedio_threaded_reads_processed: Number of read events processed by the I/O threads.io_threaded_writes_processed: Number of write events processed by the I/O threads.io_threaded_total_prefetch_batches: Indicate how many prefetch batches were executed in order to prefetch keys before executing commands.io_threaded_total_prefetch_entries: The total number of dict entries that were prefetched. Each batch can contain multiple entries, the ratio entries/batches indicates how many entries were prefetched per batch on average.io_threaded_poll_processed: Total poll system calls performed by the I/O threads.io_threaded_freed_objects: The total number of objects freed by the I/O threads.client_query_buffer_limit_disconnections: Total number of disconnections due to client reaching query buffer limitclient_output_buffer_limit_disconnections: Total number of disconnections due to client reaching output buffer limitreply_buffer_shrinks: Total number of output buffer shrinksreply_buffer_expands: Total number of output buffer expandseventloop_cycles: Total number of eventloop cycleseventloop_duration_sum: Total time spent in the eventloop in microseconds (including I/O and command processing)eventloop_duration_cmd_sum: Total time spent on executing commands in microsecondsinstantaneous_eventloop_cycles_per_sec: Number of eventloop cycles per secondinstantaneous_eventloop_duration_usec: Average time spent in a single eventloop cycle in microsecondsacl_access_denied_auth: Number of authentication failuresacl_access_denied_cmd: Number of commands rejected because of access denied to the commandacl_access_denied_key: Number of commands rejected because of access denied to a keyacl_access_denied_channel: Number of commands rejected because of access denied to a channelacl_access_denied_tls_cert: Number of failed authentications using automatic TLS clients authentication feature. Added in Valkey 9.0.
Here is the meaning of all fields in the replication section:
role: Value is "master" if the instance is replica of no one, or "slave" if the instance is a replica of some primary instance. Note that a replica can be primary of another replica (chained replication).replicas_waiting_psync: The number of replicas waiting for partial resynchronization during the dual-channel replication. Added in Valkey 8.0.master_failover_state: The state of an ongoing failover, if any.master_replid: The replication ID of the Valkey server.master_replid2: The secondary replication ID, used for PSYNC after a failover.master_repl_offset: The server's current replication offsetsecond_repl_offset: The offset up to which replication IDs are acceptedrepl_backlog_active: Flag indicating replication backlog is activerepl_backlog_size: The value of the replication backlog bufferrepl-backlog-sizeconfiguration itemrepl_backlog_first_byte_offset: Replication "primary offset" of first byte in the replication backlog bufferrepl_backlog_histlen: Size in bytes of the data in the replication backlog buffer
If the instance is a replica, these additional fields are provided:
master_host: Host or IP address of the primarymaster_port: Primary listening TCP portmaster_link_status: Status of the link (up/down)master_last_io_seconds_ago: Number of seconds since the last interaction with primarylast_successful_sync_duration_ms: The duration of the last successful full sync in milliseconds, or -1 if no successful sync has occurredmaster_sync_in_progress: Indicate the primary is syncing to the replicaslave_read_repl_offset: The read replication offset of the replica instance.slave_repl_offset: The replication offset of the replica instancereplicas_repl_buffer_size: Currently accumulated replication stream data in bytes during the dual-channel replication. Added in Valkey 8.0.replicas_repl_buffer_peak: Peak number of bytes accumulated replication stream data during the lifetime of this instance. Added in Valkey 8.0.slave_priority: The priority of the instance as a candidate for failoverslave_read_only: Flag indicating if the replica is read-onlyreplica_announced: Flag indicating if the replica is announced by Sentinel.
If a SYNC operation is on-going, these additional fields are provided:
master_sync_total_bytes: Total number of bytes that need to be transferred. this may be 0 when the size is unknown (for example, when therepl-diskless-syncconfiguration directive is used)master_sync_read_bytes: Number of bytes already transferredmaster_sync_left_bytes: Number of bytes left before syncing is complete (may be negative whenmaster_sync_total_bytesis 0)master_sync_perc: The percentagemaster_sync_read_bytesfrommaster_sync_total_bytes, or an approximation that usesloading_rdb_used_memwhenmaster_sync_total_bytesis 0master_sync_last_io_seconds_ago: Number of seconds since last transfer I/O during a SYNC operation
If the link between primary and replica is down, an additional field is provided:
master_link_down_since_seconds: Number of seconds since the link is down
The following field is always provided:
connected_slaves: Number of connected replicas
If the server is configured with the min-replicas-to-write directive, an additional field is provided:
min_slaves_good_slaves: Number of replicas currently considered good
For each replica, the following line is added:
slaveXXX:ip=xxx,port=xxx,state=xxx,offset=xxx,lag=xxx,type=xxx
state represents the state of the replica client and can be one of the following strings.
wait_bgsave: The replica is waiting for the primary to generate the RDB file.send_bulk: Primary is sending the RDB file to replica.online: RDB file transmitted, sending just updates.rdb_transmitted: RDB file transmitted, this state is used for the rdb-channel during dual-channel replication when the RDB transfer is complete but the replica has not yet established its main connection. Added in Valkey 9.1.bg_transfer: Main channel of a replica during dual-channel replication. Changes toonlineonce sync is complete. Added in Valkey 8.0.
type added in Valkey 8.0, represents the type of the replica client and can be one of the following strings.
replica: Normal replica client.main-channel: Main channel of a replica which uses dual-channel replication. Once dual channel replication is complete, the type will becomereplica.rdb-channel: RDB channel of a replica which uses dual-channel replication. Once dual channel replication is complete, the replica client will disconnect.
Here is the meaning of all fields in the cpu section:
used_cpu_sys: System CPU consumed by the Valkey server, which is the sum of system CPU consumed by all threads of the server process (main thread and background threads)used_cpu_user: User CPU consumed by the Valkey server, which is the sum of user CPU consumed by all threads of the server process (main thread and background threads)used_cpu_sys_children: System CPU consumed by the background processesused_cpu_user_children: User CPU consumed by the background processesused_cpu_sys_main_thread: System CPU consumed by the Valkey server main threadused_cpu_user_main_thread: User CPU consumed by the Valkey server main threadused_active_time_main_thread: Clock time the Valkey server main thread has spent on actual work, excluding time waiting for work.used_active_time_io_thread_N(where N is a number from 1 to the configured number of I/O threads): Clock time each I/O thread spends doing actual work, excluding time waiting for work.
The fields used_active_time_main_thread and used_active_time_io_thread_N
were added in Valkey 9.1. They are a better indication than the CPU time metrics
of the spare capacity of each thread, because Valkey uses busy-waiting when I/O
threads are used, which makes the CPU time appear to be near 100% even if the
server has spare capacity for handling more commands.
The active time fields grow linearly with the server load. To understand how to interpret them, consider this example: If the main thread's used active time increases 5 seconds between two INFO calls 10 seconds apart, it means the main thread has spent half of the time executing commands and the other half waiting. It means that it's running at 50% of its capacity.
The commandstats section provides statistics based on the command type, including the number of calls that reached command execution (not rejected), the total CPU time consumed by these commands, the average CPU consumed per command execution, the number of rejected calls (errors prior command execution), and the number of failed calls (errors within the command execution).
For each command type, the following line is added:
cmdstat_XXX:calls=XXX,usec=XXX,usec_per_call=XXX,rejected_calls=XXX,failed_calls=XXX
The latencystats section provides latency percentile distribution statistics based on the command type.
By default, the exported latency percentiles are the p50, p99, and p999.
If you need to change the exported percentiles, use CONFIG SET latency-tracking-info-percentiles "50.0 99.0 99.9".
This section requires the extended latency monitoring feature to be enabled (by default it's enabled).
If you need to enable it, use CONFIG SET latency-tracking yes.
For each command type, the following line is added:
latency_percentiles_usec_XXX: p<percentile 1>=<percentile 1 value>,p<percentile 2>=<percentile 2 value>,...
The errorstats section enables keeping track of the different errors that occurred within Valkey,
based upon the reply error prefix ( The first word after the "-", up to the first space. Example: ERR ).
For each error type, the following line is added:
errorstat_XXX:count=XXX
The sentinel section is only available in Valkey Sentinel instances. It consists of the following fields:
sentinel_masters: Number of Valkey primaries monitored by this Sentinel instancesentinel_tilt: A value of 1 means this sentinel is in TILT modesentinel_tilt_since_seconds: Duration in seconds of current TILT, or -1 if not TILTed.sentinel_total_tilt: The number of times this sentinel has been in TILT mode since running. Added in 9.0.sentinel_running_scripts: The number of scripts this Sentinel is currently executingsentinel_scripts_queue_length: The length of the queue of user scripts that are pending executionsentinel_simulate_failure_flags: Flags for theSENTINEL SIMULATE-FAILUREcommand
The cluster section currently only contains a unique field:
cluster_enabled: Indicate Valkey cluster is enabled
The modules section contains additional information about loaded modules if the modules provide it. The field part of properties lines in this section is always prefixed with the module's name.
The keyspace section provides statistics on the main dictionary of each database. The statistics are the number of keys, and the number of keys with an expiration.
For each database, the following line is added:
dbXXX:keys=XXX,expires=XXX
The debug section contains experimental metrics, which might change or get removed in future versions.
It won't be included when INFO or INFO ALL are called, and it is returned only when INFO DEBUG is used.
eventloop_duration_aof_sum: Total time spent on flushing AOF in eventloop in microsecondseventloop_duration_cron_sum: Total time consumption of cron in microseconds (including serverCron and beforeSleep, but excluding IO and AOF flushing)eventloop_duration_max: The maximal time spent in a single eventloop cycle in microsecondseventloop_cmd_per_cycle_max: The maximal number of commands processed in a single eventloop cycle
A note about the word slave used in this man page: If not for backward compatibility, the Valkey project no longer uses the words "master" and "slave". Unfortunately in the given commands these words are part of the protocol, so we'll be able to remove such occurrences only when this API will be naturally deprecated.
Modules generated sections: Starting with Valkey 6, modules can inject their info into the INFO command, these are excluded by default even when the all argument is provided (it will include a list of loaded modules but not their generated info fields). To get these you must use either the modules argument or everything.,
json.arrappend
Append one or more values to the array values at the path.
Examples
Enhanced path syntax:
127.0.0.1:6379> JSON.SET k1 . '[[], ["a"], ["a", "b"]]'
OK
127.0.0.1:6379> JSON.ARRAPPEND k1 $[*] '"c"'
1) (integer) 1
2) (integer) 2
3) (integer) 3
127.0.0.1:6379> JSON.GET k1
"[[\"c\"],[\"a\",\"c\"],[\"a\",\"b\",\"c\"]]"
Restricted path syntax:
127.0.0.1:6379> JSON.SET k1 . '[[], ["a"], ["a", "b"]]'
OK
127.0.0.1:6379> JSON.ARRAPPEND k1 [-1] '"c"'
(integer) 3
127.0.0.1:6379> JSON.GET k1
"[[],[\"a\"],[\"a\",\"b\",\"c\"]]"
json.arrindex
Search for the first occurrence of a scalar JSON value in the arrays at the path.
- Out of range errors are treated by rounding the index to the array's start and end.
- If start > end, return -1 (not found).
Examples
Enhanced path syntax:
127.0.0.1:6379> JSON.SET k1 . '[[], ["a"], ["a", "b"], ["a", "b", "c"]]'
OK
127.0.0.1:6379> JSON.ARRINDEX k1 $[*] '"b"'
1) (integer) -1
2) (integer) -1
3) (integer) 1
4) (integer) 1
Restricted path syntax:
127.0.0.1:6379> JSON.SET k1 . '{"children": ["John", "Jack", "Tom", "Bob", "Mike"]}'
OK
127.0.0.1:6379> JSON.ARRINDEX k1 .children '"Tom"'
(integer) 2
json.arrinsert
Insert one or more values into the array values at path before the index.
- Inserting at index 0 prepends to the array.
- A negative index values is interpreted as starting from the end.
- The index must be in the array's boundary.
Examples
Enhanced path syntax:
127.0.0.1:6379> JSON.SET k1 . '[[], ["a"], ["a", "b"]]'
OK
127.0.0.1:6379> JSON.ARRINSERT k1 $[*] 0 '"c"'
1) (integer) 1
2) (integer) 2
3) (integer) 3
127.0.0.1:6379> JSON.GET k1
"[[\"c\"],[\"c\",\"a\"],[\"c\",\"a\",\"b\"]]"
Restricted path syntax:
127.0.0.1:6379> JSON.SET k1 . '[[], ["a"], ["a", "b"]]'
OK
127.0.0.1:6379> JSON.ARRINSERT k1 . 0 '"c"'
(integer) 4
127.0.0.1:6379> JSON.GET k1
"[\"c\",[],[\"a\"],[\"a\",\"b\"]]"
json.arrlen
Get length of the array at the path.
Examples
Enhanced path syntax:
127.0.0.1:6379> JSON.SET k1 . '[[], [\"a\"], [\"a\", \"b\"], [\"a\", \"b\", \"c\"]]'
(error) SYNTAXERR Failed to parse JSON string due to syntax error
127.0.0.1:6379> JSON.SET k1 . '[[], ["a"], ["a", "b"], ["a", "b", "c"]]'
OK
127.0.0.1:6379> JSON.ARRLEN k1 $[*]
1) (integer) 0
2) (integer) 1
3) (integer) 2
4) (integer) 3
127.0.0.1:6379> JSON.SET k2 . '[[], "a", ["a", "b"], ["a", "b", "c"], 4]'
OK
127.0.0.1:6379> JSON.ARRLEN k2 $[*]
1) (integer) 0
2) (nil)
3) (integer) 2
4) (integer) 3
5) (nil)
127.0.0.1:6379> JSON.SET k1 . '[[], ["a"], ["a", "b"], ["a", "b", "c"]]'
OK
127.0.0.1:6379> JSON.ARRLEN k1 [*]
(integer) 0
127.0.0.1:6379> JSON.ARRLEN k1 $[3]
1) (integer) 3
127.0.0.1:6379> JSON.SET k2 . '[[], "a", ["a", "b"], ["a", "b", "c"], 4]'
OK
127.0.0.1:6379> JSON.ARRLEN k2 [*]
(integer) 0
127.0.0.1:6379> JSON.ARRLEN k2 $[1]
1) (nil)
127.0.0.1:6379> JSON.ARRLEN k2 $[2]
1) (integer) 2
json.arrpop
Remove and return element at the index from the array. Popping an empty array returns null.
Examples
Enhanced path syntax:
127.0.0.1:6379> JSON.SET k1 . '[[], ["a"], ["a", "b"]]'
OK
127.0.0.1:6379> JSON.ARRPOP k1 $[*]
1) (nil)
2) "\"a\""
3) "\"b\""
127.0.0.1:6379> JSON.GET k1
"[[],[],[\"a\"]]"
Restricted path syntax:
127.0.0.1:6379> JSON.SET k1 . '[[], ["a"], ["a", "b"]]'
OK
127.0.0.1:6379> JSON.ARRPOP k1
"[\"a\",\"b\"]"
127.0.0.1:6379> JSON.GET k1
"[[],[\"a\"]]"
127.0.0.1:6379> JSON.SET k2 . '[[], ["a"], ["a", "b"]]'
OK
127.0.0.1:6379> JSON.ARRPOP k2 . 0
"[]"
127.0.0.1:6379> JSON.GET k2
"[[\"a\"],[\"a\",\"b\"]]"
json.arrtrim
Trim arrays at the path so that it becomes subarray [start, end], both inclusive.
- If the array is empty, do nothing, return 0.
- If start < 0, treat it as 0.
- If end >= size (size of the array), treat it as size-1.
- If start >= size or start > end, empty the array and return 0.
Examples
Enhanced path syntax:
127.0.0.1:6379> JSON.SET k1 . '[[], ["a"], ["a", "b"], ["a", "b", "c"]]'
OK
127.0.0.1:6379> JSON.ARRTRIM k1 $[*] 0 1
1) (integer) 0
2) (integer) 1
3) (integer) 2
4) (integer) 2
127.0.0.1:6379> JSON.GET k1
"[[],[\"a\"],[\"a\",\"b\"],[\"a\",\"b\"]]"
Restricted path syntax:
127.0.0.1:6379> JSON.SET k1 . '{"children": ["John", "Jack", "Tom", "Bob", "Mike"]}'
OK
127.0.0.1:6379> JSON.ARRTRIM k1 .children 0 1
(integer) 2
127.0.0.1:6379> JSON.GET k1 .children
"[\"John\",\"Jack\"]"
json.clear
Clear the arrays or objects at the path.
Examples
127.0.0.1:6379> JSON.SET k1 . '[[], [0], [0,1], [0,1,2], 1, true, null, "d"]'
OK
127.0.0.1:6379> JSON.CLEAR k1 $[*]
(integer) 6
127.0.0.1:6379> JSON.CLEAR k1 $[*]
(integer) 0
127.0.0.1:6379> JSON.SET k2 . '{"children": ["John", "Jack", "Tom", "Bob", "Mike"]}'
OK
127.0.0.1:6379> JSON.CLEAR k2 .children
(integer) 1
127.0.0.1:6379> JSON.GET k2 .children
"[]"
json.debug
Report information. Supported subcommands are:
- MEMORY [path] - report memory usage in bytes of a JSON value. Path defaults to the root if not provided.
- DEPTH - report the maximum path depth of the JSON document.
- FIELDS [path] - report the number of fields at the specified document path. Path defaults to the root if not provided. Each non-container JSON value counts as one field. Objects and arrays recursively count one field for each of their containing JSON values. Each container value, except the root container, counts as one additional field.
- HELP - print help messages of the command.
Examples
Enhanced path syntax:
127.0.0.1:6379> JSON.SET k1 . '[1, 2.3, "foo", true, null, {}, [], {"a":1, "b":2}, [1,2,3]]'
OK
127.0.0.1:6379> JSON.DEBUG MEMORY k1 $[*]
1) (integer) 16
2) (integer) 16
3) (integer) 19
4) (integer) 16
5) (integer) 16
6) (integer) 16
7) (integer) 16
8) (integer) 50
9) (integer) 64
127.0.0.1:6379> JSON.DEBUG FIELDS k1 $[*]
1) (integer) 1
2) (integer) 1
3) (integer) 1
4) (integer) 1
5) (integer) 1
6) (integer) 0
7) (integer) 0
8) (integer) 2
9) (integer) 3
Restricted path syntax:
127.0.0.1:6379> JSON.SET k1 . '{"firstName":"John","lastName":"Smith","age":27,"weight":135.25,"isAlive":true,"address":{"street":"21 2nd Street","city":"New York","state":"NY","zipcode":"10021-3100"},"phoneNumbers":[{"type":"home","number":"212 555-1234"},{"type":"office","number":"646 555-4567"}],"children":[],"spouse":null}'
OK
127.0.0.1:6379> JSON.DEBUG MEMORY k1
(integer) 632
127.0.0.1:6379> JSON.DEBUG MEMORY k1 .phoneNumbers
(integer) 166
127.0.0.1:6379> JSON.DEBUG FIELDS k1
(integer) 19
127.0.0.1:6379> JSON.DEBUG FIELDS k1 .address
(integer) 4
127.0.0.1:6379> JSON.DEBUG HELP
1) JSON.DEBUG MEMORY <key> [path] - report memory size (bytes) of the JSON element. Path defaults to root if not provided.
2) JSON.DEBUG FIELDS <key> [path] - report number of fields in the JSON element. Path defaults to root if not provided.
3) JSON.DEBUG DEPTH <key> - report depth of JSON doc.
3) JSON.DEBUG HELP - print help message.
json.del
Delete the JSON values at the path in a document key. If the path is the root path, it is equivalent to deleting the key from Valkey.
Examples
Enhanced path syntax:
127.0.0.1:6379> JSON.SET k1 . '{"a":{}, "b":{"a":1}, "c":{"a":1, "b":2}, "d":{"a":1, "b":2, "c":3}, "e": [1,2,3,4,5]}'
OK
127.0.0.1:6379> JSON.DEL k1 $.d.*
(integer) 3
127.0.0.1:6379> JSON.GET k1
"{\"a\":{},\"b\":{\"a\":1},\"c\":{\"a\":1,\"b\":2},\"d\":{},\"e\":[1,2,3,4,5]}"
127.0.0.1:6379> JSON.DEL k1 $.e[*]
(integer) 5
127.0.0.1:6379> JSON.GET k1
"{\"a\":{},\"b\":{\"a\":1},\"c\":{\"a\":1,\"b\":2},\"d\":{},\"e\":[]}"
Restricted path syntax:
127.0.0.1:6379> JSON.SET k1 . '{"a":{}, "b":{"a":1}, "c":{"a":1, "b":2}, "d":{"a":1, "b":2, "c":3}, "e": [1,2,3,4,5]}'
OK
127.0.0.1:6379> JSON.DEL k1 .d.*
(integer) 3
127.0.0.1:6379> JSON.GET k1
"{\"a\":{},\"b\":{\"a\":1},\"c\":{\"a\":1,\"b\":2},\"d\":{},\"e\":[1,2,3,4,5]}"
127.0.0.1:6379> JSON.DEL k1 .e[*]
(integer) 5
127.0.0.1:6379> JSON.GET k1
"{\"a\":{},\"b\":{\"a\":1},\"c\":{\"a\":1,\"b\":2},\"d\":{},\"e\":[]}"
json.forget
An alias of JSON.DEL
json.get
Get the serialized JSON at one or multiple paths.
Examples
Enhanced path syntax:
127.0.0.1:6379> JSON.SET k1 . '{"firstName":"John","lastName":"Smith","age":27,"weight":135.25,"isAlive":true,"address":{"street":"21 2nd Street","city":"New York","state":"NY","zipcode":"10021-3100"},"phoneNumbers":[{"type":"home","number":"212 555-1234"},{"type":"office","number":"646 555-4567"}],"children":[],"spouse":null}'
OK
127.0.0.1:6379> JSON.GET k1 $.address.*
"[\"21 2nd Street\",\"New York\",\"NY\",\"10021-3100\"]"
127.0.0.1:6379> JSON.GET k1 indent "\t" space " " NEWLINE "\n" $.address.*
"[\n\t\"21 2nd Street\",\n\t\"New York\",\n\t\"NY\",\n\t\"10021-3100\"\n]"
127.0.0.1:6379> JSON.GET k1 $.firstName $.lastName $.age
"{\"$.firstName\":[\"John\"],\"$.lastName\":[\"Smith\"],\"$.age\":[27]}"
127.0.0.1:6379> JSON.SET k2 . '{"a":{}, "b":{"a":1}, "c":{"a":1, "b":2}}'
OK
127.0.0.1:6379> json.get k2 $..*
"[{},{\"a\":1},{\"a\":1,\"b\":2},1,1,2]"
Restricted path syntax:
127.0.0.1:6379> JSON.SET k1 . '{"firstName":"John","lastName":"Smith","age":27,"weight":135.25,"isAlive":true,"address":{"street":"21 2nd Street","city":"New York","state":"NY","zipcode":"10021-3100"},"phoneNumbers":[{"type":"home","number":"212 555-1234"},{"type":"office","number":"646 555-4567"}],"children":[],"spouse":null}'
OK
127.0.0.1:6379> JSON.GET k1 .address
"{\"street\":\"21 2nd Street\",\"city\":\"New York\",\"state\":\"NY\",\"zipcode\":\"10021-3100\"}"
127.0.0.1:6379> JSON.GET k1 indent "\t" space " " NEWLINE "\n" .address
"{\n\t\"street\": \"21 2nd Street\",\n\t\"city\": \"New York\",\n\t\"state\": \"NY\",\n\t\"zipcode\": \"10021-3100\"\n}"
127.0.0.1:6379> JSON.GET k1 .firstName .lastName .age
"{\".firstName\":\"John\",\".lastName\":\"Smith\",\".age\":27}"
json.mget
Get serialized JSON objects from multiple document keys at the specified path. Return null for non-existent keys or JSON paths.
Examples
Enhanced path syntax:
127.0.0.1:6379> JSON.SET k1 . '{"address":{"street":"21 2nd Street","city":"New York","state":"NY","zipcode":"10021"}}'
OK
127.0.0.1:6379> JSON.SET k2 . '{"address":{"street":"5 main Street","city":"Boston","state":"MA","zipcode":"02101"}}'
OK
127.0.0.1:6379> JSON.SET k3 . '{"address":{"street":"100 Park Ave","city":"Seattle","state":"WA","zipcode":"98102"}}'
OK
127.0.0.1:6379> JSON.MGET k1 k2 k3 $.address.city
1) "[\"New York\"]"
2) "[\"Boston\"]"
3) "[\"Seattle\"]"
Restricted path syntax:
127.0.0.1:6379> JSON.SET k1 . '{"address":{"street":"21 2nd Street","city":"New York","state":"NY","zipcode":"10021"}}'
OK
127.0.0.1:6379> JSON.SET k2 . '{"address":{"street":"5 main Street","city":"Boston","state":"MA","zipcode":"02101"}}'
OK
127.0.0.1:6379> JSON.SET k3 . '{"address":{"street":"100 Park Ave","city":"Seattle","state":"WA","zipcode":"98102"}}'
OK
127.0.0.1:6379> JSON.MGET k1 k2 k3 .address.city
1) "\"New York\""
2) "\"Seattle\""
3) "\"Seattle\""
json.mset
Set JSON values for multiple keys. The operation is atomic. Either all values are set or none is set.
- If the path calls for an object member:
- If the parent element does not exist, the command will return NONEXISTENT error.
- If the parent element exists but is not an object, the command will return ERROR.
- If the parent element exists and is an object:
- If the member does not exist, a new member will be appended to the parent object if and only if the parent object is the last child in the path. Otherwise, the command will return NONEXISTENT error.
- If the member exists, its value will be replaced by the JSON value.
- If the path calls for an array index:
- If the parent element does not exist, the command will return a NONEXISTENT error.
- If the parent element exists but is not an array, the command will return ERROR.
- If the parent element exists but the index is out of bounds, the command will return OUTOFBOUNDARIES error.
- If the parent element exists and the index is valid, the element will be replaced by the new JSON value.
- If the path calls for an object or array, the value (object or array) will be replaced by the new JSON value.
Examples
Enhanced path syntax:
127.0.0.1:6379> JSON.MSET k1 . '[1,2,3,4,5]' k2 . '{"a":{"a":1, "b":2, "c":3}}' k3 . '{"a": [1,2,3,4,5]}'
OK
127.0.0.1:6379> JSON.GET k1
"[1,2,3,4,5]"
127.0.0.1:6379> JSON.GET k2
"{\"a\":{\"a\":1,\"b\":2,\"c\":3}}"
127.0.0.1:6379> JSON.MSET k2 $.a.* '0' k3 $.a[*] '0'
OK
127.0.0.1:6379> JSON.GET k2
"{\"a\":{\"a\":0,\"b\":0,\"c\":0}}"
127.0.0.1:6379> JSON.GET k3
"{\"a\":[0,0,0,0,0]}"
Restricted path syntax:
127.0.0.1:6379> JSON.MSET k1 . '{"name": "John","address": {"street": "123 Main St","city": "Springfield"},"phones": ["555-1234","555-5678"]}'
OK
127.0.0.1:6379> JSON.MSET k1 .address.street '"21 2nd Street"' k1 .address.city '"New York"'
OK
127.0.0.1:6379> JSON.GET k1 .address.street
"\"21 2nd Street\""
127.0.0.1:6379> JSON.GET k1 .address.city
"\"New York\""