提交 28273394 编写于 作者: A antirez

Cluster: support to read from slave nodes.

A client can enter a special cluster read-only mode using the READONLY
command: if the client read from a slave instance after this command,
for slots that are actually served by the instance's master, the queries
will be processed without redirection, allowing clients to read from
slaves (but without any kind fo read-after-write guarantee).

The READWRITE command can be used in order to exit the readonly state.
上级 aacbba26
......@@ -3274,6 +3274,10 @@ socket_rd_err:
return;
}
/* -----------------------------------------------------------------------------
* Cluster functions related to serving / redirecting clients
* -------------------------------------------------------------------------- */
/* The ASKING command is required after a -ASK redirection.
* The client should issue ASKING before to actually send the command to
* the target instance. See the Redis Cluster specification for more
......@@ -3287,9 +3291,23 @@ void askingCommand(redisClient *c) {
addReply(c,shared.ok);
}
/* -----------------------------------------------------------------------------
* Cluster functions related to serving / redirecting clients
* -------------------------------------------------------------------------- */
/* The READONLY command is uesd by clients to enter the read-only mode.
* In this mode slaves will not redirect clients as long as clients access
* with read-only commands to keys that are served by the slave's master. */
void readonlyCommand(redisClient *c) {
if (server.cluster_enabled == 0) {
addReplyError(c,"This instance has cluster support disabled");
return;
}
c->flags |= REDIS_READONLY;
addReply(c,shared.ok);
}
/* The READWRITE command just clears the READONLY command state. */
void readwriteCommand(redisClient *c) {
c->flags &= ~REDIS_READONLY;
addReply(c,shared.ok);
}
/* Return the pointer to the cluster node that is able to serve the command.
* For the function to succeed the command should only target a single
......@@ -3385,6 +3403,16 @@ clusterNode *getNodeByQuery(redisClient *c, struct redisCommand *cmd, robj **arg
(c->flags & REDIS_ASKING || cmd->flags & REDIS_CMD_ASKING)) {
return server.cluster->myself;
}
/* Handle the read-only client case reading from a slave: if this
* node is a slave and the request is about an hash slot our master
* is serving, we can reply without redirection. */
if (c->flags & REDIS_READONLY &&
cmd->flags & REDIS_CMD_READONLY &&
server.cluster->myself->flags & REDIS_NODE_SLAVE &&
server.cluster->myself->slaveof == n)
{
return server.cluster->myself;
}
/* It's not a -ASK case. Base case: just return the right node. */
return n;
}
......@@ -1263,6 +1263,7 @@ sds getClientInfoString(redisClient *client) {
if (client->flags & REDIS_UNBLOCKED) *p++ = 'u';
if (client->flags & REDIS_CLOSE_ASAP) *p++ = 'A';
if (client->flags & REDIS_UNIX_SOCKET) *p++ = 'U';
if (client->flags & REDIS_READONLY) *p++ = 'r';
if (p == flags) *p++ = 'N';
*p++ = '\0';
......
......@@ -254,6 +254,8 @@ struct redisCommand redisCommandTable[] = {
{"restore-asking",restoreCommand,-4,"awmk",0,NULL,1,1,1,0,0},
{"migrate",migrateCommand,-6,"aw",0,NULL,0,0,0,0,0},
{"asking",askingCommand,1,"r",0,NULL,0,0,0,0,0},
{"readonly",readonlyCommand,1,"r",0,NULL,0,0,0,0,0},
{"readwrite",readwriteCommand,1,"r",0,NULL,0,0,0,0,0},
{"dump",dumpCommand,2,"ar",0,NULL,1,1,1,0,0},
{"object",objectCommand,-2,"r",0,NULL,2,2,2,0,0},
{"client",clientCommand,-2,"ar",0,NULL,0,0,0,0,0},
......
......@@ -232,6 +232,7 @@
#define REDIS_FORCE_AOF (1<<14) /* Force AOF propagation of current cmd. */
#define REDIS_FORCE_REPL (1<<15) /* Force replication of current cmd. */
#define REDIS_PRE_PSYNC (1<<16) /* Instance don't understand PSYNC. */
#define REDIS_READONLY (1<<17) /* Cluster client is in read-only state. */
/* Client block type (btype field in client structure)
* if REDIS_BLOCKED flag is set. */
......@@ -1397,6 +1398,8 @@ void clusterCommand(redisClient *c);
void restoreCommand(redisClient *c);
void migrateCommand(redisClient *c);
void askingCommand(redisClient *c);
void readonlyCommand(redisClient *c);
void readwriteCommand(redisClient *c);
void dumpCommand(redisClient *c);
void objectCommand(redisClient *c);
void clientCommand(redisClient *c);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册