Compare commits
4
Commits
faster-info
...
nosync
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c1d10e8bb7 | ||
|
|
ede98af9da | ||
|
|
de6f74838a | ||
|
|
abbfbcf161 |
+32
@@ -300,6 +300,38 @@ repl-diskless-sync-delay 5
|
||||
#
|
||||
# repl-ping-slave-period 10
|
||||
|
||||
# WARNING: This feature is experimental, just an evaluation draft.
|
||||
#
|
||||
# No-sync replication is a special, inconistent, mode of operation for slaves
|
||||
# that is sometimes useful in caching scenarios.
|
||||
#
|
||||
# In this setup slaves, when connecting to masters, don't ask for the pre
|
||||
# existing state of the key space, so no synchronization with the current
|
||||
# master data is performed at all. However the slaves will get all the new
|
||||
# stream of writes receiving the master, starting from the moment the slave
|
||||
# connects.
|
||||
#
|
||||
# This means that:
|
||||
# 1) There is no consistency between master and slaves operating in this mode.
|
||||
# 2) It is possible that keys with an expire in the master will never expire
|
||||
# in the slave (because the slave may miss the EXPIRE command).
|
||||
# 3) Keys updated with non-idempotent commands may end with different values.
|
||||
#
|
||||
# However if your workload is about idempotent updates (for example using
|
||||
# just the SET command), and no-sync slaves are configured in order to evict
|
||||
# data on their own using maxmemory and a suitable policy, there are certain
|
||||
# advantages:
|
||||
#
|
||||
# 1) Slaves are always available (assuming they are configured to serve stale
|
||||
# data), since reconnecting with the master has no cost.
|
||||
# 2) Masters don't have to persist on disk and/or stream an RDB file to the
|
||||
# slaves, slaves are just accepted ASAP and put online.
|
||||
#
|
||||
# To enable, simply set repl-no-sync to yes. By default this feature is
|
||||
# disabled.
|
||||
#
|
||||
# repl-no-sync no
|
||||
|
||||
# The following option sets the replication timeout for:
|
||||
#
|
||||
# 1) Bulk transfer I/O during SYNC, from the point of view of slave.
|
||||
|
||||
@@ -276,6 +276,10 @@ void loadServerConfigFromString(char *config) {
|
||||
if ((server.repl_diskless_sync = yesnotoi(argv[1])) == -1) {
|
||||
err = "argument must be 'yes' or 'no'"; goto loaderr;
|
||||
}
|
||||
} else if (!strcasecmp(argv[0],"repl-no-sync") && argc==2) {
|
||||
if ((server.repl_no_sync = yesnotoi(argv[1])) == -1) {
|
||||
err = "argument must be 'yes' or 'no'"; goto loaderr;
|
||||
}
|
||||
} else if (!strcasecmp(argv[0],"repl-diskless-sync-delay") && argc==2) {
|
||||
server.repl_diskless_sync_delay = atoi(argv[1]);
|
||||
if (server.repl_diskless_sync_delay < 0) {
|
||||
|
||||
+4
-1
@@ -673,7 +673,10 @@ void freeClient(redisClient *c) {
|
||||
*
|
||||
* Note that before doing this we make sure that the client is not in
|
||||
* some unexpected state, by checking its flags. */
|
||||
if (server.master && c->flags & REDIS_MASTER) {
|
||||
if (server.master &&
|
||||
c->flags & REDIS_MASTER &&
|
||||
server.repl_no_sync == 0)
|
||||
{
|
||||
redisLog(REDIS_WARNING,"Connection with master lost.");
|
||||
if (!(c->flags & (REDIS_CLOSE_AFTER_REPLY|
|
||||
REDIS_CLOSE_ASAP|
|
||||
|
||||
@@ -1496,6 +1496,7 @@ void initServerConfig(void) {
|
||||
server.repl_disable_tcp_nodelay = REDIS_DEFAULT_REPL_DISABLE_TCP_NODELAY;
|
||||
server.repl_diskless_sync = REDIS_DEFAULT_REPL_DISKLESS_SYNC;
|
||||
server.repl_diskless_sync_delay = REDIS_DEFAULT_REPL_DISKLESS_SYNC_DELAY;
|
||||
server.repl_no_sync = REDIS_DEFAULT_REPL_NO_SYNC;
|
||||
server.slave_priority = REDIS_DEFAULT_SLAVE_PRIORITY;
|
||||
server.master_repl_offset = 0;
|
||||
|
||||
|
||||
@@ -119,6 +119,7 @@ typedef long long mstime_t; /* millisecond time type. */
|
||||
#define REDIS_DEFAULT_RDB_FILENAME "dump.rdb"
|
||||
#define REDIS_DEFAULT_REPL_DISKLESS_SYNC 0
|
||||
#define REDIS_DEFAULT_REPL_DISKLESS_SYNC_DELAY 5
|
||||
#define REDIS_DEFAULT_REPL_NO_SYNC 0
|
||||
#define REDIS_DEFAULT_SLAVE_SERVE_STALE_DATA 1
|
||||
#define REDIS_DEFAULT_SLAVE_READ_ONLY 1
|
||||
#define REDIS_DEFAULT_REPL_DISABLE_TCP_NODELAY 0
|
||||
@@ -258,6 +259,7 @@ typedef long long mstime_t; /* millisecond time type. */
|
||||
#define REDIS_READONLY (1<<17) /* Cluster client is in read-only state. */
|
||||
#define REDIS_PUBSUB (1<<18) /* Client is in Pub/Sub mode. */
|
||||
#define REDIS_PREVENT_PROP (1<<19) /* Don't propagate to AOF / Slaves. */
|
||||
#define REDIS_SLAVE_NO_SYNC (1<<20) /* Result of: REPLCONF use-sync 0. */
|
||||
|
||||
/* Client block type (btype field in client structure)
|
||||
* if REDIS_BLOCKED flag is set. */
|
||||
@@ -853,6 +855,7 @@ struct redisServer {
|
||||
int slave_priority; /* Reported in INFO and used by Sentinel. */
|
||||
char repl_master_runid[REDIS_RUN_ID_SIZE+1]; /* Master run id for PSYNC. */
|
||||
long long repl_master_initial_offset; /* Master PSYNC offset. */
|
||||
int repl_no_sync; /* Streaming replication, no SYNC. */
|
||||
/* Replication script cache. */
|
||||
dict *repl_scriptcache_dict; /* SHA1 all slaves are aware of. */
|
||||
list *repl_scriptcache_fifo; /* First in, first out LRU eviction. */
|
||||
|
||||
+53
-2
@@ -480,6 +480,9 @@ void syncCommand(redisClient *c) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Accept the slave ASAP if it requested no-sync mode. */
|
||||
if (c->flags & REDIS_SLAVE_NO_SYNC) goto attach_slave;
|
||||
|
||||
redisLog(REDIS_NOTICE,"Slave %s asks for synchronization",
|
||||
replicationGetSlaveName(c));
|
||||
|
||||
@@ -571,6 +574,8 @@ void syncCommand(redisClient *c) {
|
||||
}
|
||||
}
|
||||
|
||||
attach_slave:
|
||||
|
||||
if (server.repl_disable_tcp_nodelay)
|
||||
anetDisableTcpNoDelay(NULL, c->fd); /* Non critical if it fails. */
|
||||
c->repldbfd = -1;
|
||||
@@ -579,6 +584,18 @@ void syncCommand(redisClient *c) {
|
||||
listAddNodeTail(server.slaves,c);
|
||||
if (listLength(server.slaves) == 1 && server.repl_backlog == NULL)
|
||||
createReplicationBacklog();
|
||||
|
||||
/* Put the slave fully online right now if it is a no-sync one. */
|
||||
if (c->flags & REDIS_SLAVE_NO_SYNC) {
|
||||
char buf[128];
|
||||
int buflen;
|
||||
|
||||
/* Inform the slave with +NOTNEEDED that the request was accepted. */
|
||||
buflen = snprintf(buf,sizeof(buf),"+NOTNEEDED\r\n");
|
||||
if (write(c->fd,buf,buflen) != buflen) freeClientAsync(c);
|
||||
aeDeleteFileEvent(server.el,c->fd,AE_WRITABLE);
|
||||
putSlaveOnline(c);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -613,6 +630,18 @@ void replconfCommand(redisClient *c) {
|
||||
&port,NULL) != REDIS_OK))
|
||||
return;
|
||||
c->slave_listening_port = port;
|
||||
} else if (!strcasecmp(c->argv[j]->ptr,"use-sync")) {
|
||||
/* REPLCONF USE-SYNC is used in order for the slave to request
|
||||
* synchronization-less replication, the master will just send
|
||||
* new data without trying to synchronize the slave. */
|
||||
long long val;
|
||||
|
||||
if ((getLongLongFromObject(c->argv[j+1], &val) != REDIS_OK))
|
||||
return;
|
||||
if (val)
|
||||
c->flags &= ~REDIS_SLAVE_NO_SYNC;
|
||||
else
|
||||
c->flags |= REDIS_SLAVE_NO_SYNC;
|
||||
} else if (!strcasecmp(c->argv[j]->ptr,"ack")) {
|
||||
/* REPLCONF ACK is used by slave to inform the master the amount
|
||||
* of replication stream that it processed so far. It is an
|
||||
@@ -1140,7 +1169,7 @@ int slaveTryPartialResynchronization(int fd) {
|
||||
* client structure representing the master into server.master. */
|
||||
server.repl_master_initial_offset = -1;
|
||||
|
||||
if (server.cached_master) {
|
||||
if (server.cached_master && server.repl_no_sync == 0) {
|
||||
psync_runid = server.cached_master->replrunid;
|
||||
snprintf(psync_offset,sizeof(psync_offset),"%lld", server.cached_master->reploff+1);
|
||||
redisLog(REDIS_NOTICE,"Trying a partial resynchronization (request %s:%s).", psync_runid, psync_offset);
|
||||
@@ -1186,6 +1215,15 @@ int slaveTryPartialResynchronization(int fd) {
|
||||
return PSYNC_FULLRESYNC;
|
||||
}
|
||||
|
||||
if (!strncmp(reply,"+NOTNEEDED",10)) {
|
||||
/* No-sync replication. */
|
||||
redisLog(REDIS_NOTICE, "No-sync slave accepted without SYNC phase.");
|
||||
sdsfree(reply);
|
||||
server.repl_master_initial_offset = 0;
|
||||
replicationCreateMasterClient(fd);
|
||||
return PSYNC_CONTINUE;
|
||||
}
|
||||
|
||||
if (!strncmp(reply,"+CONTINUE",9)) {
|
||||
/* Partial resync was accepted, set the replication state accordingly */
|
||||
redisLog(REDIS_NOTICE,
|
||||
@@ -1292,7 +1330,7 @@ void syncWithMaster(aeEventLoop *el, int fd, void *privdata, int mask) {
|
||||
}
|
||||
|
||||
/* AUTH with the master if required. */
|
||||
if(server.masterauth) {
|
||||
if (server.masterauth) {
|
||||
err = sendSynchronousCommand(fd,"AUTH",server.masterauth,NULL);
|
||||
if (err[0] == '-') {
|
||||
redisLog(REDIS_WARNING,"Unable to AUTH to MASTER: %s",err);
|
||||
@@ -1302,6 +1340,18 @@ void syncWithMaster(aeEventLoop *el, int fd, void *privdata, int mask) {
|
||||
sdsfree(err);
|
||||
}
|
||||
|
||||
/* Inform the master we don't want to synchronize if we are using
|
||||
* repl-no-sync mode. */
|
||||
if (server.repl_no_sync) {
|
||||
err = sendSynchronousCommand(fd,"REPLCONF","use-sync","0",NULL);
|
||||
if (err[0] == '-') {
|
||||
redisLog(REDIS_WARNING,"Unable to enable no-sync mode: %s",err);
|
||||
sdsfree(err);
|
||||
goto error;
|
||||
}
|
||||
sdsfree(err);
|
||||
}
|
||||
|
||||
/* Set the slave port, so that Master's INFO command can list the
|
||||
* slave listening port correctly. */
|
||||
{
|
||||
@@ -1698,6 +1748,7 @@ void refreshGoodSlavesCount(void) {
|
||||
time_t lag = server.unixtime - slave->repl_ack_time;
|
||||
|
||||
if (slave->replstate == REDIS_REPL_ONLINE &&
|
||||
!(slave->flags & REDIS_SLAVE_NO_SYNC) &&
|
||||
lag <= server.repl_min_slaves_max_lag) good++;
|
||||
}
|
||||
server.repl_good_slaves_count = good;
|
||||
|
||||
Reference in New Issue
Block a user