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 c->repl_ack_time = server.unixtime; 428 listAddNodeTail(server.slaves,c); 429 /* We can't use the connection buffers since they are used to accumulate 430 * new commands at this stage. But we are sure the socket send buffer is 431 * emtpy so this write will never fail actually. */ 432 buflen = snprintf(buf,sizeof(buf),"+CONTINUE\r\n"); 433 if (write(c->fd,buf,buflen) != buflen) { 434 freeClientAsync(c); 435 return REDIS_OK; 436 } 437 psync_len = addReplyReplicationBacklog(c,psync_offset); 438 redisLog(REDIS_NOTICE, 439 "Partial resynchronization request accepted. Sending %lld bytes of backlog starting from offset %lld.", psync_len, psync_offset); 440 /* Note that we don't need to set the selected DB at server.slaveseldb 441 * to -1 to force the master to emit SELECT, since the slave already 442 * has this state from the previous connection with the master. */ 443 444 refreshGoodSlavesCount(); 445 return REDIS_OK; /* The caller can return, no full resync needed. */ 446 447 need_full_resync: 448 /* We need a full resync for some reason... notify the client. */ 449 psync_offset = server.master_repl_offset; 450 /* Add 1 to psync_offset if it the replication backlog does not exists 451 * as when it will be created later we'll increment the offset by one. */ 452 if (server.repl_backlog == NULL) psync_offset++; 453 /* Again, we can't use the connection buffers (see above). */ 454 buflen = snprintf(buf,sizeof(buf),"+FULLRESYNC %s %lld\r\n", 455 server.runid,psync_offset); 456 if (write(c->fd,buf,buflen) != buflen) { 457 freeClientAsync(c); 458 return REDIS_OK; 459 } 460 return REDIS_ERR; 461 } 462 463 /* SYNC ad PSYNC command implemenation. */ 464 void syncCommand(redisClient *c) { 465 /* ignore SYNC if already slave or in monitor mode */ 466 if (c->flags & REDIS_SLAVE) return; 467 468 /* Refuse SYNC requests if we are a slave but the link with our master 469 * is not ok... */ 470 if (server.masterhost && server.repl_state != REDIS_REPL_CONNECTED) { 471 addReplyError(c,"Can't SYNC while not connected with my master"); 472 return; 473 } 474 475 /* SYNC can't be issued when the server has pending data to send to 476 * the client about already issued commands. We need a fresh reply 477 * buffer registering the differences between the BGSAVE and the current 478 * dataset, so that we can copy to other slaves if needed. */ 479 if (listLength(c->reply) != 0 || c->bufpos != 0) { 480 addReplyError(c,"SYNC and PSYNC are invalid with pending output"); 481 return; 482 } 483 484 redisLog(REDIS_NOTICE,"Slave asks for synchronization"); 485 486 /* Try a partial resynchronization if this is a PSYNC command. 487 * If it fails, we continue with usual full resynchronization, however 488 * when this happens masterTryPartialResynchronization() already 489 * replied with: 490 * 491 * +FULLRESYNC <runid> <offset> 492 * 493 * So the slave knows the new runid and offset to try a PSYNC later 494 * if the connection with the master is lost. */ 495 if (!strcasecmp(c->argv[0]->ptr,"psync")) { 496 if (masterTryPartialResynchronization(c) == REDIS_OK) { 497 server.stat_sync_partial_ok++; 498 return; /* No full resync needed, return. */ 499 } else { 500 char *master_runid = c->argv[1]->ptr; 501 502 /* Increment stats for failed PSYNCs, but only if the 503 * runid is not "?", as this is used by slaves to force a full 504 * resync on purpose when they are not albe to partially 505 * resync. */ 506 if (master_runid[0] != '?') server.stat_sync_partial_err++; 507 } 508 } 509 510 /* Full resynchronization. */ 511 server.stat_sync_full++; 512 513 /* Here we need to check if there is a background saving operation 514 * in progress, or if it is required to start one */ 515 if (server.rdb_child_pid != -1) { 516 /* Ok a background save is in progress. Let's check if it is a good 517 * one for replication, i.e. if there is another slave that is 518 * registering differences since the server forked to save */ 519 redisClient *slave; 520 listNode *ln; 521 listIter li; 522 523 listRewind(server.slaves,&li); 524 while((ln = listNext(&li))) { 525 slave = ln->value; 526 if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_END) break; 527 } 528 if (ln) { 529 /* Perfect, the server is already registering differences for 530 * another slave. Set the right state, and copy the buffer. */ 531 copyClientOutputBuffer(c,slave); 532 c->replstate = REDIS_REPL_WAIT_BGSAVE_END; 533 redisLog(REDIS_NOTICE,"Waiting for end of BGSAVE for SYNC"); 534 } else { 535 /* No way, we need to wait for the next BGSAVE in order to 536 * register differences */ 537 c->replstate = REDIS_REPL_WAIT_BGSAVE_START; 538 redisLog(REDIS_NOTICE,"Waiting for next BGSAVE for SYNC"); 539 } 540 } else { 541 /* Ok we don't have a BGSAVE in progress, let's start one */ 542 redisLog(REDIS_NOTICE,"Starting BGSAVE for SYNC"); 543 if (rdbSaveBackground(server.rdb_filename) != REDIS_OK) { 544 redisLog(REDIS_NOTICE,"Replication failed, can't BGSAVE"); 545 addReplyError(c,"Unable to perform background save"); 546 return; 547 } 548 c->replstate = REDIS_REPL_WAIT_BGSAVE_END; 549 } 550 551 if (server.repl_disable_tcp_nodelay) 552 anetDisableTcpNoDelay(NULL, c->fd); /* Non critical if it fails. */ 553 c->repldbfd = -1; 554 c->flags |= REDIS_SLAVE; 555 server.slaveseldb = -1; /* Force to re-emit the SELECT command. */ 556 listAddNodeTail(server.slaves,c); 557 if (listLength(server.slaves) == 1 && server.repl_backlog == NULL) 558 createReplicationBacklog(); 559 return; 560 } 561 562 /* REPLCONF <option> <value> <option> <value> ... 563 * This command is used by a slave in order to configure the replication 564 * process before starting it with the SYNC command. 565 * 566 * Currently the only use of this command is to communicate to the master 567 * what is the listening port of the Slave redis instance, so that the 568 * master can accurately list slaves and their listening ports in 569 * the INFO output. 570 * 571 * In the future the same command can be used in order to configure 572 * the replication to initiate an incremental replication instead of a 573 * full resync. */ 574 void replconfCommand(redisClient *c) { 575 int j; 576 577 if ((c->argc % 2) == 0) { 578 /* Number of arguments must be odd to make sure that every 579 * option has a corresponding value. */ 580 addReply(c,shared.syntaxerr); 581 return; 582 } 583 584 /* Process every option-value pair. */ 585 for (j = 1; j < c->argc; j+=2) { 586 if (!strcasecmp(c->argv[j]->ptr,"listening-port")) { 587 long port; 588 589 if ((getLongFromObjectOrReply(c,c->argv[j+1], 590 &port,NULL) != REDIS_OK)) 591 return; 592 c->slave_listening_port = port; 593 } else if (!strcasecmp(c->argv[j]->ptr,"ack")) { 594 /* REPLCONF ACK is used by slave to inform the master the amount 595 * of replication stream that it processed so far. It is an 596 * internal only command that normal clients should never use. */ 597 long long offset; 598 599 if (!(c->flags & REDIS_SLAVE)) return; 600 if ((getLongLongFromObject(c->argv[j+1], &offset) != REDIS_OK)) 601 return; 602 if (offset > c->repl_ack_off) 603 c->repl_ack_off = offset; 604 c->repl_ack_time = server.unixtime; 605 /* Note: this command does not reply anything! */ 606 return; 607 } else { 608 addReplyErrorFormat(c,"Unrecognized REPLCONF option: %s", 609 (char*)c->argv[j]->ptr); 610 return; 611 } 612 } 613 addReply(c,shared.ok); 614 } 615 616 void sendBulkToSlave(aeEventLoop *el, int fd, void *privdata, int mask) { 617 redisClient *slave = privdata; 618 REDIS_NOTUSED(el); 619 REDIS_NOTUSED(mask); 620 char buf[REDIS_IOBUF_LEN]; 621 ssize_t nwritten, buflen; 622 623 if (slave->repldboff == 0) { 624 /* Write the bulk write count before to transfer the DB. In theory here 625 * we don't know how much room there is in the output buffer of the 626 * socket, but in practice SO_SNDLOWAT (the minimum count for output 627 * operations) will never be smaller than the few bytes we need. */ 628 sds bulkcount; 629 630 bulkcount = sdscatprintf(sdsempty(),"$%lld\r\n",(unsigned long long) 631 slave->repldbsize); 632 if (write(fd,bulkcount,sdslen(bulkcount)) != (signed)sdslen(bulkcount)) 633 { 634 sdsfree(bulkcount); 635 freeClient(slave); 636 return; 637 } 638 sdsfree(bulkcount); 639 } 640 lseek(slave->repldbfd,slave->repldboff,SEEK_SET); 641 buflen = read(slave->repldbfd,buf,REDIS_IOBUF_LEN); 642 if (buflen <= 0) { 643 redisLog(REDIS_WARNING,"Read error sending DB to slave: %s", 644 (buflen == 0) ? "premature EOF" : strerror(errno)); 645 freeClient(slave); 646 return; 647 } 648 if ((nwritten = write(fd,buf,buflen)) == -1) { 649 redisLog(REDIS_VERBOSE,"Write error sending DB to slave: %s", 650 strerror(errno)); 651 freeClient(slave); 652 return; 653 } 654 slave->repldboff += nwritten; 655 if (slave->repldboff == slave->repldbsize) { 656 close(slave->repldbfd); 657 slave->repldbfd = -1; 658 aeDeleteFileEvent(server.el,slave->fd,AE_WRITABLE); 659 slave->replstate = REDIS_REPL_ONLINE; 660 slave->repl_ack_time = server.unixtime; 661 if (aeCreateFileEvent(server.el, slave->fd, AE_WRITABLE, 662 sendReplyToClient, slave) == AE_ERR) { 663 freeClient(slave); 664 return; 665 } 666 refreshGoodSlavesCount(); 667 redisLog(REDIS_NOTICE,"Synchronization with slave succeeded"); 668 } 669 } 670 671 /* This function is called at the end of every background saving. 672 * The argument bgsaveerr is REDIS_OK if the background saving succeeded 673 * otherwise REDIS_ERR is passed to the function. 674 * 675 * The goal of this function is to handle slaves waiting for a successful 676 * background saving in order to perform non-blocking synchronization. */ 677 void updateSlavesWaitingBgsave(int bgsaveerr) { 678 listNode *ln; 679 int startbgsave = 0; 680 listIter li; 681 682 listRewind(server.slaves,&li); 683 while((ln = listNext(&li))) { 684 redisClient *slave = ln->value; 685 686 if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_START) { 687 startbgsave = 1; 688 slave->replstate = REDIS_REPL_WAIT_BGSAVE_END; 689 } else if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_END) { 690 struct redis_stat buf; 691 692 if (bgsaveerr != REDIS_OK) { 693 freeClient(slave); 694 redisLog(REDIS_WARNING,"SYNC failed. BGSAVE child returned an error"); 695 continue; 696 } 697 if ((slave->repldbfd = open(server.rdb_filename,O_RDONLY)) == -1 || 698 redis_fstat(slave->repldbfd,&buf) == -1) { 699 freeClient(slave); 700 redisLog(REDIS_WARNING,"SYNC failed. Can't open/stat DB after BGSAVE: %s", strerror(errno)); 701 continue; 702 } 703 slave->repldboff = 0; 704 slave->repldbsize = buf.st_size; 705 slave->replstate = REDIS_REPL_SEND_BULK; 706 aeDeleteFileEvent(server.el,slave->fd,AE_WRITABLE); 707 if (aeCreateFileEvent(server.el, slave->fd, AE_WRITABLE, sendBulkToSlave, slave) == AE_ERR) { 708 freeClient(slave); 709 continue; 710 } 711 } 712 } 713 if (startbgsave) { 714 if (rdbSaveBackground(server.rdb_filename) != REDIS_OK) { 715 listIter li; 716 717 listRewind(server.slaves,&li); 718 redisLog(REDIS_WARNING,"SYNC failed. BGSAVE failed"); 719 while((ln = listNext(&li))) { 720 redisClient *slave = ln->value; 721 722 if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_START) 723 freeClient(slave); 724 } 725 } 726 } 727 } 728 729 /* ----------------------------------- SLAVE -------------------------------- */ 730 731 /* Abort the async download of the bulk dataset while SYNC-ing with master */ 732 void replicationAbortSyncTransfer(void) { 733 redisAssert(server.repl_state == REDIS_REPL_TRANSFER); 734 735 aeDeleteFileEvent(server.el,server.repl_transfer_s,AE_READABLE); 736 close(server.repl_transfer_s); 737 close(server.repl_transfer_fd); 738 unlink(server.repl_transfer_tmpfile); 739 zfree(server.repl_transfer_tmpfile); 740 server.repl_state = REDIS_REPL_CONNECT; 741 } 742 743 /* Asynchronously read the SYNC payload we receive from a master */ 744 #define REPL_MAX_WRITTEN_BEFORE_FSYNC (1024*1024*8) /* 8 MB */ 745 void readSyncBulkPayload(aeEventLoop *el, int fd, void *privdata, int mask) { 746 char buf[4096]; 747 ssize_t nread, readlen; 748 off_t left; 749 REDIS_NOTUSED(el); 750 REDIS_NOTUSED(privdata); 751 REDIS_NOTUSED(mask); 752 753 /* If repl_transfer_size == -1 we still have to read the bulk length 754 * from the master reply. */ 755 if (server.repl_transfer_size == -1) { 756 if (syncReadLine(fd,buf,1024,server.repl_syncio_timeout*1000) == -1) { 757 redisLog(REDIS_WARNING, 758 "I/O error reading bulk count from MASTER: %s", 759 strerror(errno)); 760 goto error; 761 } 762 763 if (buf[0] == '-') { 764 redisLog(REDIS_WARNING, 765 "MASTER aborted replication with an error: %s", 766 buf+1); 767 goto error; 768 } else if (buf[0] == '\0') { 769 /* At this stage just a newline works as a PING in order to take 770 * the connection live. So we refresh our last interaction 771 * timestamp. */ 772 server.repl_transfer_lastio = server.unixtime; 773 return; 774 } else if (buf[0] != '$') { 775 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); 776 goto error; 777 } 778 server.repl_transfer_size = strtol(buf+1,NULL,10); 779 redisLog(REDIS_NOTICE, 780 "MASTER <-> SLAVE sync: receiving %lld bytes from master", 781 (long long) server.repl_transfer_size); 782 return; 783 } 784 785 /* Read bulk data */ 786 left = server.repl_transfer_size - server.repl_transfer_read; 787 readlen = (left < (signed)sizeof(buf)) ? left : (signed)sizeof(buf); 788 nread = read(fd,buf,readlen); 789 if (nread <= 0) { 790 redisLog(REDIS_WARNING,"I/O error trying to sync with MASTER: %s", 791 (nread == -1) ? strerror(errno) : "connection lost"); 792 replicationAbortSyncTransfer(); 793 return; 794 } 795 server.repl_transfer_lastio = server.unixtime; 796 if (write(server.repl_transfer_fd,buf,nread) != nread) { 797 redisLog(REDIS_WARNING,"Write error or short write writing to the DB dump file needed for MASTER <-> SLAVE synchronization: %s", strerror(errno)); 798 goto error; 799 } 800 server.repl_transfer_read += nread; 801 802 /* Sync data on disk from time to time, otherwise at the end of the transfer 803 * we may suffer a big delay as the memory buffers are copied into the 804 * actual disk. */ 805 if (server.repl_transfer_read >= 806 server.repl_transfer_last_fsync_off + REPL_MAX_WRITTEN_BEFORE_FSYNC) 807 { 808 off_t sync_size = server.repl_transfer_read - 809 server.repl_transfer_last_fsync_off; 810 rdb_fsync_range(server.repl_transfer_fd, 811 server.repl_transfer_last_fsync_off, sync_size); 812 server.repl_transfer_last_fsync_off += sync_size; 813 } 814 815 /* Check if the transfer is now complete */ 816 if (server.repl_transfer_read == server.repl_transfer_size) { 817 if (rename(server.repl_transfer_tmpfile,server.rdb_filename) == -1) { 818 redisLog(REDIS_WARNING,"Failed trying to rename the temp DB into dump.rdb in MASTER <-> SLAVE synchronization: %s", strerror(errno)); 819 replicationAbortSyncTransfer(); 820 return; 821 } 822 redisLog(REDIS_NOTICE, "MASTER <-> SLAVE sync: Loading DB in memory"); 823 signalFlushedDb(-1); 824 emptyDb(); 825 /* Before loading the DB into memory we need to delete the readable 826 * handler, otherwise it will get called recursively since 827 * rdbLoad() will call the event loop to process events from time to 828 * time for non blocking loading. */ 829 aeDeleteFileEvent(server.el,server.repl_transfer_s,AE_READABLE); 830 if (rdbLoad(server.rdb_filename) != REDIS_OK) { 831 redisLog(REDIS_WARNING,"Failed trying to load the MASTER synchronization DB from disk"); 832 replicationAbortSyncTransfer(); 833 return; 834 } 835 /* Final setup of the connected slave <- master link */ 836 zfree(server.repl_transfer_tmpfile); 837 close(server.repl_transfer_fd); 838 server.master = createClient(server.repl_transfer_s); 839 server.master->flags |= REDIS_MASTER; 840 server.master->authenticated = 1; 841 server.repl_state = REDIS_REPL_CONNECTED; 842 server.master->reploff = server.repl_master_initial_offset; 843 memcpy(server.master->replrunid, server.repl_master_runid, 844 sizeof(server.repl_master_runid)); 845 redisLog(REDIS_NOTICE, "MASTER <-> SLAVE sync: Finished with success"); 846 /* Restart the AOF subsystem now that we finished the sync. This 847 * will trigger an AOF rewrite, and when done will start appending 848 * to the new file. */ 849 if (server.aof_state != REDIS_AOF_OFF) { 850 int retry = 10; 851 852 stopAppendOnly(); 853 while (retry-- && startAppendOnly() == REDIS_ERR) { 854 redisLog(REDIS_WARNING,"Failed enabling the AOF after successful master synchronization! Trying it again in one second."); 855 sleep(1); 856 } 857 if (!retry) { 858 redisLog(REDIS_WARNING,"FATAL: this slave instance finished the synchronization with its master, but the AOF can't be turned on. Exiting now."); 859 exit(1); 860 } 861 } 862 } 863 864 return; 865 866 error: 867 replicationAbortSyncTransfer(); 868 return; 869 } 870 871 /* Send a synchronous command to the master. Used to send AUTH and 872 * REPLCONF commands before starting the replication with SYNC. 873 * 874 * The command returns an sds string representing the result of the 875 * operation. On error the first byte is a "-". 876 */ 877 char *sendSynchronousCommand(int fd, ...) { 878 va_list ap; 879 sds cmd = sdsempty(); 880 char *arg, buf[256]; 881 882 /* Create the command to send to the master, we use simple inline 883 * protocol for simplicity as currently we only send simple strings. */ 884 va_start(ap,fd); 885 while(1) { 886 arg = va_arg(ap, char*); 887 if (arg == NULL) break; 888 889 if (sdslen(cmd) != 0) cmd = sdscatlen(cmd," ",1); 890 cmd = sdscat(cmd,arg); 891 } 892 cmd = sdscatlen(cmd,"\r\n",2); 893 894 /* Transfer command to the server. */ 895 if (syncWrite(fd,cmd,sdslen(cmd),server.repl_syncio_timeout*1000) == -1) { 896 sdsfree(cmd); 897 return sdscatprintf(sdsempty(),"-Writing to master: %s", 898 strerror(errno)); 899 } 900 sdsfree(cmd); 901 902 /* Read the reply from the server. */ 903 if (syncReadLine(fd,buf,sizeof(buf),server.repl_syncio_timeout*1000) == -1) 904 { 905 return sdscatprintf(sdsempty(),"-Reading from master: %s", 906 strerror(errno)); 907 } 908 return sdsnew(buf); 909 } 910 911 /* Try a partial resynchronization with the master if we are about to reconnect. 912 * If there is no cached master structure, at least try to issue a 913 * "PSYNC ? -1" command in order to trigger a full resync using the PSYNC 914 * command in order to obtain the master run id and the master replication 915 * global offset. 916 * 917 * This function is designed to be called from syncWithMaster(), so the 918 * following assumptions are made: 919 * 920 * 1) We pass the function an already connected socket "fd". 921 * 2) This function does not close the file descriptor "fd". However in case 922 * of successful partial resynchronization, the function will reuse 923 * 'fd' as file descriptor of the server.master client structure. 924 * 925 * The function returns: 926 * 927 * PSYNC_CONTINUE: If the PSYNC command succeded and we can continue. 928 * PSYNC_FULLRESYNC: If PSYNC is supported but a full resync is needed. 929 * In this case the master run_id and global replication 930 * offset is saved. 931 * PSYNC_NOT_SUPPORTED: If the server does not understand PSYNC at all and 932 * the caller should fall back to SYNC. 933 */ 934 935 #define PSYNC_CONTINUE 0 936 #define PSYNC_FULLRESYNC 1 937 #define PSYNC_NOT_SUPPORTED 2 938 int slaveTryPartialResynchronization(int fd) { 939 char *psync_runid; 940 char psync_offset[32]; 941 sds reply; 942 943 /* Initially set repl_master_initial_offset to -1 to mark the current 944 * master run_id and offset as not valid. Later if we'll be able to do 945 * a FULL resync using the PSYNC command we'll set the offset at the 946 * right value, so that this information will be propagated to the 947 * client structure representing the master into server.master. */ 948 server.repl_master_initial_offset = -1; 949 950 if (server.cached_master) { 951 psync_runid = server.cached_master->replrunid; 952 snprintf(psync_offset,sizeof(psync_offset),"%lld", server.cached_master->reploff+1); 953 redisLog(REDIS_NOTICE,"Trying a partial resynchronization (request %s:%s).", psync_runid, psync_offset); 954 } else { 955 redisLog(REDIS_NOTICE,"Partial resynchronization not possible (no cached master)"); 956 psync_runid = "?"; 957 memcpy(psync_offset,"-1",3); 958 } 959 960 /* Issue the PSYNC command */ 961 reply = sendSynchronousCommand(fd,"PSYNC",psync_runid,psync_offset,NULL); 962 963 if (!strncmp(reply,"+FULLRESYNC",11)) { 964 char *runid = NULL, *offset = NULL; 965 966 /* FULL RESYNC, parse the reply in order to extract the run id 967 * and the replication offset. */ 968 runid = strchr(reply,' '); 969 if (runid) { 970 runid++; 971 offset = strchr(runid,' '); 972 if (offset) offset++; 973 } 974 if (!runid || !offset || (offset-runid-1) != REDIS_RUN_ID_SIZE) { 975 redisLog(REDIS_WARNING, 976 "Master replied with wrong +FULLRESYNC syntax."); 977 /* This is an unexpected condition, actually the +FULLRESYNC 978 * reply means that the master supports PSYNC, but the reply 979 * format seems wrong. To stay safe we blank the master 980 * runid to make sure next PSYNCs will fail. */ 981 memset(server.repl_master_runid,0,REDIS_RUN_ID_SIZE+1); 982 } else { 983 memcpy(server.repl_master_runid, runid, offset-runid-1); 984 server.repl_master_runid[REDIS_RUN_ID_SIZE] = '\0'; 985 server.repl_master_initial_offset = strtoll(offset,NULL,10); 986 redisLog(REDIS_NOTICE,"Full resync from master: %s:%lld", 987 server.repl_master_runid, 988 server.repl_master_initial_offset); 989 } 990 /* We are going to full resync, discard the cached master structure. */ 991 replicationDiscardCachedMaster(); 992 sdsfree(reply); 993 return PSYNC_FULLRESYNC; 994 } 995 996 if (!strncmp(reply,"+CONTINUE",9)) { 997 /* Partial resync was accepted, set the replication state accordingly */ 998 redisLog(REDIS_NOTICE, 999 "Successful partial resynchronization with master."); 1000 sdsfree(reply); 1001 replicationResurrectCachedMaster(fd); 1002 return PSYNC_CONTINUE; 1003 } 1004 1005 /* If we reach this point we receied either an error since the master does 1006 * not understand PSYNC, or an unexpected reply from the master. 1007 * Reply with PSYNC_NOT_SUPPORTED in both cases. */ 1008 1009 if (strncmp(reply,"-ERR",4)) { 1010 /* If it's not an error, log the unexpected event. */ 1011 redisLog(REDIS_WARNING, 1012 "Unexpected reply to PSYNC from master: %s", reply); 1013 } else { 1014 redisLog(REDIS_NOTICE, 1015 "Master does not support PSYNC or is in " 1016 "error state (reply: %s)", reply); 1017 } 1018 sdsfree(reply); 1019 replicationDiscardCachedMaster(); 1020 return PSYNC_NOT_SUPPORTED; 1021 } 1022 1023 void syncWithMaster(aeEventLoop *el, int fd, void *privdata, int mask) { 1024 char tmpfile[256], *err; 1025 int dfd, maxtries = 5; 1026 int sockerr = 0, psync_result; 1027 socklen_t errlen = sizeof(sockerr); 1028 REDIS_NOTUSED(el); 1029 REDIS_NOTUSED(privdata); 1030 REDIS_NOTUSED(mask); 1031 1032 /* If this event fired after the user turned the instance into a master 1033 * with SLAVEOF NO ONE we must just return ASAP. */ 1034 if (server.repl_state == REDIS_REPL_NONE) { 1035 close(fd); 1036 return; 1037 } 1038 1039 /* Check for errors in the socket. */ 1040 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &sockerr, &errlen) == -1) 1041 sockerr = errno; 1042 if (sockerr) { 1043 aeDeleteFileEvent(server.el,fd,AE_READABLE|AE_WRITABLE); 1044 redisLog(REDIS_WARNING,"Error condition on socket for SYNC: %s", 1045 strerror(sockerr)); 1046 goto error; 1047 } 1048 1049 /* If we were connecting, it's time to send a non blocking PING, we want to 1050 * make sure the master is able to reply before going into the actual 1051 * replication process where we have long timeouts in the order of 1052 * seconds (in the meantime the slave would block). */ 1053 if (server.repl_state == REDIS_REPL_CONNECTING) { 1054 redisLog(REDIS_NOTICE,"Non blocking connect for SYNC fired the event."); 1055 /* Delete the writable event so that the readable event remains 1056 * registered and we can wait for the PONG reply. */ 1057 aeDeleteFileEvent(server.el,fd,AE_WRITABLE); 1058 server.repl_state = REDIS_REPL_RECEIVE_PONG; 1059 /* Send the PING, don't check for errors at all, we have the timeout 1060 * that will take care about this. */ 1061 syncWrite(fd,"PING\r\n",6,100); 1062 return; 1063 } 1064 1065 /* Receive the PONG command. */ 1066 if (server.repl_state == REDIS_REPL_RECEIVE_PONG) { 1067 char buf[1024]; 1068 1069 /* Delete the readable event, we no longer need it now that there is 1070 * the PING reply to read. */ 1071 aeDeleteFileEvent(server.el,fd,AE_READABLE); 1072 1073 /* Read the reply with explicit timeout. */ 1074 buf[0] = '\0'; 1075 if (syncReadLine(fd,buf,sizeof(buf), 1076 server.repl_syncio_timeout*1000) == -1) 1077 { 1078 redisLog(REDIS_WARNING, 1079 "I/O error reading PING reply from master: %s", 1080 strerror(errno)); 1081 goto error; 1082 } 1083 1084 /* We accept only two replies as valid, a positive +PONG reply 1085 * (we just check for "+") or an authentication error. 1086 * Note that older versions of Redis replied with "operation not 1087 * permitted" instead of using a proper error code, so we test 1088 * both. */ 1089 if (buf[0] != '+' && 1090 strncmp(buf,"-NOAUTH",7) != 0 && 1091 strncmp(buf,"-ERR operation not permitted",28) != 0) 1092 { 1093 redisLog(REDIS_WARNING,"Error reply to PING from master: '%s'",buf); 1094 goto error; 1095 } else { 1096 redisLog(REDIS_NOTICE, 1097 "Master replied to PING, replication can continue..."); 1098 } 1099 } 1100 1101 /* AUTH with the master if required. */ 1102 if(server.masterauth) { 1103 err = sendSynchronousCommand(fd,"AUTH",server.masterauth,NULL); 1104 if (err[0] == '-') { 1105 redisLog(REDIS_WARNING,"Unable to AUTH to MASTER: %s",err); 1106 sdsfree(err); 1107 goto error; 1108 } 1109 sdsfree(err); 1110 } 1111 1112 /* Set the slave port, so that Master's INFO command can list the 1113 * slave listening port correctly. */ 1114 { 1115 sds port = sdsfromlonglong(server.port); 1116 err = sendSynchronousCommand(fd,"REPLCONF","listening-port",port, 1117 NULL); 1118 sdsfree(port); 1119 /* Ignore the error if any, not all the Redis versions support 1120 * REPLCONF listening-port. */ 1121 if (err[0] == '-') { 1122 redisLog(REDIS_NOTICE,"(Non critical) Master does not understand REPLCONF listening-port: %s", err); 1123 } 1124 sdsfree(err); 1125 } 1126 1127 /* Try a partial resynchonization. If we don't have a cached master 1128 * slaveTryPartialResynchronization() will at least try to use PSYNC 1129 * to start a full resynchronization so that we get the master run id 1130 * and the global offset, to try a partial resync at the next 1131 * reconnection attempt. */ 1132 psync_result = slaveTryPartialResynchronization(fd); 1133 if (psync_result == PSYNC_CONTINUE) { 1134 redisLog(REDIS_NOTICE, "MASTER <-> SLAVE sync: Master accepted a Partial Resynchronization."); 1135 return; 1136 } 1137 1138 /* Fall back to SYNC if needed. Otherwise psync_result == PSYNC_FULLRESYNC 1139 * and the server.repl_master_runid and repl_master_initial_offset are 1140 * already populated. */ 1141 if (psync_result == PSYNC_NOT_SUPPORTED) { 1142 redisLog(REDIS_NOTICE,"Retrying with SYNC..."); 1143 if (syncWrite(fd,"SYNC\r\n",6,server.repl_syncio_timeout*1000) == -1) { 1144 redisLog(REDIS_WARNING,"I/O error writing to MASTER: %s", 1145 strerror(errno)); 1146 goto error; 1147 } 1148 } 1149 1150 /* Prepare a suitable temp file for bulk transfer */ 1151 while(maxtries--) { 1152 snprintf(tmpfile,256, 1153 "temp-%d.%ld.rdb",(int)server.unixtime,(long int)getpid()); 1154 dfd = open(tmpfile,O_CREAT|O_WRONLY|O_EXCL,0644); 1155 if (dfd != -1) break; 1156 sleep(1); 1157 } 1158 if (dfd == -1) { 1159 redisLog(REDIS_WARNING,"Opening the temp file needed for MASTER <-> SLAVE synchronization: %s",strerror(errno)); 1160 goto error; 1161 } 1162 1163 /* Setup the non blocking download of the bulk file. */ 1164 if (aeCreateFileEvent(server.el,fd, AE_READABLE,readSyncBulkPayload,NULL) 1165 == AE_ERR) 1166 { 1167 redisLog(REDIS_WARNING, 1168 "Can't create readable event for SYNC: %s (fd=%d)", 1169 strerror(errno),fd); 1170 goto error; 1171 } 1172 1173 server.repl_state = REDIS_REPL_TRANSFER; 1174 server.repl_transfer_size = -1; 1175 server.repl_transfer_read = 0; 1176 server.repl_transfer_last_fsync_off = 0; 1177 server.repl_transfer_fd = dfd; 1178 server.repl_transfer_lastio = server.unixtime; 1179 server.repl_transfer_tmpfile = zstrdup(tmpfile); 1180 return; 1181 1182 error: 1183 close(fd); 1184 server.repl_transfer_s = -1; 1185 server.repl_state = REDIS_REPL_CONNECT; 1186 return; 1187 } 1188 1189 int connectWithMaster(void) { 1190 int fd; 1191 1192 fd = anetTcpNonBlockConnect(NULL,server.masterhost,server.masterport); 1193 if (fd == -1) { 1194 redisLog(REDIS_WARNING,"Unable to connect to MASTER: %s", 1195 strerror(errno)); 1196 return REDIS_ERR; 1197 } 1198 1199 if (aeCreateFileEvent(server.el,fd,AE_READABLE|AE_WRITABLE,syncWithMaster,NULL) == 1200 AE_ERR) 1201 { 1202 close(fd); 1203 redisLog(REDIS_WARNING,"Can't create readable event for SYNC"); 1204 return REDIS_ERR; 1205 } 1206 1207 server.repl_transfer_lastio = server.unixtime; 1208 server.repl_transfer_s = fd; 1209 server.repl_state = REDIS_REPL_CONNECTING; 1210 return REDIS_OK; 1211 } 1212 1213 /* This function can be called when a non blocking connection is currently 1214 * in progress to undo it. */ 1215 void undoConnectWithMaster(void) { 1216 int fd = server.repl_transfer_s; 1217 1218 redisAssert(server.repl_state == REDIS_REPL_CONNECTING || 1219 server.repl_state == REDIS_REPL_RECEIVE_PONG); 1220 aeDeleteFileEvent(server.el,fd,AE_READABLE|AE_WRITABLE); 1221 close(fd); 1222 server.repl_transfer_s = -1; 1223 server.repl_state = REDIS_REPL_CONNECT; 1224 } 1225 1226 /* This function aborts a non blocking replication attempt if there is one 1227 * in progress, by canceling the non-blocking connect attempt or 1228 * the initial bulk transfer. 1229 * 1230 * If there was a replication handshake in progress 1 is returned and 1231 * the replication state (server.repl_state) set to REDIS_REPL_CONNECT. 1232 * 1233 * Otherwise zero is returned and no operation is perforemd at all. */ 1234 int cancelReplicationHandshake(void) { 1235 if (server.repl_state == REDIS_REPL_TRANSFER) { 1236 replicationAbortSyncTransfer(); 1237 } else if (server.repl_state == REDIS_REPL_CONNECTING || 1238 server.repl_state == REDIS_REPL_RECEIVE_PONG) 1239 { 1240 undoConnectWithMaster(); 1241 } else { 1242 return 0; 1243 } 1244 return 1; 1245 } 1246 1247 /* Set replication to the specified master address and port. */ 1248 void replicationSetMaster(char *ip, int port) { 1249 sdsfree(server.masterhost); 1250 server.masterhost = sdsnew(ip); 1251 server.masterport = port; 1252 if (server.master) freeClient(server.master); 1253 disconnectSlaves(); /* Force our slaves to resync with us as well. */ 1254 replicationDiscardCachedMaster(); /* Don't try a PSYNC. */ 1255 freeReplicationBacklog(); /* Don't allow our chained slaves to PSYNC. */ 1256 cancelReplicationHandshake(); 1257 server.repl_state = REDIS_REPL_CONNECT; 1258 } 1259 1260 /* Cancel replication, setting the instance as a master itself. */ 1261 void replicationUnsetMaster(void) { 1262 if (server.masterhost == NULL) return; /* Nothing to do. */ 1263 sdsfree(server.masterhost); 1264 server.masterhost = NULL; 1265 if (server.master) freeClient(server.master); 1266 replicationDiscardCachedMaster(); 1267 cancelReplicationHandshake(); 1268 server.repl_state = REDIS_REPL_NONE; 1269 } 1270 1271 void slaveofCommand(redisClient *c) { 1272 /* SLAVEOF is not allowed in cluster mode as replication is automatically 1273 * configured using the current address of the master node. */ 1274 if (server.cluster_enabled) { 1275 addReplyError(c,"SLAVEOF not allowed in cluster mode."); 1276 return; 1277 } 1278 1279 /* The special host/port combination "NO" "ONE" turns the instance 1280 * into a master. Otherwise the new master address is set. */ 1281 if (!strcasecmp(c->argv[1]->ptr,"no") && 1282 !strcasecmp(c->argv[2]->ptr,"one")) { 1283 if (server.masterhost) { 1284 replicationUnsetMaster(); 1285 redisLog(REDIS_NOTICE,"MASTER MODE enabled (user request)"); 1286 } 1287 } else { 1288 long port; 1289 1290 if ((getLongFromObjectOrReply(c, c->argv[2], &port, NULL) != REDIS_OK)) 1291 return; 1292 1293 /* Check if we are already attached to the specified slave */ 1294 if (server.masterhost && !strcasecmp(server.masterhost,c->argv[1]->ptr) 1295 && server.masterport == port) { 1296 redisLog(REDIS_NOTICE,"SLAVE OF would result into synchronization with the master we are already connected with. No operation performed."); 1297 addReplySds(c,sdsnew("+OK Already connected to specified master\r\n")); 1298 return; 1299 } 1300 /* There was no previous master or the user specified a different one, 1301 * we can continue. */ 1302 replicationSetMaster(c->argv[1]->ptr, port); 1303 redisLog(REDIS_NOTICE,"SLAVE OF %s:%d enabled (user request)", 1304 server.masterhost, server.masterport); 1305 } 1306 addReply(c,shared.ok); 1307 } 1308 1309 /* Send a REPLCONF ACK command to the master to inform it about the current 1310 * processed offset. If we are not connected with a master, the command has 1311 * no effects. */ 1312 void replicationSendAck(void) { 1313 redisClient *c = server.master; 1314 1315 if (c != NULL) { 1316 c->flags |= REDIS_MASTER_FORCE_REPLY; 1317 addReplyMultiBulkLen(c,3); 1318 addReplyBulkCString(c,"REPLCONF"); 1319 addReplyBulkCString(c,"ACK"); 1320 addReplyBulkLongLong(c,c->reploff); 1321 c->flags &= ~REDIS_MASTER_FORCE_REPLY; 1322 } 1323 } 1324 1325 /* ---------------------- MASTER CACHING FOR PSYNC -------------------------- */ 1326 1327 /* In order to implement partial synchronization we need to be able to cache 1328 * our master's client structure after a transient disconnection. 1329 * It is cached into server.cached_master and flushed away using the following 1330 * functions. */ 1331 1332 /* This function is called by freeClient() in order to cache the master 1333 * client structure instead of destryoing it. freeClient() will return 1334 * ASAP after this function returns, so every action needed to avoid problems 1335 * with a client that is really "suspended" has to be done by this function. 1336 * 1337 * The other functions that will deal with the cached master are: 1338 * 1339 * replicationDiscardCachedMaster() that will make sure to kill the client 1340 * as for some reason we don't want to use it in the future. 1341 * 1342 * replicationResurrectCachedMaster() that is used after a successful PSYNC 1343 * handshake in order to reactivate the cached master. 1344 */ 1345 void replicationCacheMaster(redisClient *c) { 1346 listNode *ln; 1347 1348 redisAssert(server.master != NULL && server.cached_master == NULL); 1349 redisLog(REDIS_NOTICE,"Caching the disconnected master state."); 1350 1351 /* Remove from the list of clients, we don't want this client to be 1352 * listed by CLIENT LIST or processed in any way by batch operations. */ 1353 ln = listSearchKey(server.clients,c); 1354 redisAssert(ln != NULL); 1355 listDelNode(server.clients,ln); 1356 1357 /* Save the master. Server.master will be set to null later by 1358 * replicationHandleMasterDisconnection(). */ 1359 server.cached_master = server.master; 1360 1361 /* Remove the event handlers and close the socket. We'll later reuse 1362 * the socket of the new connection with the master during PSYNC. */ 1363 aeDeleteFileEvent(server.el,c->fd,AE_READABLE); 1364 aeDeleteFileEvent(server.el,c->fd,AE_WRITABLE); 1365 close(c->fd); 1366 1367 /* Set fd to -1 so that we can safely call freeClient(c) later. */ 1368 c->fd = -1; 1369 1370 /* Caching the master happens instead of the actual freeClient() call, 1371 * so make sure to adjust the replication state. This function will 1372 * also set server.master to NULL. */ 1373 replicationHandleMasterDisconnection(); 1374 } 1375 1376 /* Free a cached master, called when there are no longer the conditions for 1377 * a partial resync on reconnection. */ 1378 void replicationDiscardCachedMaster(void) { 1379 if (server.cached_master == NULL) return; 1380 1381 redisLog(REDIS_NOTICE,"Discarding previously cached master state."); 1382 server.cached_master->flags &= ~REDIS_MASTER; 1383 freeClient(server.cached_master); 1384 server.cached_master = NULL; 1385 } 1386 1387 /* Turn the cached master into the current master, using the file descriptor 1388 * passed as argument as the socket for the new master. 1389 * 1390 * This funciton is called when successfully setup a partial resynchronization 1391 * so the stream of data that we'll receive will start from were this 1392 * master left. */ 1393 void replicationResurrectCachedMaster(int newfd) { 1394 server.master = server.cached_master; 1395 server.cached_master = NULL; 1396 server.master->fd = newfd; 1397 server.master->flags &= ~(REDIS_CLOSE_AFTER_REPLY|REDIS_CLOSE_ASAP); 1398 server.master->authenticated = 1; 1399 server.master->lastinteraction = server.unixtime; 1400 server.repl_state = REDIS_REPL_CONNECTED; 1401 1402 /* Re-add to the list of clients. */ 1403 listAddNodeTail(server.clients,server.master); 1404 if (aeCreateFileEvent(server.el, newfd, AE_READABLE, 1405 readQueryFromClient, server.master)) { 1406 redisLog(REDIS_WARNING,"Error resurrecting the cached master, impossible to add the readable handler: %s", strerror(errno)); 1407 freeClientAsync(server.master); /* Close ASAP. */ 1408 } 1409 } 1410 1411 /* ------------------------- MIN-SLAVES-TO-WRITE --------------------------- */ 1412 1413 /* This function counts the number of slaves with lag <= min-slaves-max-lag. 1414 * If the option is active, the server will prevent writes if there are not 1415 * enough connected slaves with the specified lag (or less). */ 1416 void refreshGoodSlavesCount(void) { 1417 listIter li; 1418 listNode *ln; 1419 int good = 0; 1420 1421 if (!server.repl_min_slaves_to_write || 1422 !server.repl_min_slaves_max_lag) return; 1423 1424 listRewind(server.slaves,&li); 1425 while((ln = listNext(&li))) { 1426 redisClient *slave = ln->value; 1427 time_t lag = server.unixtime - slave->repl_ack_time; 1428 1429 if (slave->replstate == REDIS_REPL_ONLINE && 1430 lag <= server.repl_min_slaves_max_lag) good++; 1431 } 1432 server.repl_good_slaves_count = good; 1433 } 1434 1435 /* --------------------------- REPLICATION CRON ---------------------------- */ 1436 1437 /* Replication cron funciton, called 1 time per second. */ 1438 void replicationCron(void) { 1439 /* Non blocking connection timeout? */ 1440 if (server.masterhost && 1441 (server.repl_state == REDIS_REPL_CONNECTING || 1442 server.repl_state == REDIS_REPL_RECEIVE_PONG) && 1443 (time(NULL)-server.repl_transfer_lastio) > server.repl_timeout) 1444 { 1445 redisLog(REDIS_WARNING,"Timeout connecting to the MASTER..."); 1446 undoConnectWithMaster(); 1447 } 1448 1449 /* Bulk transfer I/O timeout? */ 1450 if (server.masterhost && server.repl_state == REDIS_REPL_TRANSFER && 1451 (time(NULL)-server.repl_transfer_lastio) > server.repl_timeout) 1452 { 1453 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."); 1454 replicationAbortSyncTransfer(); 1455 } 1456 1457 /* Timed out master when we are an already connected slave? */ 1458 if (server.masterhost && server.repl_state == REDIS_REPL_CONNECTED && 1459 (time(NULL)-server.master->lastinteraction) > server.repl_timeout) 1460 { 1461 redisLog(REDIS_WARNING,"MASTER time out: no data nor PING received..."); 1462 freeClient(server.master); 1463 } 1464 1465 /* Check if we should connect to a MASTER */ 1466 if (server.repl_state == REDIS_REPL_CONNECT) { 1467 redisLog(REDIS_NOTICE,"Connecting to MASTER..."); 1468 if (connectWithMaster() == REDIS_OK) { 1469 redisLog(REDIS_NOTICE,"MASTER <-> SLAVE sync started"); 1470 } 1471 } 1472 1473 /* Send ACK to master from time to time. */ 1474 if (server.masterhost && server.master) 1475 replicationSendAck(); 1476 1477 /* If we have attached slaves, PING them from time to time. 1478 * So slaves can implement an explicit timeout to masters, and will 1479 * be able to detect a link disconnection even if the TCP connection 1480 * will not actually go down. */ 1481 if (!(server.cronloops % (server.repl_ping_slave_period * server.hz))) { 1482 listIter li; 1483 listNode *ln; 1484 robj *ping_argv[1]; 1485 1486 /* First, send PING */ 1487 ping_argv[0] = createStringObject("PING",4); 1488 replicationFeedSlaves(server.slaves, server.slaveseldb, ping_argv, 1); 1489 decrRefCount(ping_argv[0]); 1490 1491 /* Second, send a newline to all the slaves in pre-synchronization 1492 * stage, that is, slaves waiting for the master to create the RDB file. 1493 * The newline will be ignored by the slave but will refresh the 1494 * last-io timer preventing a timeout. */ 1495 listRewind(server.slaves,&li); 1496 while((ln = listNext(&li))) { 1497 redisClient *slave = ln->value; 1498 1499 if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_START || 1500 slave->replstate == REDIS_REPL_WAIT_BGSAVE_END) { 1501 if (write(slave->fd, "\n", 1) == -1) { 1502 /* Don't worry, it's just a ping. */ 1503 } 1504 } 1505 } 1506 } 1507 1508 /* Disconnect timedout slaves. */ 1509 if (listLength(server.slaves)) { 1510 listIter li; 1511 listNode *ln; 1512 1513 listRewind(server.slaves,&li); 1514 while((ln = listNext(&li))) { 1515 redisClient *slave = ln->value; 1516 1517 if (slave->replstate != REDIS_REPL_ONLINE) continue; 1518 if ((server.unixtime - slave->repl_ack_time) > server.repl_timeout) 1519 { 1520 char ip[32]; 1521 int port; 1522 1523 if (anetPeerToString(slave->fd,ip,&port) != -1) { 1524 redisLog(REDIS_WARNING, 1525 "Disconnecting timedout slave: %s:%d", 1526 ip, slave->slave_listening_port); 1527 } 1528 freeClient(slave); 1529 } 1530 } 1531 } 1532 1533 /* If we have no attached slaves and there is a replication backlog 1534 * using memory, free it after some (configured) time. */ 1535 if (listLength(server.slaves) == 0 && server.repl_backlog_time_limit && 1536 server.repl_backlog) 1537 { 1538 time_t idle = server.unixtime - server.repl_no_slaves_since; 1539 1540 if (idle > server.repl_backlog_time_limit) { 1541 freeReplicationBacklog(); 1542 redisLog(REDIS_NOTICE, 1543 "Replication backlog freed after %d seconds " 1544 "without connected slaves.", 1545 (int) server.repl_backlog_time_limit); 1546 } 1547 } 1548 1549 /* Refresh the number of slaves with lag <= min-slaves-max-lag. */ 1550 refreshGoodSlavesCount(); 1551 } 1552