diff options
author | Huang Zhw <huang_zhw@126.com> | 2022-06-14 12:32:43 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-06-13 21:32:43 -0700 |
commit | 78960ad57b8a5e6af743d789ed8fd767e37d42b8 (patch) | |
tree | 0afb27e62fe4b811a037592cce4c32b1ddc7df72 /src | |
parent | 0a2f78837d82046ec7ffe77f8a2addcb591ff4f7 (diff) | |
download | redis-78960ad57b8a5e6af743d789ed8fd767e37d42b8.tar.gz |
Throw -TRYAGAIN instead of -ASK on migrating nodes for multi-key commands when the node only has some of the keys (#9526)
* In cluster getNodeByQuery when target slot is in migrating state and
the slot lack some keys but have at least one key, should return TRYAGAIN.
Before this commit, when a node is in migrating state and recevies
multiple keys command, if some keys don't exist, the command emits
an `ASK` redirection.
After this commit, if some keys exist and some keys don't exist, the
command emits a TRYAGAIN error. If all keys don't exist, the command
emits an `ASK` redirection.
Diffstat (limited to 'src')
-rw-r--r-- | src/cluster.c | 21 |
1 files changed, 14 insertions, 7 deletions
diff --git a/src/cluster.c b/src/cluster.c index d328ede2f..0975db53a 100644 --- a/src/cluster.c +++ b/src/cluster.c @@ -6583,7 +6583,8 @@ clusterNode *getNodeByQuery(client *c, struct redisCommand *cmd, robj **argv, in int multiple_keys = 0; multiState *ms, _ms; multiCmd mc; - int i, slot = 0, migrating_slot = 0, importing_slot = 0, missing_keys = 0; + int i, slot = 0, migrating_slot = 0, importing_slot = 0, missing_keys = 0, + existing_keys = 0; /* Allow any key to be set if a module disabled cluster redirections. */ if (server.cluster_module_flags & CLUSTER_MODULE_FLAG_NO_REDIRECTION) @@ -6695,10 +6696,10 @@ clusterNode *getNodeByQuery(client *c, struct redisCommand *cmd, robj **argv, in * node until the migration completes with CLUSTER SETSLOT <slot> * NODE <node-id>. */ int flags = LOOKUP_NOTOUCH | LOOKUP_NOSTATS | LOOKUP_NONOTIFY; - if ((migrating_slot || importing_slot) && !is_pubsubshard && - lookupKeyReadWithFlags(&server.db[0], thiskey, flags) == NULL) + if ((migrating_slot || importing_slot) && !is_pubsubshard) { - missing_keys++; + if (lookupKeyReadWithFlags(&server.db[0], thiskey, flags) == NULL) missing_keys++; + else existing_keys++; } } getKeysFreeResult(&result); @@ -6742,10 +6743,16 @@ clusterNode *getNodeByQuery(client *c, struct redisCommand *cmd, robj **argv, in return myself; /* If we don't have all the keys and we are migrating the slot, send - * an ASK redirection. */ + * an ASK redirection or TRYAGAIN. */ if (migrating_slot && missing_keys) { - if (error_code) *error_code = CLUSTER_REDIR_ASK; - return server.cluster->migrating_slots_to[slot]; + /* If we have keys but we don't have all keys, we return TRYAGAIN */ + if (existing_keys) { + if (error_code) *error_code = CLUSTER_REDIR_UNSTABLE; + return NULL; + } else { + if (error_code) *error_code = CLUSTER_REDIR_ASK; + return server.cluster->migrating_slots_to[slot]; + } } /* If we are receiving the slot, and the client correctly flagged the |