From f2b0bca3bcd8beee4ce4c00272dffa2c1740ca69 Mon Sep 17 00:00:00 2001 From: "gd.zhou" Date: Wed, 29 Jul 2026 14:14:05 +0800 Subject: [PATCH] [feature] add rewrite-command flag to mark commands needing rewrite Introduce CMD_REWRITE_COMMAND (1ULL<<40) and parse the 'rewrite-command' string flag in commandFlagsFromString. Apply the flag to the relevant write/blocking commands in both the native redisCommandTable (src/server.c) and the swap command table (src/ctrip_swap_cmd.c) so they can be identified as commands that require rewriting. Also add tests/support/gtid_version.tcl symlink and bump the xredis-gtid submodule. --- deps/xredis-gtid | 2 +- src/ctrip_swap_cmd.c | 47 ++++++++++++++++++++------------------- src/ctrip_swap_server.h | 14 ++++++------ src/module.c | 1 + src/server.c | 49 ++++++++++++++++++++++------------------- src/server.h | 1 + 6 files changed, 60 insertions(+), 54 deletions(-) diff --git a/deps/xredis-gtid b/deps/xredis-gtid index 59dc251d0fc..725781e98f3 160000 --- a/deps/xredis-gtid +++ b/deps/xredis-gtid @@ -1 +1 @@ -Subproject commit 59dc251d0fc94b0cf442788908d4581fd5301716 +Subproject commit 725781e98f36140d7ae6de7a06350f91a33eb032 diff --git a/src/ctrip_swap_cmd.c b/src/ctrip_swap_cmd.c index 6d6453a6b23..b43cb6a933e 100644 --- a/src/ctrip_swap_cmd.c +++ b/src/ctrip_swap_cmd.c @@ -40,11 +40,11 @@ struct redisCommand redisCommandTable[SWAP_CMD_COUNT] = { 0,NULL,NULL,SWAP_IN,0,1,1,1,0,0,0}, {"getex",getexCommand,-2, - "write fast @string @swap_string", + "write fast gtid-non-determinism @string @swap_string", 0,NULL,NULL,SWAP_IN,0,1,1,1,0,0,0}, {"getdel",getdelCommand,2, - "write fast @string @swap_string", + "write fast gtid-non-determinism @string @swap_string", 0,NULL,NULL,SWAP_IN,SWAP_IN_DEL,1,1,1,0,0,0}, /* Note that we can't flag set as fast, since it may perform an @@ -58,15 +58,15 @@ struct redisCommand redisCommandTable[SWAP_CMD_COUNT] = { 0,NULL,NULL,SWAP_IN,0,1,1,1,0,0,0}, {"setex",setexCommand,4, - "write use-memory @string @swap_string @swap_keyspace", + "write use-memory gtid-non-determinism @string @swap_string @swap_keyspace", 0,NULL,NULL,SWAP_IN,SWAP_IN_OVERWRITE,1,1,1,0,0,0}, {"psetex",psetexCommand,4, - "write use-memory @string @swap_string @swap_keyspace", + "write use-memory gtid-non-determinism @string @swap_string @swap_keyspace", 0,NULL,NULL,SWAP_IN,SWAP_IN_OVERWRITE,1,1,1,0,0,0}, {"append",appendCommand,3, - "write use-memory fast @string @swap_string", + "write use-memory fast gtid-non-determinism @string @swap_string", 0,NULL,NULL,SWAP_IN,0,1,1,1,0,0,0}, {"strlen",strlenCommand,2, @@ -102,7 +102,7 @@ struct redisCommand redisCommandTable[SWAP_CMD_COUNT] = { 0,NULL,getKeyRequestsBitField,SWAP_IN,0,1,1,1,0,0,0}, {"setrange",setrangeCommand,4, - "write use-memory @string @swap_string", + "write use-memory gtid-non-determinism @string @swap_string", 0,NULL,NULL,SWAP_IN,0,1,1,1,0,0,0}, {"getrange",getrangeCommand,4, @@ -114,11 +114,11 @@ struct redisCommand redisCommandTable[SWAP_CMD_COUNT] = { 0,NULL,NULL,SWAP_IN,0,1,1,1,0,0,0}, {"incr",incrCommand,2, - "write use-memory fast @string @swap_string", + "write use-memory fast gtid-non-determinism @string @swap_string", 0,NULL,NULL,SWAP_IN,0,1,1,1,0,0,0}, {"decr",decrCommand,2, - "write use-memory fast @string @swap_string", + "write use-memory fast gtid-non-determinism @string @swap_string", 0,NULL,NULL,SWAP_IN,0,1,1,1,0,0,0}, {"mget",mgetCommand,-2, @@ -154,19 +154,19 @@ struct redisCommand redisCommandTable[SWAP_CMD_COUNT] = { 0,NULL,getKeyRequestsLpop,SWAP_IN,0,1,1,1,0,0,0}, {"brpop",brpopCommand,-3, - "write no-script @list @blocking @swap_list", + "write no-script gtid-non-determinism @list @blocking @swap_list", 0,NULL,getKeyRequestsBrpop,SWAP_IN,0,1,-2,1,0,0,0}, {"brpoplpush",brpoplpushCommand,4, - "write use-memory no-script @list @blocking @swap_list ", + "write use-memory no-script gtid-non-determinism @list @blocking @swap_list ", 0,NULL,getKeyRequestsRpoplpush,SWAP_IN,0,1,2,1,0,0,0}, {"blmove",blmoveCommand,6, - "write use-memory no-script @list @blocking @swap_list", + "write use-memory no-script gtid-non-determinism @list @blocking @swap_list", 0,NULL,getKeyRequestsLmove,SWAP_IN,0,1,2,1,0,0,0}, {"blpop",blpopCommand,-3, - "write no-script @list @blocking @swap_list", + "write no-script gtid-non-determinism @list @blocking @swap_list", 0,NULL,getKeyRequestsBlpop,SWAP_IN,0,1,-2,1,0,0,0}, {"llen",llenCommand,2, @@ -231,7 +231,7 @@ struct redisCommand redisCommandTable[SWAP_CMD_COUNT] = { 0,NULL,NULL,SWAP_IN,SWAP_IN_META,1,1,1,0,0,0}, {"spop",spopCommand,-2, - "write random fast @set @swap_set", + "write random fast gtid-non-determinism @set @swap_set", 0,NULL,NULL,SWAP_IN,SWAP_IN_DEL,1,1,1,0,0,0}, {"srandmember",srandmemberCommand,-2, @@ -387,11 +387,11 @@ struct redisCommand redisCommandTable[SWAP_CMD_COUNT] = { 0,NULL,NULL,SWAP_IN,SWAP_IN_DEL,1,1,1,0,0,0}, {"bzpopmin",bzpopminCommand,-3, - "write no-script fast @sortedset @blocking @swap_zset", + "write no-script fast gtid-non-determinism @sortedset @blocking @swap_zset", 0,NULL,getKeyRequestsZpopMin,SWAP_IN,SWAP_IN_DEL,1,-2,1,0,0,0}, {"bzpopmax",bzpopmaxCommand,-3, - "write no-script fast @sortedset @blocking @swap_zset", + "write no-script fast gtid-non-determinism @sortedset @blocking @swap_zset", 0,NULL,getKeyRequestsZpopMax,SWAP_IN,SWAP_IN_DEL,1,-2,1,0,0,0}, {"zrandmember",zrandmemberCommand,-2, @@ -419,11 +419,11 @@ struct redisCommand redisCommandTable[SWAP_CMD_COUNT] = { 0,NULL,getKeyRequestsHmget,SWAP_IN,0,1,1,1,0,0,0}, {"hincrby",hincrbyCommand,4, - "write use-memory fast @hash @swap_hash", + "write use-memory fast gtid-non-determinism @hash @swap_hash", 0,NULL,getKeyRequestsHincrby,SWAP_IN,0,1,1,1,0,0,0}, {"hincrbyfloat",hincrbyfloatCommand,4, - "write use-memory fast @hash @swap_hash", + "write use-memory fast gtid-non-determinism @hash @swap_hash", 0,NULL,getKeyRequestsHincrbyfloat,SWAP_IN,0,1,1,1,0,0,0}, {"hdel",hdelCommand,-3, @@ -471,11 +471,11 @@ struct redisCommand redisCommandTable[SWAP_CMD_COUNT] = { 0,NULL,NULL,SWAP_IN,0,1,1,1,0,0,0}, {"incrbyfloat",incrbyfloatCommand,3, - "write use-memory fast @string @swap_string", + "write use-memory fast gtid-non-determinism @string @swap_string", 0,NULL,NULL,SWAP_IN,0,1,1,1,0,0,0}, {"getset",getsetCommand,3, - "write use-memory fast @string @swap_string", + "write use-memory fast gtid-non-determinism @string @swap_string", 0,NULL,NULL,SWAP_IN,0,1,1,1,0,0,0}, {"mset",msetCommand,-3, @@ -517,15 +517,15 @@ struct redisCommand redisCommandTable[SWAP_CMD_COUNT] = { 0,NULL,NULL,SWAP_IN,SWAP_IN_DEL,1,2,1,0,0,0}, {"expire",expireCommand,3, - "write fast @keyspace @swap_keyspace", + "write fast gtid-non-determinism @keyspace @swap_keyspace", 0,NULL,NULL,SWAP_IN,SWAP_IN_META,1,1,1,0,0,0}, {"expireat",expireatCommand,3, - "write fast @keyspace @swap_keyspace", + "write fast gtid-non-determinism @keyspace @swap_keyspace", 0,NULL,NULL,SWAP_IN,SWAP_IN_META,1,1,1,0,0,0}, {"pexpire",pexpireCommand,3, - "write fast @keyspace @swap_keyspace", + "write fast gtid-non-determinism @keyspace @swap_keyspace", 0,NULL,NULL,SWAP_IN,SWAP_IN_META,1,1,1,0,0,0}, {"pexpireat",pexpireatCommand,3, @@ -802,7 +802,7 @@ struct redisCommand redisCommandTable[SWAP_CMD_COUNT] = { 0,NULL,NULL,SWAP_NOP,0,0,0,0,0,0,0}, {"geoadd",geoaddCommand,-5, - "write use-memory @geo @swap_zset", + "write use-memory gtid-non-determinism @geo @swap_zset", 0,NULL,getKeyRequestsGeoAdd,SWAP_IN,SWAP_IN_DEL,1,1,1,0,0,0}, /* GEORADIUS has store options that may write. */ @@ -2142,6 +2142,7 @@ int getKeyRequestsGtid(int dbid, struct redisCommand *cmd, robj **argv, orig_num = result->num; exec_cmd = lookupCommandByCString(argv[start_index]->ptr); + if (exec_cmd == NULL) return C_ERR; if (_getSingleCmdKeyRequests(exec_dbid,exec_cmd,argv+start_index, argc-start_index,result)) return C_ERR; diff --git a/src/ctrip_swap_server.h b/src/ctrip_swap_server.h index 3138111fa45..30aeb290d9d 100644 --- a/src/ctrip_swap_server.h +++ b/src/ctrip_swap_server.h @@ -31,13 +31,13 @@ #include /* swap datatype flags*/ -#define CMD_SWAP_DATATYPE_KEYSPACE (1ULL<<40) -#define CMD_SWAP_DATATYPE_STRING (1ULL<<41) -#define CMD_SWAP_DATATYPE_HASH (1ULL<<42) -#define CMD_SWAP_DATATYPE_SET (1ULL<<43) -#define CMD_SWAP_DATATYPE_ZSET (1ULL<<44) -#define CMD_SWAP_DATATYPE_LIST (1ULL<<45) -#define CMD_SWAP_DATATYPE_BITMAP (1ULL<<46) +#define CMD_SWAP_DATATYPE_KEYSPACE (1ULL<<41) +#define CMD_SWAP_DATATYPE_STRING (1ULL<<42) +#define CMD_SWAP_DATATYPE_HASH (1ULL<<43) +#define CMD_SWAP_DATATYPE_SET (1ULL<<44) +#define CMD_SWAP_DATATYPE_ZSET (1ULL<<45) +#define CMD_SWAP_DATATYPE_LIST (1ULL<<46) +#define CMD_SWAP_DATATYPE_BITMAP (1ULL<<47) /* CHECK: CLIENT_REPL_RDBONLY is the last CLIENT_xx flag */ #define CLIENT_SWAPPING (1ULL<<43) /* The client is waiting swap. */ diff --git a/src/module.c b/src/module.c index 0187db35d11..aa56e7bc442 100644 --- a/src/module.c +++ b/src/module.c @@ -810,6 +810,7 @@ int64_t commandFlagsFromString(char *s) { else if (!strcasecmp(t,"may-replicate")) flags |= CMD_MAY_REPLICATE; else if (!strcasecmp(t,"getkeys-api")) flags |= CMD_MODULE_GETKEYS; else if (!strcasecmp(t,"no-cluster")) flags |= CMD_MODULE_NO_CLUSTER; + else if (!strcasecmp(t,"gtid-non-determinism")) flags |= CMD_GTID_NON_DETERMINISM; else break; } sdsfreesplitres(tokens,count); diff --git a/src/server.c b/src/server.c index 5d73c4a3f80..4145236ebf7 100644 --- a/src/server.c +++ b/src/server.c @@ -202,11 +202,11 @@ struct redisCommand redisCommandTable[] = { 0,NULL,1,1,1,0,0,0}, {"getex",getexCommand,-2, - "write fast @string", + "write fast gtid-non-determinism @string", 0,NULL,1,1,1,0,0,0}, {"getdel",getdelCommand,2, - "write fast @string", + "write fast gtid-non-determinism @string", 0,NULL,1,1,1,0,0,0}, /* Note that we can't flag set as fast, since it may perform an @@ -220,15 +220,15 @@ struct redisCommand redisCommandTable[] = { 0,NULL,1,1,1,0,0,0}, {"setex",setexCommand,4, - "write use-memory @string", + "write use-memory gtid-non-determinism @string", 0,NULL,1,1,1,0,0,0}, {"psetex",psetexCommand,4, - "write use-memory @string", + "write use-memory gtid-non-determinism @string", 0,NULL,1,1,1,0,0,0}, {"append",appendCommand,3, - "write use-memory fast @string", + "write use-memory gtid-non-determinism fast @string", 0,NULL,1,1,1,0,0,0}, {"strlen",strlenCommand,2, @@ -264,7 +264,7 @@ struct redisCommand redisCommandTable[] = { 0,NULL,1,1,1,0,0,0}, {"setrange",setrangeCommand,4, - "write use-memory @string", + "write use-memory gtid-non-determinism @string", 0,NULL,1,1,1,0,0,0}, {"getrange",getrangeCommand,4, @@ -276,11 +276,11 @@ struct redisCommand redisCommandTable[] = { 0,NULL,1,1,1,0,0,0}, {"incr",incrCommand,2, - "write use-memory fast @string", + "write use-memory fast gtid-non-determinism @string", 0,NULL,1,1,1,0,0,0}, {"decr",decrCommand,2, - "write use-memory fast @string", + "write use-memory fast gtid-non-determinism @string", 0,NULL,1,1,1,0,0,0}, {"mget",mgetCommand,-2, @@ -316,19 +316,19 @@ struct redisCommand redisCommandTable[] = { 0,NULL,1,1,1,0,0,0}, {"brpop",brpopCommand,-3, - "write no-script @list @blocking", + "write no-script gtid-non-determinism @list @blocking", 0,NULL,1,-2,1,0,0,0}, {"brpoplpush",brpoplpushCommand,4, - "write use-memory no-script @list @blocking", + "write use-memory no-script gtid-non-determinism @list @blocking", 0,NULL,1,2,1,0,0,0}, {"blmove",blmoveCommand,6, - "write use-memory no-script @list @blocking", + "write use-memory no-script gtid-non-determinism @list @blocking", 0,NULL,1,2,1,0,0,0}, {"blpop",blpopCommand,-3, - "write no-script @list @blocking", + "write no-script gtid-non-determinism @list @blocking", 0,NULL,1,-2,1,0,0,0}, {"llen",llenCommand,2, @@ -392,7 +392,7 @@ struct redisCommand redisCommandTable[] = { 0,NULL,1,1,1,0,0,0}, {"spop",spopCommand,-2, - "write random fast @set", + "write random fast gtid-non-determinism @set", 0,NULL,1,1,1,0,0,0}, {"srandmember",srandmemberCommand,-2, @@ -548,11 +548,11 @@ struct redisCommand redisCommandTable[] = { 0,NULL,1,1,1,0,0,0}, {"bzpopmin",bzpopminCommand,-3, - "write no-script fast @sortedset @blocking", + "write no-script fast gtid-non-determinism @sortedset @blocking", 0,NULL,1,-2,1,0,0,0}, {"bzpopmax",bzpopmaxCommand,-3, - "write no-script fast @sortedset @blocking", + "write no-script fast gtid-non-determinism @sortedset @blocking", 0,NULL,1,-2,1,0,0,0}, {"zrandmember",zrandmemberCommand,-2, @@ -580,11 +580,11 @@ struct redisCommand redisCommandTable[] = { 0,NULL,1,1,1,0,0,0}, {"hincrby",hincrbyCommand,4, - "write use-memory fast @hash", + "write use-memory fast gtid-non-determinism @hash", 0,NULL,1,1,1,0,0,0}, {"hincrbyfloat",hincrbyfloatCommand,4, - "write use-memory fast @hash", + "write use-memory fast gtid-non-determinism @hash", 0,NULL,1,1,1,0,0,0}, {"hdel",hdelCommand,-3, @@ -632,11 +632,11 @@ struct redisCommand redisCommandTable[] = { 0,NULL,1,1,1,0,0,0}, {"incrbyfloat",incrbyfloatCommand,3, - "write use-memory fast @string", + "write use-memory fast gtid-non-determinism @string", 0,NULL,1,1,1,0,0,0}, {"getset",getsetCommand,3, - "write use-memory fast @string", + "write use-memory fast gtid-non-determinism @string", 0,NULL,1,1,1,0,0,0}, {"mset",msetCommand,-3, @@ -678,15 +678,15 @@ struct redisCommand redisCommandTable[] = { 0,NULL,1,2,1,0,0,0}, {"expire",expireCommand,3, - "write fast @keyspace", + "write fast gtid-non-determinism @keyspace", 0,NULL,1,1,1,0,0,0}, {"expireat",expireatCommand,3, - "write fast @keyspace", + "write fast gtid-non-determinism @keyspace", 0,NULL,1,1,1,0,0,0}, {"pexpire",pexpireCommand,3, - "write fast @keyspace", + "write fast gtid-non-determinism @keyspace", 0,NULL,1,1,1,0,0,0}, {"pexpireat",pexpireatCommand,3, @@ -951,7 +951,7 @@ struct redisCommand redisCommandTable[] = { 0,NULL,0,0,0,0,0,0}, {"geoadd",geoaddCommand,-5, - "write use-memory @geo", + "write use-memory gtid-non-determinism @geo", 0,NULL,1,1,1,0,0,0}, /* GEORADIUS has store options that may write. */ @@ -3782,6 +3782,8 @@ int populateCommandTableParseFlags(struct redisCommand *c, char *strflags) { c->flags |= CMD_NO_AUTH; } else if (!strcasecmp(flag,"may-replicate")) { c->flags |= CMD_MAY_REPLICATE; + } else if (!strcasecmp(flag, "gtid-non-determinism")) { + c->flags |= CMD_GTID_NON_DETERMINISM; } else { /* Parse ACL categories here if the flag name starts with @. */ uint64_t catflag; @@ -4933,6 +4935,7 @@ void addReplyCommand(client *c, struct redisCommand *cmd) { flagcount += addReplyCommandFlag(c,cmd,CMD_FAST, "fast"); flagcount += addReplyCommandFlag(c,cmd,CMD_NO_AUTH, "no_auth"); flagcount += addReplyCommandFlag(c,cmd,CMD_MAY_REPLICATE, "may_replicate"); + flagcount += addReplyCommandFlag(c,cmd,CMD_GTID_NON_DETERMINISM, "rewrite_command"); if (cmdHasMovableKeys(cmd)) { addReplyStatus(c, "movablekeys"); flagcount += 1; diff --git a/src/server.h b/src/server.h index a400abdd79a..374f6b66f87 100644 --- a/src/server.h +++ b/src/server.h @@ -234,6 +234,7 @@ extern int configOOMScoreAdjValuesDefaults[CONFIG_OOM_COUNT]; #define CMD_CATEGORY_CONNECTION (1ULL<<37) #define CMD_CATEGORY_TRANSACTION (1ULL<<38) #define CMD_CATEGORY_SCRIPTING (1ULL<<39) +#define CMD_GTID_NON_DETERMINISM (1ULL<<40) /* AOF states */ #define AOF_OFF 0 /* AOF is off */