mirror of https://mirror.osredm.com/root/redis.git
Correctly handle scripts with shebang (not read-only) on a cluster replica (#11223)
EVAL scripts are by default not considered `write` commands, so they were allowed on a replica. But when adding a shebang, they become `write` command (unless the `no-writes` flag is added). With this change we'll handle them as write commands, and reply with MOVED instead of READONLY when executed on a redis cluster replica. Co-authored-by: chendianqiang <chendianqiang@meituan.com>
This commit is contained in:
parent
87e7973c7e
commit
e42d98ed27
|
@ -6797,6 +6797,7 @@ clusterNode *getNodeByQuery(client *c, struct redisCommand *cmd, robj **argv, in
|
|||
* without redirections or errors in all the cases. */
|
||||
if (n == NULL) return myself;
|
||||
|
||||
uint64_t cmd_flags = getCommandFlags(c);
|
||||
/* Cluster is globally down but we got keys? We only serve the request
|
||||
* if it is a read command and when allow_reads_when_down is enabled. */
|
||||
if (server.cluster->state != CLUSTER_OK) {
|
||||
|
@ -6810,7 +6811,7 @@ clusterNode *getNodeByQuery(client *c, struct redisCommand *cmd, robj **argv, in
|
|||
* cluster is down. */
|
||||
if (error_code) *error_code = CLUSTER_REDIR_DOWN_STATE;
|
||||
return NULL;
|
||||
} else if (cmd->flags & CMD_WRITE) {
|
||||
} else if (cmd_flags & CMD_WRITE) {
|
||||
/* The cluster is configured to allow read only commands */
|
||||
if (error_code) *error_code = CLUSTER_REDIR_DOWN_RO_STATE;
|
||||
return NULL;
|
||||
|
@ -6848,7 +6849,7 @@ clusterNode *getNodeByQuery(client *c, struct redisCommand *cmd, robj **argv, in
|
|||
* involves multiple keys and we don't have them all, the only option is
|
||||
* to send a TRYAGAIN error. */
|
||||
if (importing_slot &&
|
||||
(c->flags & CLIENT_ASKING || cmd->flags & CMD_ASKING))
|
||||
(c->flags & CLIENT_ASKING || cmd_flags & CMD_ASKING))
|
||||
{
|
||||
if (multiple_keys && missing_keys) {
|
||||
if (error_code) *error_code = CLUSTER_REDIR_UNSTABLE;
|
||||
|
@ -6861,7 +6862,7 @@ clusterNode *getNodeByQuery(client *c, struct redisCommand *cmd, robj **argv, in
|
|||
/* Handle the read-only client case reading from a slave: if this
|
||||
* node is a slave and the request is about a hash slot our master
|
||||
* is serving, we can reply without redirection. */
|
||||
int is_write_command = (c->cmd->flags & CMD_WRITE) ||
|
||||
int is_write_command = (cmd_flags & CMD_WRITE) ||
|
||||
(c->cmd->proc == execCommand && (c->mstate.cmd_flags & CMD_WRITE));
|
||||
if (((c->flags & CLIENT_READONLY) || is_pubsubshard) &&
|
||||
!is_write_command &&
|
||||
|
|
|
@ -69,3 +69,11 @@ test "read-only blocking operations from replica" {
|
|||
assert {$res eq {foo bar}}
|
||||
$rd close
|
||||
}
|
||||
|
||||
test "reply MOVED when eval from replica for update" {
|
||||
catch {[$replica eval {#!lua
|
||||
return redis.call('del','a')
|
||||
} 1 a
|
||||
]} err
|
||||
assert {[string range $err 0 4] eq {MOVED}}
|
||||
}
|
Loading…
Reference in New Issue