See https://github.com/redis/redis/pull/9656
We need to define and document general command hints that can help clients/proxies know how to behave.
Sketch
Simple examples (for proxies):
- PING should probably be sent to all shards
- DBSIZE should be sent to all shards and be aggregated as a sum
Non-deterministic commands:
Since EVAL is no longer propagated as is (see #9812), redis no longer uses the random and to-sort flags, and they should be moved to client hints like so:
- random-output
- random-order-output (HGETALL should be here, not in random-output)
- the old COMMAND command flags (i.e. sort_for_script) will be gone (breaking change in some way)
Modules: - RM_CreateCommand (or alternative) should be able to set that flag (same as it sets the no-monitor flag and others)
other flags - blocking - might block the client for a long time (#3642) - let's use this opportunity to go over the flags exposed in addReplyFlagsForCommand, and see if anything is missing.
Final list of tips
boolean
- blocking: if found, this command has the potential to block (but not always, see
block_keywordbelow) - random-output: the output of the command is random (e.g.
RANDOMKEY,SPOP) - random-order-output: the output is not random, but comes in random order (e.g.
HGETALL,SMEMBERS)
key-value
- block_keyword: identify commands which the potential to block: the ACL category
blockingis too loose: XREAD and other commands have it, but they will only block if a specific arg was given (usuallyBLOCK <time>). it could be useful to add something likeblock_keyword:<word>, which the proxy will search in argv to determine if the command may indeed block. we could have a problem if that keyword is a keyname etc. but we can just define it as best-effort - there's probably no harm in mistaking a non-blocking command with a blocking one (but there is the harm in mistaking in the other direction). - request_policy: there are two implicit cases: 1) command goes to one shard, according to the has slots of the key(s). 2) command doesn't have keys, goes to some shard (probably the first). otherwise, we need to split the command into several shards. a partial list of options:
- ALL_SHARDS - Forward to all shards (
PING). The operation is atomic on all shards. - FEW_SHARDS - Forward to several shards, used by multi-key commands (
MSET,MGET,DEL, etc.). The operation is atomic on relevant shards only. - reply_policy: the default here is to append all replies, if there are no keys, order doesn't matter (KEYS), otherwise order by the order of keys in request (MGET). how do we aggregate commands that are sent to multiple shards? a partial list of options:
- ALL_SUCCEEDED - Return OK if all shards responded OK. Examples:
CONFIG SET,SCRIPT FLUSH - ONE_SUCCEEDED - Return OK if at least one shard responded OK. Example:
SCRIPT KILL. Used bySCRIPT LOAD. This is meant to return the script’s SHA1 digest, which can be done based on any of the shards' replies. - AGG_LOGICAL_AND - Relevant for
SCRIPT EXISTS, which returns an array of 0/1 indicating which of the provided scripts exist - AGG_LOGICAL_OR - For symmetry
- AGG_MIN - Used by
WAIT. Returns the lowest number among the ones the shards return - AGG_MAX - For symmetry
- AGG_SUM - Sums the integer values returned by the shards. Example:
DBSIZE
docs PR: https://github.com/redis/redis-doc/pull/1697 (probably the more up-to-date than the description above)
Comment From: oranagra
here's some hins: * random-output, random-order-output - https://github.com/redis/redis/pull/9812#discussion_r764821576 * blocking - https://github.com/redis/redis/issues/3642