1 /* Asynchronous replication implementation. 2 * 3 * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * * Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * * Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * * Neither the name of Redis nor the names of its contributors may be used 15 * to endorse or promote products derived from this software without 16 * specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 32 #include "redis.h" 33 34 #include <sys/time.h> 35 #include <unistd.h> 36 #include <fcntl.h> 37 #include <sys/socket.h> 38 #include <sys/stat.h> 39 40 void replicationDiscardCachedMaster(void); 41 void replicationResurrectCachedMaster(int newfd); 42 43 /* ---------------------------------- MASTER -------------------------------- */ 44 45 void createReplicationBacklog(void) { 46 redisAssert(server.repl_backlog == NULL); 47 server.repl_backlog = zmalloc(server.repl_backlog_size); 48 server.repl_backlog_histlen = 0; 49 server.repl_backlog_idx = 0; 50 /* When a new backlog buffer is created, we increment the replication 51 * offset by one to make sure we'll not be able to PSYNC with any 52 * previous slave. This is needed because we avoid incrementing the 53 * master_repl_offset if no backlog exists nor slaves are attached. */ 54 server.master_repl_offset++; 55 56 /* We don't have any data inside our buffer, but virtually the first 57 * byte we have is the next byte that will be generated for the 58 * replication stream. */ 59 server.repl_backlog_off = server.master_repl_offset+1; 60 } 61 62 /* This function is called when the user modifies the replication backlog 63 * size at runtime. It is up to the function to both update the 64 * server.repl_backlog_size and to resize the buffer and setup it so that 65 * it contains the same data as the previous one (possibly less data, but 66 * the most recent bytes, or the same data and more free space in case the 67 * buffer is enlarged). */ 68 void resizeReplicationBacklog(long long newsize) { 69 if (newsize < REDIS_REPL_BACKLOG_MIN_SIZE) 70 newsize = REDIS_REPL_BACKLOG_MIN_SIZE; 71 if (server.repl_backlog_size == newsize) return; 72 73 server.repl_backlog_size = newsize; 74 if (server.repl_backlog != NULL) { 75 /* What we actually do is to flush the old buffer and realloc a new 76 * empty one. It will refill with new data incrementally. 77 * The reason is that copying a few gigabytes adds latency and even 78 * worse often we need to alloc additional space before freeing the 79 * old buffer. */ 80 zfree(server.repl_backlog); 81 server.repl_backlog = zmalloc(server.repl_backlog_size); 82 server.repl_backlog_histlen = 0; 83 server.repl_backlog_idx = 0; 84 /* Next byte we have is... the next since the buffer is emtpy. */ 85 server.repl_backlog_off = server.master_repl_offset+1; 86 } 87 } 88 89 void freeReplicationBacklog(void) { 90 redisAssert(listLength(server.slaves) == 0); 91 zfree(server.repl_backlog); 92 server.repl_backlog = NULL; 93 } 94 95 /* Add data to the replication backlog. 96 * This function also increments the global replication offset stored at 97 * server.master_repl_offset, because there is no case where we want to feed 98 * the backlog without incrementing the buffer. */ 99 void feedReplicationBacklog(void *ptr, size_t len) { 100 unsigned char *p = ptr; 101 102 server.master_repl_offset += len; 103 104 /* This is a circular buffer, so write as much data we can at every 105 * iteration and rewind the "idx" index if we reach the limit. */ 106 while(len) { 107 size_t thislen = server.repl_backlog_size - server.repl_backlog_idx; 108 if (thislen > len) thislen = len; 109 memcpy(server.repl_backlog+server.repl_backlog_idx,p,thislen); 110 server.repl_backlog_idx += thislen; 111 if (server.repl_backlog_idx == server.repl_backlog_size) 112 server.repl_backlog_idx = 0; 113 len -= thislen; 114 p += thislen; 115 server.repl_backlog_histlen += thislen; 116 } 117 if (server.repl_backlog_histlen > server.repl_backlog_size) 118 server.repl_backlog_histlen = server.repl_backlog_size; 119 /* Set the offset of the first byte we have in the backlog. */ 120 server.repl_backlog_off = server.master_repl_offset - 121 server.repl_backlog_histlen + 1; 122 } 123 124 /* Wrapper for feedReplicationBacklog() that takes Redis string objects 125 * as input. */ 126 void feedReplicationBacklogWithObject(robj *o) { 127 char llstr[REDIS_LONGSTR_SIZE]; 128 void *p; 129 size_t len; 130 131 if (o->encoding == REDIS_ENCODING_INT) { 132 len = ll2string(llstr,sizeof(llstr),(long)o->ptr); 133 p = llstr; 134 } else { 135 len = sdslen(o->ptr); 136 p = o->ptr; 137 } 138 feedReplicationBacklog(p,len); 139 } 140 141 #define FEEDSLAVE_BUF_SIZE (1024*64) 142 void replicationFeedSlaves(list *slaves, int dictid, robj **argv, int argc) { 143 listNode *ln; 144 listIter li; 145 int j, i, len; 146 char buf[FEEDSLAVE_BUF_SIZE], *b = buf; 147 char llstr[REDIS_LONGSTR_SIZE]; 148 int buf_left = FEEDSLAVE_BUF_SIZE; 149 robj *o; 150 151 /* If there aren't slaves, and there is no backlog buffer to populate, 152 * we can return ASAP. */ 153 if (server.repl_backlog == NULL && listLength(slaves) == 0) return; 154 155 /* We can't have slaves attached and no backlog. */ 156 redisAssert(!(listLength(slaves) != 0 && server.repl_backlog == NULL)); 157 158 /* What we do here is to try to write as much data as possible in a static 159 * buffer "buf" that is used to create an object that is later sent to all 160 * the slaves. This way we do the decoding only one time for most commands 161 * not containing big payloads. */ 162 163 /* Create the SELECT command into the static buffer if needed. */ 164 if (server.slaveseldb != dictid) { 165 char *selectcmd; 166 size_t sclen; 167 168 if (dictid >= 0 && dictid < REDIS_SHARED_SELECT_CMDS) { 169 selectcmd = shared.select[dictid]->ptr; 170 sclen = sdslen(selectcmd); 171 memcpy(b,selectcmd,sclen); 172 b += sclen; 173 buf_left -= sclen; 174 } else { 175 int dictid_len; 176 177 dictid_len = ll2string(llstr,sizeof(llstr),dictid); 178 sclen = snprintf(b,buf_left,"*2\r\n$6\r\nSELECT\r\n$%d\r\n%s\r\n", 179 dictid_len, llstr); 180 b += sclen; 181 buf_left -= sclen; 182 } 183 } 184 server.slaveseldb = dictid; 185 186 /* Add the multi bulk reply size to the static buffer, that is, the number 187 * of arguments of the command to send to every slave. */ 188 b[0] = '*'; 189 len = ll2string(b+1,REDIS_LONGSTR_SIZE,argc); 190 b += len+1; 191 buf_left -= len; 192 b[0] = '\r'; 193 b[1] = '\n'; 194 b += 2; 195 buf_left -= 2; 196 197 /* Try to use the static buffer for as much arguments is possible. */ 198 for (j = 0; j < argc; j++) { 199 int objlen; 200 char *objptr; 201 202 if (argv[j]->encoding != REDIS_ENCODING_RAW && 203 argv[j]->encoding != REDIS_ENCODING_INT) { 204 redisPanic("Unexpected encoding"); 205 } 206 if (argv[j]->encoding == REDIS_ENCODING_RAW) { 207 objlen = sdslen(argv[j]->ptr); 208 objptr = argv[j]->ptr; 209 } else { 210 objlen = ll2string(llstr,REDIS_LONGSTR_SIZE,(long)argv[j]->ptr); 211 objptr = llstr; 212 } 213 /* We need enough space for bulk reply encoding, newlines, and 214 * the data itself. */ 215 if (buf_left < objlen+REDIS_LONGSTR_SIZE+32) break; 216 217 /* Write $...CRLF */ 218 b[0] = '$'; 219 len = ll2string(b+1,REDIS_LONGSTR_SIZE,objlen); 220 b += len+1; 221 buf_left -= len; 222 b[0] = '\r'; 223 b[1] = '\n'; 224 b += 2; 225 buf_left -= 2; 226 227 /* And data plus CRLF */ 228 memcpy(b,objptr,objlen); 229 b += objlen; 230 buf_left -= objlen; 231 b[0] = '\r'; 232 b[1] = '\n'; 233 b += 2; 234 buf_left -= 2; 235 } 236 237 /* Create an object with the static buffer content. */ 238 redisAssert(buf_left < FEEDSLAVE_BUF_SIZE); 239 o = createStringObject(buf,b-buf); 240 241 /* If we have a backlog, populate it with data and increment 242 * the global replication offset. */ 243 if (server.repl_backlog) { 244 feedReplicationBacklogWithObject(o); 245 for (i = j; i < argc; i++) { 246 char aux[REDIS_LONGSTR_SIZE+3]; 247 long objlen = stringObjectLen(argv[i]); 248 249 /* We need to feed the buffer with the object as a bulk reply 250 * not just as a plain string, so create the $..CRLF payload len 251 * ad add the final CRLF */ 252 aux[0] = '$'; 253 len = ll2string(aux+1,objlen,sizeof(aux)-1); 254 aux[len+1] = '\r'; 255 aux[len+2] = '\n'; 256 feedReplicationBacklog(aux,len+3); 257 feedReplicationBacklogWithObject(argv[j]); 258 feedReplicationBacklogWithObject(shared.crlf); 259 } 260 } 261 262 /* Write data to slaves. Here we do two things: 263 * 1) We write the "o" object that was created using the accumulated 264 * static buffer. 265 * 2) We write any additional argument of the command to replicate that 266 * was not written inside the static buffer for lack of space. 267 */ 268 listRewind(slaves,&li); 269 while((ln = listNext(&li))) { 270 redisClient *slave = ln->value; 271 272 /* Don't feed slaves that are still waiting for BGSAVE to start */ 273 if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_START) continue; 274 275 /* Feed slaves that are waiting for the initial SYNC (so these commands 276 * are queued in the output buffer until the initial SYNC completes), 277 * or are already in sync with the master. */ 278 279 /* First, trasmit the object created from the static buffer. */ 280 addReply(slave,o); 281 282 /* Finally any additional argument that was not stored inside the 283 * static buffer if any (from j to argc). */ 284 for (i = j; i < argc; i++) 285 addReplyBulk(slave,argv[i]); 286 } 287 decrRefCount(o); 288 } 289 290 void replicationFeedMonitors(redisClient *c, list *monitors, int dictid, robj **argv, int argc) { 291 listNode *ln; 292 listIter li; 293 int j, port; 294 sds cmdrepr = sdsnew("+"); 295 robj *cmdobj; 296 char ip[32]; 297 struct timeval tv; 298 299 gettimeofday(&tv,NULL); 300 cmdrepr = sdscatprintf(cmdrepr,"%ld.%06ld ",(long)tv.tv_sec,(long)tv.tv_usec); 301 if (c->flags & REDIS_LUA_CLIENT) { 302 cmdrepr = sdscatprintf(cmdrepr,"[%d lua] ",dictid); 303 } else if (c->flags & REDIS_UNIX_SOCKET) { 304 cmdrepr = sdscatprintf(cmdrepr,"[%d unix:%s] ",dictid,server.unixsocket); 305 } else { 306 anetPeerToString(c->fd,ip,&port); 307 cmdrepr = sdscatprintf(cmdrepr,"[%d %s:%d] ",dictid,ip,port); 308 } 309 310 for (j = 0; j < argc; j++) { 311 if (argv[j]->encoding == REDIS_ENCODING_INT) { 312 cmdrepr = sdscatprintf(cmdrepr, "\"%ld\"", (long)argv[j]->ptr); 313 } else { 314 cmdrepr = sdscatrepr(cmdrepr,(char*)argv[j]->ptr, 315 sdslen(argv[j]->ptr)); 316 } 317 if (j != argc-1) 318 cmdrepr = sdscatlen(cmdrepr," ",1); 319 } 320 cmdrepr = sdscatlen(cmdrepr,"\r\n",2); 321 cmdobj = createObject(REDIS_STRING,cmdrepr); 322 323 listRewind(monitors,&li); 324 while((ln = listNext(&li))) { 325 redisClient *monitor = ln->value; 326 addReply(monitor,cmdobj); 327 } 328 decrRefCount(cmdobj); 329 } 330 331 /* Feed the slave 'c' with the replication backlog starting from the 332 * specified 'offset' up to the end of the backlog. */ 333 long long addReplyReplicationBacklog(redisClient *c, long long offset) { 334 long long j, skip, len; 335 336 redisLog(REDIS_DEBUG, "[PSYNC] Slave request offset: %lld", offset); 337 338 if (server.repl_backlog_histlen == 0) { 339 redisLog(REDIS_DEBUG, "[PSYNC] Backlog history len is zero"); 340 return 0; 341 } 342 343 redisLog(REDIS_DEBUG, "[PSYNC] Backlog size: %lld", 344 server.repl_backlog_size); 345 redisLog(REDIS_DEBUG, "[PSYNC] First byte: %lld", 346 server.repl_backlog_off); 347 redisLog(REDIS_DEBUG, "[PSYNC] History len: %lld", 348 server.repl_backlog_histlen); 349 redisLog(REDIS_DEBUG, "[PSYNC] Current index: %lld", 350 server.repl_backlog_idx); 351 352 /* Compute the amount of bytes we need to discard. */ 353 skip = offset - server.repl_backlog_off; 354 redisLog(REDIS_DEBUG, "[PSYNC] Skipping: %lld", skip); 355 356 /* Point j to the oldest byte, that is actaully our 357 * server.repl_backlog_off byte. */ 358 j = (server.repl_backlog_idx + 359 (server.repl_backlog_size-server.repl_backlog_histlen)) % 360 server.repl_backlog_size; 361 redisLog(REDIS_DEBUG, "[PSYNC] Index of first byte: %lld", j); 362 363 /* Discard the amount of data to seek to the specified 'offset'. */ 364 j = (j + skip) % server.repl_backlog_size; 365 366 /* Feed slave with data. Since it is a circular buffer we have to 367 * split the reply in two parts if we are cross-boundary. */ 368 len = server.repl_backlog_histlen - skip; 369 redisLog(REDIS_DEBUG, "[PSYNC] Reply total length: %lld", len); 370 while(len) { 371 long long thislen = 372 ((server.repl_backlog_size - j) < len) ? 373 (server.repl_backlog_size - j) : len; 374 375 redisLog(REDIS_DEBUG, "[PSYNC] addReply() length: %lld", thislen); 376 addReplySds(c,sdsnewlen(server.repl_backlog + j, thislen)); 377 len -= thislen; 378 j = 0; 379 } 380 return server.repl_backlog_histlen - skip; 381 } 382 383 /* This function handles the PSYNC command from the point of view of a 384 * master receiving a request for partial resynchronization. 385 * 386 * On success return REDIS_OK, otherwise REDIS_ERR is returned and we proceed 387 * with the usual full resync. */ 388 int masterTryPartialResynchronization(redisClient *c) { 389 long long psync_offset, psync_len; 390 char *master_runid = c->argv[1]->ptr; 391 char buf[128]; 392 int buflen; 393 394 /* Is the runid of this master the same advertised by the wannabe slave 395 * via PSYNC? If runid changed this master is a different instance and 396 * there is no way to continue. */ 397 if (strcasecmp(master_runid, server.runid)) { 398 /* Run id "?" is used by slaves that want to force a full resync. */ 399 if (master_runid[0] != '?') { 400 redisLog(REDIS_NOTICE,"Partial resynchronization not accepted: " 401 "Runid mismatch (Client asked for '%s', I'm '%s')", 402 master_runid, server.runid); 403 } else { 404 redisLog(REDIS_NOTICE,"Full resync requested by slave."); 405 } 406 goto need_full_resync; 407 } 408 409 /* We still have the data our slave is asking for? */ 410 if (getLongLongFromObjectOrReply(c,c->argv[2],&psync_offset,NULL) != 411 REDIS_OK) goto need_full_resync; 412 if (!server.repl_backlog || 413 psync_offset < server.repl_backlog_off || 414 psync_offset >= (server.repl_backlog_off + server.repl_backlog_size)) 415 { 416 redisLog(REDIS_NOTICE, 417 "Unable to partial resync with the slave for lack of backlog (Slave request was: %lld).", psync_offset); 418 goto need_full_resync; 419 } 420 421 /* If we reached this point, we are able to perform a partial resync: 422 * 1) Set client state to make it a slave. 423 * 2) Inform the client we can continue with +CONTINUE 424 * 3) Send the backlog data (from the offset to the end) to the slave. */ 425 c->flags |= REDIS_SLAVE; 426 c->replstate = REDIS_REPL_ONLINE; 427 listAddNodeTail(server.slaves,c); 428 /* We can't use the connection buffers since they are used to accumulate 429 * new commands at this stage. But we are sure the socket send buffer is 430 * emtpy so this write will never fail actually. */ 431 buflen = snprintf(buf,sizeof(buf),"+CONTINUE\r\n"); 432 if (write(c->fd,buf,buflen) != buflen) { 433 freeClientAsync(c); 434 return REDIS_OK; 435 } 436 psync_len = addReplyReplicationBacklog(c,psync_offset); 437 redisLog(REDIS_NOTICE, 438 "Partial resynchronization request accepted. Sending %lld bytes of backlog starting from offset %lld.", psync_len, psync_offset); 439 /* Note that we don't need to set the selected DB at server.slaveseldb 440 * to -1 to force the master to emit SELECT, since the slave already 441 * has this state from the previous connection with the master. */ 442 443 return REDIS_OK; /* The caller can return, no full resync needed. */ 444 445 need_full_resync: 446 /* We need a full resync for some reason... notify the client. */ 447 psync_offset = server.master_repl_offset; 448 /* Add 1 to psync_offset if it the replication backlog does not exists 449 * as when it will be created later we'll increment the offset by one. */ 450 if (server.repl_backlog == NULL) psync_offset++; 451 /* Again, we can't use the connection buffers (see above). */ 452 buflen = snprintf(buf,sizeof(buf),"+FULLRESYNC %s %lld\r\n", 453 server.runid,psync_offset); 454 if (write(c->fd,buf,buflen) != buflen) { 455 freeClientAsync(c); 456 return REDIS_OK; 457 } 458 return REDIS_ERR; 459 } 460 461 /* SYNC ad PSYNC command implemenation. */ 462 void syncCommand(redisClient *c) { 463 /* ignore SYNC if already slave or in monitor mode */ 464 if (c->flags & REDIS_SLAVE) return; 465 466 /* Refuse SYNC requests if we are a slave but the link with our master 467 * is not ok... */ 468 if (server.masterhost && server.repl_state != REDIS_REPL_CONNECTED) { 469 addReplyError(c,"Can't SYNC while not connected with my master"); 470 return; 471 } 472 473 /* SYNC can't be issued when the server has pending data to send to 474 * the client about already issued commands. We need a fresh reply 475 * buffer registering the differences between the BGSAVE and the current 476 * dataset, so that we can copy to other slaves if needed. */ 477 if (listLength(c->reply) != 0 || c->bufpos != 0) { 478 addReplyError(c,"SYNC and PSYNC are invalid with pending output"); 479 return; 480 } 481 482 redisLog(REDIS_NOTICE,"Slave asks for synchronization"); 483 484 /* Try a partial resynchronization if this is a PSYNC command. 485 * If it fails, we continue with usual full resynchronization, however 486 * when this happens masterTryPartialResynchronization() already 487 * replied with: 488 * 489 * +FULLRESYNC <runid> <offset> 490 * 491 * So the slave knows the new runid and offset to try a PSYNC later 492 * if the connection with the master is lost. */ 493 if (!strcasecmp(c->argv[0]->ptr,"psync")) { 494 if (masterTryPartialResynchronization(c) == REDIS_OK) { 495 server.stat_sync_partial_ok++; 496 return; /* No full resync needed, return. */ 497 } else { 498 char *master_runid = c->argv[1]->ptr; 499 500 /* Increment stats for failed PSYNCs, but only if the 501 * runid is not "?", as this is used by slaves to force a full 502 * resync on purpose when they are not albe to partially 503 * resync. */ 504 if (master_runid[0] != '?') server.stat_sync_partial_err++; 505 } 506 } 507 508 /* Full resynchronization. */ 509 server.stat_sync_full++; 510 511 /* Here we need to check if there is a background saving operation 512 * in progress, or if it is required to start one */ 513 if (server.rdb_child_pid != -1) { 514 /* Ok a background save is in progress. Let's check if it is a good 515 * one for replication, i.e. if there is another slave that is 516 * registering differences since the server forked to save */ 517 redisClient *slave; 518 listNode *ln; 519 listIter li; 520 521 listRewind(server.slaves,&li); 522 while((ln = listNext(&li))) { 523 slave = ln->value; 524 if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_END) break; 525 } 526 if (ln) { 527 /* Perfect, the server is already registering differences for 528 * another slave. Set the right state, and copy the buffer. */ 529 copyClientOutputBuffer(c,slave); 530 c->replstate = REDIS_REPL_WAIT_BGSAVE_END; 531 redisLog(REDIS_NOTICE,"Waiting for end of BGSAVE for SYNC"); 532 } else { 533 /* No way, we need to wait for the next BGSAVE in order to 534 * register differences */ 535 c->replstate = REDIS_REPL_WAIT_BGSAVE_START; 536 redisLog(REDIS_NOTICE,"Waiting for next BGSAVE for SYNC"); 537 } 538 } else { 539 /* Ok we don't have a BGSAVE in progress, let's start one */ 540 redisLog(REDIS_NOTICE,"Starting BGSAVE for SYNC"); 541 if (rdbSaveBackground(server.rdb_filename) != REDIS_OK) { 542 redisLog(REDIS_NOTICE,"Replication failed, can't BGSAVE"); 543 addReplyError(c,"Unable to perform background save"); 544 return; 545 } 546 c->replstate = REDIS_REPL_WAIT_BGSAVE_END; 547 } 548 549 if (server.repl_disable_tcp_nodelay) 550 anetDisableTcpNoDelay(NULL, c->fd); /* Non critical if it fails. */ 551 c->repldbfd = -1; 552 c->flags |= REDIS_SLAVE; 553 server.slaveseldb = -1; /* Force to re-emit the SELECT command. */ 554 listAddNodeTail(server.slaves,c); 555 if (listLength(server.slaves) == 1 && server.repl_backlog == NULL) 556 createReplicationBacklog(); 557 return; 558 } 559 560 /* REPLCONF <option> <value> <option> <value> ... 561 * This command is used by a slave in order to configure the replication 562 * process before starting it with the SYNC command. 563 * 564 * Currently the only use of this command is to communicate to the master 565 * what is the listening port of the Slave redis instance, so that the 566 * master can accurately list slaves and their listening ports in 567 * the INFO output. 568 * 569 * In the future the same command can be used in order to configure 570 * the replication to initiate an incremental replication instead of a 571 * full resync. */ 572 void replconfCommand(redisClient *c) { 573 int j; 574 575 if ((c->argc % 2) == 0) { 576 /* Number of arguments must be odd to make sure that every 577 * option has a corresponding value. */ 578 addReply(c,shared.syntaxerr); 579 return; 580 } 581 582 /* Process every option-value pair. */ 583 for (j = 1; j < c->argc; j+=2) { 584 if (!strcasecmp(c->argv[j]->ptr,"listening-port")) { 585 long port; 586 587 if ((getLongFromObjectOrReply(c,c->argv[j+1], 588 &port,NULL) != REDIS_OK)) 589 return; 590 c->slave_listening_port = port; 591 } else { 592 addReplyErrorFormat(c,"Unrecognized REPLCONF option: %s", 593 (char*)c->argv[j]->ptr); 594 return; 595 } 596 } 597 addReply(c,shared.ok); 598 } 599 600 void sendBulkToSlave(aeEventLoop *el, int fd, void *privdata, int mask) { 601 redisClient *slave = privdata; 602 REDIS_NOTUSED(el); 603 REDIS_NOTUSED(mask); 604 char buf[REDIS_IOBUF_LEN]; 605 ssize_t nwritten, buflen; 606 607 if (slave->repldboff == 0) { 608 /* Write the bulk write count before to transfer the DB. In theory here 609 * we don't know how much room there is in the output buffer of the 610 * socket, but in practice SO_SNDLOWAT (the minimum count for output 611 * operations) will never be smaller than the few bytes we need. */ 612 sds bulkcount; 613 614 bulkcount = sdscatprintf(sdsempty(),"$%lld\r\n",(unsigned long long) 615 slave->repldbsize); 616 if (write(fd,bulkcount,sdslen(bulkcount)) != (signed)sdslen(bulkcount)) 617 { 618 sdsfree(bulkcount); 619 freeClient(slave); 620 return; 621 } 622 sdsfree(bulkcount); 623 } 624 lseek(slave->repldbfd,slave->repldboff,SEEK_SET); 625 buflen = read(slave->repldbfd,buf,REDIS_IOBUF_LEN); 626 if (buflen <= 0) { 627 redisLog(REDIS_WARNING,"Read error sending DB to slave: %s", 628 (buflen == 0) ? "premature EOF" : strerror(errno)); 629 freeClient(slave); 630 return; 631 } 632 if ((nwritten = write(fd,buf,buflen)) == -1) { 633 redisLog(REDIS_VERBOSE,"Write error sending DB to slave: %s", 634 strerror(errno)); 635 freeClient(slave); 636 return; 637 } 638 slave->repldboff += nwritten; 639 if (slave->repldboff == slave->repldbsize) { 640 close(slave->repldbfd); 641 slave->repldbfd = -1; 642 aeDeleteFileEvent(server.el,slave->fd,AE_WRITABLE); 643 slave->replstate = REDIS_REPL_ONLINE; 644 if (aeCreateFileEvent(server.el, slave->fd, AE_WRITABLE, 645 sendReplyToClient, slave) == AE_ERR) { 646 freeClient(slave); 647 return; 648 } 649 redisLog(REDIS_NOTICE,"Synchronization with slave succeeded"); 650 } 651 } 652 653 /* This function is called at the end of every background saving. 654 * The argument bgsaveerr is REDIS_OK if the background saving succeeded 655 * otherwise REDIS_ERR is passed to the function. 656 * 657 * The goal of this function is to handle slaves waiting for a successful 658 * background saving in order to perform non-blocking synchronization. */ 659 void updateSlavesWaitingBgsave(int bgsaveerr) { 660 listNode *ln; 661 int startbgsave = 0; 662 listIter li; 663 664 listRewind(server.slaves,&li); 665 while((ln = listNext(&li))) { 666 redisClient *slave = ln->value; 667 668 if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_START) { 669 startbgsave = 1; 670 slave->replstate = REDIS_REPL_WAIT_BGSAVE_END; 671 } else if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_END) { 672 struct redis_stat buf; 673 674 if (bgsaveerr != REDIS_OK) { 675 freeClient(slave); 676 redisLog(REDIS_WARNING,"SYNC failed. BGSAVE child returned an error"); 677 continue; 678 } 679 if ((slave->repldbfd = open(server.rdb_filename,O_RDONLY)) == -1 || 680 redis_fstat(slave->repldbfd,&buf) == -1) { 681 freeClient(slave); 682 redisLog(REDIS_WARNING,"SYNC failed. Can't open/stat DB after BGSAVE: %s", strerror(errno)); 683 continue; 684 } 685 slave->repldboff = 0; 686 slave->repldbsize = buf.st_size; 687 slave->replstate = REDIS_REPL_SEND_BULK; 688 aeDeleteFileEvent(server.el,slave->fd,AE_WRITABLE); 689 if (aeCreateFileEvent(server.el, slave->fd, AE_WRITABLE, sendBulkToSlave, slave) == AE_ERR) { 690 freeClient(slave); 691 continue; 692 } 693 } 694 } 695 if (startbgsave) { 696 if (rdbSaveBackground(server.rdb_filename) != REDIS_OK) { 697 listIter li; 698 699 listRewind(server.slaves,&li); 700 redisLog(REDIS_WARNING,"SYNC failed. BGSAVE failed"); 701 while((ln = listNext(&li))) { 702 redisClient *slave = ln->value; 703 704 if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_START) 705 freeClient(slave); 706 } 707 } 708 } 709 } 710 711 /* ----------------------------------- SLAVE -------------------------------- */ 712 713 /* Abort the async download of the bulk dataset while SYNC-ing with master */ 714 void replicationAbortSyncTransfer(void) { 715 redisAssert(server.repl_state == REDIS_REPL_TRANSFER); 716 717 aeDeleteFileEvent(server.el,server.repl_transfer_s,AE_READABLE); 718 close(server.repl_transfer_s); 719 close(server.repl_transfer_fd); 720 unlink(server.repl_transfer_tmpfile); 721 zfree(server.repl_transfer_tmpfile); 722 server.repl_state = REDIS_REPL_CONNECT; 723 } 724 725 /* Asynchronously read the SYNC payload we receive from a master */ 726 #define REPL_MAX_WRITTEN_BEFORE_FSYNC (1024*1024*8) /* 8 MB */ 727 void readSyncBulkPayload(aeEventLoop *el, int fd, void *privdata, int mask) { 728 char buf[4096]; 729 ssize_t nread, readlen; 730 off_t left; 731 REDIS_NOTUSED(el); 732 REDIS_NOTUSED(privdata); 733 REDIS_NOTUSED(mask); 734 735 /* If repl_transfer_size == -1 we still have to read the bulk length 736 * from the master reply. */ 737 if (server.repl_transfer_size == -1) { 738 if (syncReadLine(fd,buf,1024,server.repl_syncio_timeout*1000) == -1) { 739 redisLog(REDIS_WARNING, 740 "I/O error reading bulk count from MASTER: %s", 741 strerror(errno)); 742 goto error; 743 } 744 745 if (buf[0] == '-') { 746 redisLog(REDIS_WARNING, 747 "MASTER aborted replication with an error: %s", 748 buf+1); 749 goto error; 750 } else if (buf[0] == '\0') { 751 /* At this stage just a newline works as a PING in order to take 752 * the connection live. So we refresh our last interaction 753 * timestamp. */ 754 server.repl_transfer_lastio = server.unixtime; 755 return; 756 } else if (buf[0] != '$') { 757 redisLog(REDIS_WARNING,"Bad protocol from MASTER, the first byte is not '$' (we received '%s'), are you sure the host and port are right?", buf); 758 goto error; 759 } 760 server.repl_transfer_size = strtol(buf+1,NULL,10); 761 redisLog(REDIS_NOTICE, 762 "MASTER <-> SLAVE sync: receiving %lld bytes from master", 763 (long long) server.repl_transfer_size); 764 return; 765 } 766 767 /* Read bulk data */ 768 left = server.repl_transfer_size - server.repl_transfer_read; 769 readlen = (left < (signed)sizeof(buf)) ? left : (signed)sizeof(buf); 770 nread = read(fd,buf,readlen); 771 if (nread <= 0) { 772 redisLog(REDIS_WARNING,"I/O error trying to sync with MASTER: %s", 773 (nread == -1) ? strerror(errno) : "connection lost"); 774 replicationAbortSyncTransfer(); 775 return; 776 } 777 server.repl_transfer_lastio = server.unixtime; 778 if (write(server.repl_transfer_fd,buf,nread) != nread) { 779 redisLog(REDIS_WARNING,"Write error or short write writing to the DB dump file needed for MASTER <-> SLAVE synchronization: %s", strerror(errno)); 780 goto error; 781 } 782 server.repl_transfer_read += nread; 783 784 /* Sync data on disk from time to time, otherwise at the end of the transfer 785 * we may suffer a big delay as the memory buffers are copied into the 786 * actual disk. */ 787 if (server.repl_transfer_read >= 788 server.repl_transfer_last_fsync_off + REPL_MAX_WRITTEN_BEFORE_FSYNC) 789 { 790 off_t sync_size = server.repl_transfer_read - 791 server.repl_transfer_last_fsync_off; 792 rdb_fsync_range(server.repl_transfer_fd, 793 server.repl_transfer_last_fsync_off, sync_size); 794 server.repl_transfer_last_fsync_off += sync_size; 795 } 796 797 /* Check if the transfer is now complete */ 798 if (server.repl_transfer_read == server.repl_transfer_size) { 799 if (rename(server.repl_transfer_tmpfile,server.rdb_filename) == -1) { 800 redisLog(REDIS_WARNING,"Failed trying to rename the temp DB into dump.rdb in MASTER <-> SLAVE synchronization: %s", strerror(errno)); 801 replicationAbortSyncTransfer(); 802 return; 803 } 804 redisLog(REDIS_NOTICE, "MASTER <-> SLAVE sync: Loading DB in memory"); 805 signalFlushedDb(-1); 806 emptyDb(); 807 /* Before loading the DB into memory we need to delete the readable 808 * handler, otherwise it will get called recursively since 809 * rdbLoad() will call the event loop to process events from time to 810 * time for non blocking loading. */ 811 aeDeleteFileEvent(server.el,server.repl_transfer_s,AE_READABLE); 812 if (rdbLoad(server.rdb_filename) != REDIS_OK) { 813 redisLog(REDIS_WARNING,"Failed trying to load the MASTER synchronization DB from disk"); 814 replicationAbortSyncTransfer(); 815 return; 816 } 817 /* Final setup of the connected slave <- master link */ 818 zfree(server.repl_transfer_tmpfile); 819 close(server.repl_transfer_fd); 820 server.master = createClient(server.repl_transfer_s); 821 server.master->flags |= REDIS_MASTER; 822 server.master->authenticated = 1; 823 server.repl_state = REDIS_REPL_CONNECTED; 824 server.master->reploff = server.repl_master_initial_offset; 825 memcpy(server.master->replrunid, server.repl_master_runid, 826 sizeof(server.repl_master_runid)); 827 redisLog(REDIS_NOTICE, "MASTER <-> SLAVE sync: Finished with success"); 828 /* Restart the AOF subsystem now that we finished the sync. This 829 * will trigger an AOF rewrite, and when done will start appending 830 * to the new file. */ 831 if (server.aof_state != REDIS_AOF_OFF) { 832 int retry = 10; 833 834 stopAppendOnly(); 835 while (retry-- && startAppendOnly() == REDIS_ERR) { 836 redisLog(REDIS_WARNING,"Failed enabling the AOF after successful master synchronization! Trying it again in one second."); 837 sleep(1); 838 } 839 if (!retry) { 840 redisLog(REDIS_WARNING,"FATAL: this slave instance finished the synchronization with its master, but the AOF can't be turned on. Exiting now."); 841 exit(1); 842 } 843 } 844 } 845 846 return; 847 848 error: 849 replicationAbortSyncTransfer(); 850 return; 851 } 852 853 /* Send a synchronous command to the master. Used to send AUTH and 854 * REPLCONF commands before starting the replication with SYNC. 855 * 856 * The command returns an sds string representing the result of the 857 * operation. On error the first byte is a "-". 858 */ 859 char *sendSynchronousCommand(int fd, ...) { 860 va_list ap; 861 sds cmd = sdsempty(); 862 char *arg, buf[256]; 863 864 /* Create the command to send to the master, we use simple inline 865 * protocol for simplicity as currently we only send simple strings. */ 866 va_start(ap,fd); 867 while(1) { 868 arg = va_arg(ap, char*); 869 if (arg == NULL) break; 870 871 if (sdslen(cmd) != 0) cmd = sdscatlen(cmd," ",1); 872 cmd = sdscat(cmd,arg); 873 } 874 cmd = sdscatlen(cmd,"\r\n",2); 875 876 /* Transfer command to the server. */ 877 if (syncWrite(fd,cmd,sdslen(cmd),server.repl_syncio_timeout*1000) == -1) { 878 sdsfree(cmd); 879 return sdscatprintf(sdsempty(),"-Writing to master: %s", 880 strerror(errno)); 881 } 882 sdsfree(cmd); 883 884 /* Read the reply from the server. */ 885 if (syncReadLine(fd,buf,sizeof(buf),server.repl_syncio_timeout*1000) == -1) 886 { 887 return sdscatprintf(sdsempty(),"-Reading from master: %s", 888 strerror(errno)); 889 } 890 return sdsnew(buf); 891 } 892 893 /* Try a partial resynchronization with the master if we are about to reconnect. 894 * If there is no cached master structure, at least try to issue a 895 * "PSYNC ? -1" command in order to trigger a full resync using the PSYNC 896 * command in order to obtain the master run id and the master replication 897 * global offset. 898 * 899 * This function is designed to be called from syncWithMaster(), so the 900 * following assumptions are made: 901 * 902 * 1) We pass the function an already connected socket "fd". 903 * 2) This function does not close the file descriptor "fd". However in case 904 * of successful partial resynchronization, the function will reuse 905 * 'fd' as file descriptor of the server.master client structure. 906 * 907 * The function returns: 908 * 909 * PSYNC_CONTINUE: If the PSYNC command succeded and we can continue. 910 * PSYNC_FULLRESYNC: If PSYNC is supported but a full resync is needed. 911 * In this case the master run_id and global replication 912 * offset is saved. 913 * PSYNC_NOT_SUPPORTED: If the server does not understand PSYNC at all and 914 * the caller should fall back to SYNC. 915 */ 916 917 #define PSYNC_CONTINUE 0 918 #define PSYNC_FULLRESYNC 1 919 #define PSYNC_NOT_SUPPORTED 2 920 int slaveTryPartialResynchronization(int fd) { 921 char *psync_runid; 922 char psync_offset[32]; 923 sds reply; 924 925 /* Initially set repl_master_initial_offset to -1 to mark the current 926 * master run_id and offset as not valid. Later if we'll be able to do 927 * a FULL resync using the PSYNC command we'll set the offset at the 928 * right value, so that this information will be propagated to the 929 * client structure representing the master into server.master. */ 930 server.repl_master_initial_offset = -1; 931 932 if (server.cached_master) { 933 psync_runid = server.cached_master->replrunid; 934 snprintf(psync_offset,sizeof(psync_offset),"%lld", server.cached_master->reploff+1); 935 redisLog(REDIS_NOTICE,"Trying a partial resynchronization (request %s:%s).", psync_runid, psync_offset); 936 } else { 937 redisLog(REDIS_NOTICE,"Partial resynchronization not possible (no cached master)"); 938 psync_runid = "?"; 939 memcpy(psync_offset,"-1",3); 940 } 941 942 /* Issue the PSYNC command */ 943 reply = sendSynchronousCommand(fd,"PSYNC",psync_runid,psync_offset,NULL); 944 945 if (!strncmp(reply,"+FULLRESYNC",11)) { 946 char *runid = NULL, *offset = NULL; 947 948 /* FULL RESYNC, parse the reply in order to extract the run id 949 * and the replication offset. */ 950 runid = strchr(reply,' '); 951 if (runid) { 952 runid++; 953 offset = strchr(runid,' '); 954 if (offset) offset++; 955 } 956 if (!runid || !offset || (offset-runid-1) != REDIS_RUN_ID_SIZE) { 957 redisLog(REDIS_WARNING, 958 "Master replied with wrong +FULLRESYNC syntax."); 959 /* This is an unexpected condition, actually the +FULLRESYNC 960 * reply means that the master supports PSYNC, but the reply 961 * format seems wrong. To stay safe we blank the master 962 * runid to make sure next PSYNCs will fail. */ 963 memset(server.repl_master_runid,0,REDIS_RUN_ID_SIZE+1); 964 } else { 965 memcpy(server.repl_master_runid, runid, offset-runid-1); 966 server.repl_master_runid[REDIS_RUN_ID_SIZE] = '\0'; 967 server.repl_master_initial_offset = strtoll(offset,NULL,10); 968 redisLog(REDIS_NOTICE,"Full resync from master: %s:%lld", 969 server.repl_master_runid, 970 server.repl_master_initial_offset); 971 } 972 /* We are going to full resync, discard the cached master structure. */ 973 replicationDiscardCachedMaster(); 974 sdsfree(reply); 975 return PSYNC_FULLRESYNC; 976 } 977 978 if (!strncmp(reply,"+CONTINUE",9)) { 979 /* Partial resync was accepted, set the replication state accordingly */ 980 redisLog(REDIS_NOTICE, 981 "Successful partial resynchronization with master."); 982 sdsfree(reply); 983 replicationResurrectCachedMaster(fd); 984 return PSYNC_CONTINUE; 985 } 986 987 /* If we reach this point we receied either an error since the master does 988 * not understand PSYNC, or an unexpected reply from the master. 989 * Reply with PSYNC_NOT_SUPPORTED in both cases. */ 990 991 if (strncmp(reply,"-ERR",4)) { 992 /* If it's not an error, log the unexpected event. */ 993 redisLog(REDIS_WARNING, 994 "Unexpected reply to PSYNC from master: %s", reply); 995 } else { 996 redisLog(REDIS_NOTICE, 997 "Master does not support PSYNC or is in " 998 "error state (reply: %s)", reply); 999 } 1000 sdsfree(reply); 1001 replicationDiscardCachedMaster(); 1002 return PSYNC_NOT_SUPPORTED; 1003 } 1004 1005 void syncWithMaster(aeEventLoop *el, int fd, void *privdata, int mask) { 1006 char tmpfile[256], *err; 1007 int dfd, maxtries = 5; 1008 int sockerr = 0, psync_result; 1009 socklen_t errlen = sizeof(sockerr); 1010 REDIS_NOTUSED(el); 1011 REDIS_NOTUSED(privdata); 1012 REDIS_NOTUSED(mask); 1013 1014 /* If this event fired after the user turned the instance into a master 1015 * with SLAVEOF NO ONE we must just return ASAP. */ 1016 if (server.repl_state == REDIS_REPL_NONE) { 1017 close(fd); 1018 return; 1019 } 1020 1021 /* Check for errors in the socket. */ 1022 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &sockerr, &errlen) == -1) 1023 sockerr = errno; 1024 if (sockerr) { 1025 aeDeleteFileEvent(server.el,fd,AE_READABLE|AE_WRITABLE); 1026 redisLog(REDIS_WARNING,"Error condition on socket for SYNC: %s", 1027 strerror(sockerr)); 1028 goto error; 1029 } 1030 1031 /* If we were connecting, it's time to send a non blocking PING, we want to 1032 * make sure the master is able to reply before going into the actual 1033 * replication process where we have long timeouts in the order of 1034 * seconds (in the meantime the slave would block). */ 1035 if (server.repl_state == REDIS_REPL_CONNECTING) { 1036 redisLog(REDIS_NOTICE,"Non blocking connect for SYNC fired the event."); 1037 /* Delete the writable event so that the readable event remains 1038 * registered and we can wait for the PONG reply. */ 1039 aeDeleteFileEvent(server.el,fd,AE_WRITABLE); 1040 server.repl_state = REDIS_REPL_RECEIVE_PONG; 1041 /* Send the PING, don't check for errors at all, we have the timeout 1042 * that will take care about this. */ 1043 syncWrite(fd,"PING\r\n",6,100); 1044 return; 1045 } 1046 1047 /* Receive the PONG command. */ 1048 if (server.repl_state == REDIS_REPL_RECEIVE_PONG) { 1049 char buf[1024]; 1050 1051 /* Delete the readable event, we no longer need it now that there is 1052 * the PING reply to read. */ 1053 aeDeleteFileEvent(server.el,fd,AE_READABLE); 1054 1055 /* Read the reply with explicit timeout. */ 1056 buf[0] = '\0'; 1057 if (syncReadLine(fd,buf,sizeof(buf), 1058 server.repl_syncio_timeout*1000) == -1) 1059 { 1060 redisLog(REDIS_WARNING, 1061 "I/O error reading PING reply from master: %s", 1062 strerror(errno)); 1063 goto error; 1064 } 1065 1066 /* We accept only two replies as valid, a positive +PONG reply 1067 * (we just check for "+") or an authentication error. 1068 * Note that older versions of Redis replied with "operation not 1069 * permitted" instead of using a proper error code, so we test 1070 * both. */ 1071 if (buf[0] != '+' && 1072 strncmp(buf,"-NOAUTH",7) != 0 && 1073 strncmp(buf,"-ERR operation not permitted",28) != 0) 1074 { 1075 redisLog(REDIS_WARNING,"Error reply to PING from master: '%s'",buf); 1076 goto error; 1077 } else { 1078 redisLog(REDIS_NOTICE, 1079 "Master replied to PING, replication can continue..."); 1080 } 1081 } 1082 1083 /* AUTH with the master if required. */ 1084 if(server.masterauth) { 1085 err = sendSynchronousCommand(fd,"AUTH",server.masterauth,NULL); 1086 if (err[0] == '-') { 1087 redisLog(REDIS_WARNING,"Unable to AUTH to MASTER: %s",err); 1088 sdsfree(err); 1089 goto error; 1090 } 1091 sdsfree(err); 1092 } 1093 1094 /* Set the slave port, so that Master's INFO command can list the 1095 * slave listening port correctly. */ 1096 { 1097 sds port = sdsfromlonglong(server.port); 1098 err = sendSynchronousCommand(fd,"REPLCONF","listening-port",port, 1099 NULL); 1100 sdsfree(port); 1101 /* Ignore the error if any, not all the Redis versions support 1102 * REPLCONF listening-port. */ 1103 if (err[0] == '-') { 1104 redisLog(REDIS_NOTICE,"(Non critical) Master does not understand REPLCONF listening-port: %s", err); 1105 } 1106 sdsfree(err); 1107 } 1108 1109 /* Try a partial resynchonization. If we don't have a cached master 1110 * slaveTryPartialResynchronization() will at least try to use PSYNC 1111 * to start a full resynchronization so that we get the master run id 1112 * and the global offset, to try a partial resync at the next 1113 * reconnection attempt. */ 1114 psync_result = slaveTryPartialResynchronization(fd); 1115 if (psync_result == PSYNC_CONTINUE) { 1116 redisLog(REDIS_NOTICE, "MASTER <-> SLAVE sync: Master accepted a Partial Resynchronization."); 1117 return; 1118 } 1119 1120 /* Fall back to SYNC if needed. Otherwise psync_result == PSYNC_FULLRESYNC 1121 * and the server.repl_master_runid and repl_master_initial_offset are 1122 * already populated. */ 1123 if (psync_result == PSYNC_NOT_SUPPORTED) { 1124 redisLog(REDIS_NOTICE,"Retrying with SYNC..."); 1125 if (syncWrite(fd,"SYNC\r\n",6,server.repl_syncio_timeout*1000) == -1) { 1126 redisLog(REDIS_WARNING,"I/O error writing to MASTER: %s", 1127 strerror(errno)); 1128 goto error; 1129 } 1130 } 1131 1132 /* Prepare a suitable temp file for bulk transfer */ 1133 while(maxtries--) { 1134 snprintf(tmpfile,256, 1135 "temp-%d.%ld.rdb",(int)server.unixtime,(long int)getpid()); 1136 dfd = open(tmpfile,O_CREAT|O_WRONLY|O_EXCL,0644); 1137 if (dfd != -1) break; 1138 sleep(1); 1139 } 1140 if (dfd == -1) { 1141 redisLog(REDIS_WARNING,"Opening the temp file needed for MASTER <-> SLAVE synchronization: %s",strerror(errno)); 1142 goto error; 1143 } 1144 1145 /* Setup the non blocking download of the bulk file. */ 1146 if (aeCreateFileEvent(server.el,fd, AE_READABLE,readSyncBulkPayload,NULL) 1147 == AE_ERR) 1148 { 1149 redisLog(REDIS_WARNING, 1150 "Can't create readable event for SYNC: %s (fd=%d)", 1151 strerror(errno),fd); 1152 goto error; 1153 } 1154 1155 server.repl_state = REDIS_REPL_TRANSFER; 1156 server.repl_transfer_size = -1; 1157 server.repl_transfer_read = 0; 1158 server.repl_transfer_last_fsync_off = 0; 1159 server.repl_transfer_fd = dfd; 1160 server.repl_transfer_lastio = server.unixtime; 1161 server.repl_transfer_tmpfile = zstrdup(tmpfile); 1162 return; 1163 1164 error: 1165 close(fd); 1166 server.repl_transfer_s = -1; 1167 server.repl_state = REDIS_REPL_CONNECT; 1168 return; 1169 } 1170 1171 int connectWithMaster(void) { 1172 int fd; 1173 1174 fd = anetTcpNonBlockConnect(NULL,server.masterhost,server.masterport); 1175 if (fd == -1) { 1176 redisLog(REDIS_WARNING,"Unable to connect to MASTER: %s", 1177 strerror(errno)); 1178 return REDIS_ERR; 1179 } 1180 1181 if (aeCreateFileEvent(server.el,fd,AE_READABLE|AE_WRITABLE,syncWithMaster,NULL) == 1182 AE_ERR) 1183 { 1184 close(fd); 1185 redisLog(REDIS_WARNING,"Can't create readable event for SYNC"); 1186 return REDIS_ERR; 1187 } 1188 1189 server.repl_transfer_lastio = server.unixtime; 1190 server.repl_transfer_s = fd; 1191 server.repl_state = REDIS_REPL_CONNECTING; 1192 return REDIS_OK; 1193 } 1194 1195 /* This function can be called when a non blocking connection is currently 1196 * in progress to undo it. */ 1197 void undoConnectWithMaster(void) { 1198 int fd = server.repl_transfer_s; 1199 1200 redisAssert(server.repl_state == REDIS_REPL_CONNECTING || 1201 server.repl_state == REDIS_REPL_RECEIVE_PONG); 1202 aeDeleteFileEvent(server.el,fd,AE_READABLE|AE_WRITABLE); 1203 close(fd); 1204 server.repl_transfer_s = -1; 1205 server.repl_state = REDIS_REPL_CONNECT; 1206 } 1207 1208 /* This function aborts a non blocking replication attempt if there is one 1209 * in progress, by canceling the non-blocking connect attempt or 1210 * the initial bulk transfer. 1211 * 1212 * If there was a replication handshake in progress 1 is returned and 1213 * the replication state (server.repl_state) set to REDIS_REPL_CONNECT. 1214 * 1215 * Otherwise zero is returned and no operation is perforemd at all. */ 1216 int cancelReplicationHandshake(void) { 1217 if (server.repl_state == REDIS_REPL_TRANSFER) { 1218 replicationAbortSyncTransfer(); 1219 } else if (server.repl_state == REDIS_REPL_CONNECTING || 1220 server.repl_state == REDIS_REPL_RECEIVE_PONG) 1221 { 1222 undoConnectWithMaster(); 1223 } else { 1224 return 0; 1225 } 1226 return 1; 1227 } 1228 1229 /* Set replication to the specified master address and port. */ 1230 void replicationSetMaster(char *ip, int port) { 1231 sdsfree(server.masterhost); 1232 server.masterhost = sdsnew(ip); 1233 server.masterport = port; 1234 if (server.master) freeClient(server.master); 1235 disconnectSlaves(); /* Force our slaves to resync with us as well. */ 1236 replicationDiscardCachedMaster(); /* Don't try a PSYNC. */ 1237 freeReplicationBacklog(); /* Don't allow our chained slaves to PSYNC. */ 1238 cancelReplicationHandshake(); 1239 server.repl_state = REDIS_REPL_CONNECT; 1240 } 1241 1242 /* Cancel replication, setting the instance as a master itself. */ 1243 void replicationUnsetMaster(void) { 1244 if (server.masterhost == NULL) return; /* Nothing to do. */ 1245 sdsfree(server.masterhost); 1246 server.masterhost = NULL; 1247 if (server.master) freeClient(server.master); 1248 replicationDiscardCachedMaster(); 1249 cancelReplicationHandshake(); 1250 server.repl_state = REDIS_REPL_NONE; 1251 } 1252 1253 void slaveofCommand(redisClient *c) { 1254 /* SLAVEOF is not allowed in cluster mode as replication is automatically 1255 * configured using the current address of the master node. */ 1256 if (server.cluster_enabled) { 1257 addReplyError(c,"SLAVEOF not allowed in cluster mode."); 1258 return; 1259 } 1260 1261 /* The special host/port combination "NO" "ONE" turns the instance 1262 * into a master. Otherwise the new master address is set. */ 1263 if (!strcasecmp(c->argv[1]->ptr,"no") && 1264 !strcasecmp(c->argv[2]->ptr,"one")) { 1265 if (server.masterhost) { 1266 replicationUnsetMaster(); 1267 redisLog(REDIS_NOTICE,"MASTER MODE enabled (user request)"); 1268 } 1269 } else { 1270 long port; 1271 1272 if ((getLongFromObjectOrReply(c, c->argv[2], &port, NULL) != REDIS_OK)) 1273 return; 1274 1275 /* Check if we are already attached to the specified slave */ 1276 if (server.masterhost && !strcasecmp(server.masterhost,c->argv[1]->ptr) 1277 && server.masterport == port) { 1278 redisLog(REDIS_NOTICE,"SLAVE OF would result into synchronization with the master we are already connected with. No operation performed."); 1279 addReplySds(c,sdsnew("+OK Already connected to specified master\r\n")); 1280 return; 1281 } 1282 /* There was no previous master or the user specified a different one, 1283 * we can continue. */ 1284 replicationSetMaster(c->argv[1]->ptr, port); 1285 redisLog(REDIS_NOTICE,"SLAVE OF %s:%d enabled (user request)", 1286 server.masterhost, server.masterport); 1287 } 1288 addReply(c,shared.ok); 1289 } 1290 1291 /* ---------------------- MASTER CACHING FOR PSYNC -------------------------- */ 1292 1293 /* In order to implement partial synchronization we need to be able to cache 1294 * our master's client structure after a transient disconnection. 1295 * It is cached into server.cached_master and flushed away using the following 1296 * functions. */ 1297 1298 /* This function is called by freeClient() in order to cache the master 1299 * client structure instead of destryoing it. freeClient() will return 1300 * ASAP after this function returns, so every action needed to avoid problems 1301 * with a client that is really "suspended" has to be done by this function. 1302 * 1303 * The other functions that will deal with the cached master are: 1304 * 1305 * replicationDiscardCachedMaster() that will make sure to kill the client 1306 * as for some reason we don't want to use it in the future. 1307 * 1308 * replicationResurrectCachedMaster() that is used after a successful PSYNC 1309 * handshake in order to reactivate the cached master. 1310 */ 1311 void replicationCacheMaster(redisClient *c) { 1312 listNode *ln; 1313 1314 redisAssert(server.master != NULL && server.cached_master == NULL); 1315 redisLog(REDIS_NOTICE,"Caching the disconnected master state."); 1316 1317 /* Remove from the list of clients, we don't want this client to be 1318 * listed by CLIENT LIST or processed in any way by batch operations. */ 1319 ln = listSearchKey(server.clients,c); 1320 redisAssert(ln != NULL); 1321 listDelNode(server.clients,ln); 1322 1323 /* Save the master. Server.master will be set to null later by 1324 * replicationHandleMasterDisconnection(). */ 1325 server.cached_master = server.master; 1326 1327 /* Remove the event handlers and close the socket. We'll later reuse 1328 * the socket of the new connection with the master during PSYNC. */ 1329 aeDeleteFileEvent(server.el,c->fd,AE_READABLE); 1330 aeDeleteFileEvent(server.el,c->fd,AE_WRITABLE); 1331 close(c->fd); 1332 1333 /* Set fd to -1 so that we can safely call freeClient(c) later. */ 1334 c->fd = -1; 1335 1336 /* Caching the master happens instead of the actual freeClient() call, 1337 * so make sure to adjust the replication state. This function will 1338 * also set server.master to NULL. */ 1339 replicationHandleMasterDisconnection(); 1340 } 1341 1342 /* Free a cached master, called when there are no longer the conditions for 1343 * a partial resync on reconnection. */ 1344 void replicationDiscardCachedMaster(void) { 1345 if (server.cached_master == NULL) return; 1346 1347 redisLog(REDIS_NOTICE,"Discarding previously cached master state."); 1348 server.cached_master->flags &= ~REDIS_MASTER; 1349 freeClient(server.cached_master); 1350 server.cached_master = NULL; 1351 } 1352 1353 /* Turn the cached master into the current master, using the file descriptor 1354 * passed as argument as the socket for the new master. 1355 * 1356 * This funciton is called when successfully setup a partial resynchronization 1357 * so the stream of data that we'll receive will start from were this 1358 * master left. */ 1359 void replicationResurrectCachedMaster(int newfd) { 1360 server.master = server.cached_master; 1361 server.cached_master = NULL; 1362 server.master->fd = newfd; 1363 server.master->flags &= ~(REDIS_CLOSE_AFTER_REPLY|REDIS_CLOSE_ASAP); 1364 server.master->authenticated = 1; 1365 server.master->lastinteraction = server.unixtime; 1366 server.repl_state = REDIS_REPL_CONNECTED; 1367 1368 /* Re-add to the list of clients. */ 1369 listAddNodeTail(server.clients,server.master); 1370 if (aeCreateFileEvent(server.el, newfd, AE_READABLE, 1371 readQueryFromClient, server.master)) { 1372 redisLog(REDIS_WARNING,"Error resurrecting the cached master, impossible to add the readable handler: %s", strerror(errno)); 1373 freeClientAsync(server.master); /* Close ASAP. */ 1374 } 1375 } 1376 1377 /* --------------------------- REPLICATION CRON ---------------------------- */ 1378 1379 void replicationCron(void) { 1380 /* Non blocking connection timeout? */ 1381 if (server.masterhost && 1382 (server.repl_state == REDIS_REPL_CONNECTING || 1383 server.repl_state == REDIS_REPL_RECEIVE_PONG) && 1384 (time(NULL)-server.repl_transfer_lastio) > server.repl_timeout) 1385 { 1386 redisLog(REDIS_WARNING,"Timeout connecting to the MASTER..."); 1387 undoConnectWithMaster(); 1388 } 1389 1390 /* Bulk transfer I/O timeout? */ 1391 if (server.masterhost && server.repl_state == REDIS_REPL_TRANSFER && 1392 (time(NULL)-server.repl_transfer_lastio) > server.repl_timeout) 1393 { 1394 redisLog(REDIS_WARNING,"Timeout receiving bulk data from MASTER... If the problem persists try to set the 'repl-timeout' parameter in redis.conf to a larger value."); 1395 replicationAbortSyncTransfer(); 1396 } 1397 1398 /* Timed out master when we are an already connected slave? */ 1399 if (server.masterhost && server.repl_state == REDIS_REPL_CONNECTED && 1400 (time(NULL)-server.master->lastinteraction) > server.repl_timeout) 1401 { 1402 redisLog(REDIS_WARNING,"MASTER time out: no data nor PING received..."); 1403 freeClient(server.master); 1404 } 1405 1406 /* Check if we should connect to a MASTER */ 1407 if (server.repl_state == REDIS_REPL_CONNECT) { 1408 redisLog(REDIS_NOTICE,"Connecting to MASTER..."); 1409 if (connectWithMaster() == REDIS_OK) { 1410 redisLog(REDIS_NOTICE,"MASTER <-> SLAVE sync started"); 1411 } 1412 } 1413 1414 /* If we have attached slaves, PING them from time to time. 1415 * So slaves can implement an explicit timeout to masters, and will 1416 * be able to detect a link disconnection even if the TCP connection 1417 * will not actually go down. */ 1418 if (!(server.cronloops % (server.repl_ping_slave_period * server.hz))) { 1419 listIter li; 1420 listNode *ln; 1421 robj *ping_argv[1]; 1422 1423 /* First, send PING */ 1424 ping_argv[0] = createStringObject("PING",4); 1425 replicationFeedSlaves(server.slaves, server.slaveseldb, ping_argv, 1); 1426 decrRefCount(ping_argv[0]); 1427 1428 /* Second, send a newline to all the slaves in pre-synchronization 1429 * stage, that is, slaves waiting for the master to create the RDB file. 1430 * The newline will be ignored by the slave but will refresh the 1431 * last-io timer preventing a timeout. */ 1432 listRewind(server.slaves,&li); 1433 while((ln = listNext(&li))) { 1434 redisClient *slave = ln->value; 1435 1436 if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_START || 1437 slave->replstate == REDIS_REPL_WAIT_BGSAVE_END) { 1438 if (write(slave->fd, "\n", 1) == -1) { 1439 /* Don't worry, it's just a ping. */ 1440 } 1441 } 1442 } 1443 } 1444 1445 /* If we have no attached slaves and there is a replication backlog 1446 * using memory, free it after some (configured) time. */ 1447 if (listLength(server.slaves) == 0 && server.repl_backlog_time_limit && 1448 server.repl_backlog) 1449 { 1450 time_t idle = server.unixtime - server.repl_no_slaves_since; 1451 1452 if (idle > server.repl_backlog_time_limit) { 1453 freeReplicationBacklog(); 1454 redisLog(REDIS_NOTICE, 1455 "Replication backlog freed after %d seconds " 1456 "without connected slaves.", 1457 (int) server.repl_backlog_time_limit); 1458 } 1459 } 1460 } 1461