1 /* Redis Cluster 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 #include "redis.h" 32 #include "endianconv.h" 33 34 #include <arpa/inet.h> 35 #include <fcntl.h> 36 #include <unistd.h> 37 #include <sys/socket.h> 38 39 void clusterAcceptHandler(aeEventLoop *el, int fd, void *privdata, int mask); 40 void clusterReadHandler(aeEventLoop *el, int fd, void *privdata, int mask); 41 void clusterSendPing(clusterLink *link, int type); 42 void clusterSendFail(char *nodename); 43 void clusterSendFailoverAuthIfNeeded(clusterNode *sender); 44 void clusterUpdateState(void); 45 int clusterNodeGetSlotBit(clusterNode *n, int slot); 46 sds clusterGenNodesDescription(void); 47 clusterNode *clusterLookupNode(char *name); 48 int clusterNodeAddSlave(clusterNode *master, clusterNode *slave); 49 int clusterAddSlot(clusterNode *n, int slot); 50 int clusterDelSlot(int slot); 51 int clusterDelNodeSlots(clusterNode *node); 52 int clusterNodeSetSlotBit(clusterNode *n, int slot); 53 void clusterSetMaster(clusterNode *n); 54 int bitmapTestBit(unsigned char *bitmap, int pos); 55 56 /* ----------------------------------------------------------------------------- 57 * Initialization 58 * -------------------------------------------------------------------------- */ 59 60 int clusterLoadConfig(char *filename) { 61 FILE *fp = fopen(filename,"r"); 62 char *line; 63 int maxline, j; 64 65 if (fp == NULL) return REDIS_ERR; 66 67 /* Parse the file. Note that single liens of the cluster config file can 68 * be really long as they include all the hash slots of the node. 69 * This means in the worst possible case, half of the Redis slots will be 70 * present in a single line, possibly in importing or migrating state, so 71 * together with the node ID of the sender/receiver. 72 * 73 * To simplify we allocate 1024+REDIS_CLUSTER_SLOTS*128 bytes per line. */ 74 maxline = 1024+REDIS_CLUSTER_SLOTS*128; 75 line = zmalloc(maxline); 76 while(fgets(line,maxline,fp) != NULL) { 77 int argc; 78 sds *argv = sdssplitargs(line,&argc); 79 if (argv == NULL) goto fmterr; 80 81 clusterNode *n, *master; 82 char *p, *s; 83 84 /* Create this node if it does not exist */ 85 n = clusterLookupNode(argv[0]); 86 if (!n) { 87 n = createClusterNode(argv[0],0); 88 clusterAddNode(n); 89 } 90 /* Address and port */ 91 if ((p = strchr(argv[1],':')) == NULL) goto fmterr; 92 *p = '\0'; 93 memcpy(n->ip,argv[1],strlen(argv[1])+1); 94 n->port = atoi(p+1); 95 96 /* Parse flags */ 97 p = s = argv[2]; 98 while(p) { 99 p = strchr(s,','); 100 if (p) *p = '\0'; 101 if (!strcasecmp(s,"myself")) { 102 redisAssert(server.cluster->myself == NULL); 103 server.cluster->myself = n; 104 n->flags |= REDIS_NODE_MYSELF; 105 } else if (!strcasecmp(s,"master")) { 106 n->flags |= REDIS_NODE_MASTER; 107 } else if (!strcasecmp(s,"slave")) { 108 n->flags |= REDIS_NODE_SLAVE; 109 } else if (!strcasecmp(s,"fail?")) { 110 n->flags |= REDIS_NODE_PFAIL; 111 } else if (!strcasecmp(s,"fail")) { 112 n->flags |= REDIS_NODE_FAIL; 113 n->fail_time = time(NULL); 114 } else if (!strcasecmp(s,"handshake")) { 115 n->flags |= REDIS_NODE_HANDSHAKE; 116 } else if (!strcasecmp(s,"noaddr")) { 117 n->flags |= REDIS_NODE_NOADDR; 118 } else if (!strcasecmp(s,"promoted")) { 119 n->flags |= REDIS_NODE_PROMOTED; 120 } else if (!strcasecmp(s,"noflags")) { 121 /* nothing to do */ 122 } else { 123 redisPanic("Unknown flag in redis cluster config file"); 124 } 125 if (p) s = p+1; 126 } 127 128 /* Get master if any. Set the master and populate master's 129 * slave list. */ 130 if (argv[3][0] != '-') { 131 master = clusterLookupNode(argv[3]); 132 if (!master) { 133 master = createClusterNode(argv[3],0); 134 clusterAddNode(master); 135 } 136 n->slaveof = master; 137 clusterNodeAddSlave(master,n); 138 } 139 140 /* Set ping sent / pong received timestamps */ 141 if (atoi(argv[4])) n->ping_sent = time(NULL); 142 if (atoi(argv[5])) n->pong_received = time(NULL); 143 144 /* Populate hash slots served by this instance. */ 145 for (j = 7; j < argc; j++) { 146 int start, stop; 147 148 if (argv[j][0] == '[') { 149 /* Here we handle migrating / importing slots */ 150 int slot; 151 char direction; 152 clusterNode *cn; 153 154 p = strchr(argv[j],'-'); 155 redisAssert(p != NULL); 156 *p = '\0'; 157 direction = p[1]; /* Either '>' or '<' */ 158 slot = atoi(argv[j]+1); 159 p += 3; 160 cn = clusterLookupNode(p); 161 if (!cn) { 162 cn = createClusterNode(p,0); 163 clusterAddNode(cn); 164 } 165 if (direction == '>') { 166 server.cluster->migrating_slots_to[slot] = cn; 167 } else { 168 server.cluster->importing_slots_from[slot] = cn; 169 } 170 continue; 171 } else if ((p = strchr(argv[j],'-')) != NULL) { 172 *p = '\0'; 173 start = atoi(argv[j]); 174 stop = atoi(p+1); 175 } else { 176 start = stop = atoi(argv[j]); 177 } 178 while(start <= stop) clusterAddSlot(n, start++); 179 } 180 181 sdsfreesplitres(argv,argc); 182 } 183 zfree(line); 184 fclose(fp); 185 186 /* Config sanity check */ 187 redisAssert(server.cluster->myself != NULL); 188 redisLog(REDIS_NOTICE,"Node configuration loaded, I'm %.40s", 189 server.cluster->myself->name); 190 clusterUpdateState(); 191 return REDIS_OK; 192 193 fmterr: 194 redisLog(REDIS_WARNING,"Unrecoverable error: corrupted cluster config file."); 195 fclose(fp); 196 exit(1); 197 } 198 199 /* Cluster node configuration is exactly the same as CLUSTER NODES output. 200 * 201 * This function writes the node config and returns 0, on error -1 202 * is returned. */ 203 int clusterSaveConfig(void) { 204 sds ci = clusterGenNodesDescription(); 205 int fd; 206 207 if ((fd = open(server.cluster_configfile,O_WRONLY|O_CREAT|O_TRUNC,0644)) 208 == -1) goto err; 209 if (write(fd,ci,sdslen(ci)) != (ssize_t)sdslen(ci)) goto err; 210 close(fd); 211 sdsfree(ci); 212 return 0; 213 214 err: 215 sdsfree(ci); 216 return -1; 217 } 218 219 void clusterSaveConfigOrDie(void) { 220 if (clusterSaveConfig() == -1) { 221 redisLog(REDIS_WARNING,"Fatal: can't update cluster config file."); 222 exit(1); 223 } 224 } 225 226 void clusterInit(void) { 227 int saveconf = 0; 228 229 server.cluster = zmalloc(sizeof(clusterState)); 230 server.cluster->myself = NULL; 231 server.cluster->state = REDIS_CLUSTER_FAIL; 232 server.cluster->size = 1; 233 server.cluster->nodes = dictCreate(&clusterNodesDictType,NULL); 234 server.cluster->failover_auth_time = 0; 235 server.cluster->failover_auth_count = 0; 236 memset(server.cluster->migrating_slots_to,0, 237 sizeof(server.cluster->migrating_slots_to)); 238 memset(server.cluster->importing_slots_from,0, 239 sizeof(server.cluster->importing_slots_from)); 240 memset(server.cluster->slots,0, 241 sizeof(server.cluster->slots)); 242 if (clusterLoadConfig(server.cluster_configfile) == REDIS_ERR) { 243 /* No configuration found. We will just use the random name provided 244 * by the createClusterNode() function. */ 245 server.cluster->myself = 246 createClusterNode(NULL,REDIS_NODE_MYSELF|REDIS_NODE_MASTER); 247 redisLog(REDIS_NOTICE,"No cluster configuration found, I'm %.40s", 248 server.cluster->myself->name); 249 clusterAddNode(server.cluster->myself); 250 saveconf = 1; 251 } 252 if (saveconf) clusterSaveConfigOrDie(); 253 /* We need a listening TCP port for our cluster messaging needs */ 254 server.cfd = anetTcpServer(server.neterr, 255 server.port+REDIS_CLUSTER_PORT_INCR, server.bindaddr); 256 if (server.cfd == -1) { 257 redisLog(REDIS_WARNING, "Opening cluster TCP port: %s", server.neterr); 258 exit(1); 259 } 260 if (aeCreateFileEvent(server.el, server.cfd, AE_READABLE, 261 clusterAcceptHandler, NULL) == AE_ERR) redisPanic("Unrecoverable error creating Redis Cluster file event."); 262 server.cluster->slots_to_keys = zslCreate(); 263 } 264 265 /* ----------------------------------------------------------------------------- 266 * CLUSTER communication link 267 * -------------------------------------------------------------------------- */ 268 269 clusterLink *createClusterLink(clusterNode *node) { 270 clusterLink *link = zmalloc(sizeof(*link)); 271 link->sndbuf = sdsempty(); 272 link->rcvbuf = sdsempty(); 273 link->node = node; 274 link->fd = -1; 275 return link; 276 } 277 278 /* Free a cluster link, but does not free the associated node of course. 279 * Just this function will make sure that the original node associated 280 * with this link will have the 'link' field set to NULL. */ 281 void freeClusterLink(clusterLink *link) { 282 if (link->fd != -1) { 283 aeDeleteFileEvent(server.el, link->fd, AE_WRITABLE); 284 aeDeleteFileEvent(server.el, link->fd, AE_READABLE); 285 } 286 sdsfree(link->sndbuf); 287 sdsfree(link->rcvbuf); 288 if (link->node) 289 link->node->link = NULL; 290 close(link->fd); 291 zfree(link); 292 } 293 294 void clusterAcceptHandler(aeEventLoop *el, int fd, void *privdata, int mask) { 295 int cport, cfd; 296 char cip[128]; 297 clusterLink *link; 298 REDIS_NOTUSED(el); 299 REDIS_NOTUSED(mask); 300 REDIS_NOTUSED(privdata); 301 302 cfd = anetTcpAccept(server.neterr, fd, cip, &cport); 303 if (cfd == AE_ERR) { 304 redisLog(REDIS_VERBOSE,"Accepting cluster node: %s", server.neterr); 305 return; 306 } 307 redisLog(REDIS_VERBOSE,"Accepted cluster node %s:%d", cip, cport); 308 /* We need to create a temporary node in order to read the incoming 309 * packet in a valid contest. This node will be released once we 310 * read the packet and reply. */ 311 link = createClusterLink(NULL); 312 link->fd = cfd; 313 aeCreateFileEvent(server.el,cfd,AE_READABLE,clusterReadHandler,link); 314 } 315 316 /* ----------------------------------------------------------------------------- 317 * Key space handling 318 * -------------------------------------------------------------------------- */ 319 320 /* We have 16384 hash slots. The hash slot of a given key is obtained 321 * as the least significant 14 bits of the crc16 of the key. */ 322 unsigned int keyHashSlot(char *key, int keylen) { 323 return crc16(key,keylen) & 0x3FFF; 324 } 325 326 /* ----------------------------------------------------------------------------- 327 * CLUSTER node API 328 * -------------------------------------------------------------------------- */ 329 330 /* Create a new cluster node, with the specified flags. 331 * If "nodename" is NULL this is considered a first handshake and a random 332 * node name is assigned to this node (it will be fixed later when we'll 333 * receive the first pong). 334 * 335 * The node is created and returned to the user, but it is not automatically 336 * added to the nodes hash table. */ 337 clusterNode *createClusterNode(char *nodename, int flags) { 338 clusterNode *node = zmalloc(sizeof(*node)); 339 340 if (nodename) 341 memcpy(node->name, nodename, REDIS_CLUSTER_NAMELEN); 342 else 343 getRandomHexChars(node->name, REDIS_CLUSTER_NAMELEN); 344 node->flags = flags; 345 memset(node->slots,0,sizeof(node->slots)); 346 node->numslots = 0; 347 node->numslaves = 0; 348 node->slaves = NULL; 349 node->slaveof = NULL; 350 node->ping_sent = node->pong_received = 0; 351 node->fail_time = 0; 352 node->link = NULL; 353 memset(node->ip,0,sizeof(node->ip)); 354 node->port = 0; 355 node->fail_reports = listCreate(); 356 listSetFreeMethod(node->fail_reports,zfree); 357 return node; 358 } 359 360 /* This function is called every time we get a failure report from a node. 361 * The side effect is to populate the fail_reports list (or to update 362 * the timestamp of an existing report). 363 * 364 * 'failing' is the node that is in failure state according to the 365 * 'sender' node. 366 * 367 * The function returns 0 if it just updates a timestamp of an existing 368 * failure report from the same sender. 1 is returned if a new failure 369 * report is created. */ 370 int clusterNodeAddFailureReport(clusterNode *failing, clusterNode *sender) { 371 list *l = failing->fail_reports; 372 listNode *ln; 373 listIter li; 374 clusterNodeFailReport *fr; 375 376 /* If a failure report from the same sender already exists, just update 377 * the timestamp. */ 378 listRewind(l,&li); 379 while ((ln = listNext(&li)) != NULL) { 380 fr = ln->value; 381 if (fr->node == sender) { 382 fr->time = time(NULL); 383 return 0; 384 } 385 } 386 387 /* Otherwise create a new report. */ 388 fr = zmalloc(sizeof(*fr)); 389 fr->node = sender; 390 fr->time = time(NULL); 391 listAddNodeTail(l,fr); 392 return 1; 393 } 394 395 /* Remove failure reports that are too old, where too old means reasonably 396 * older than the global node timeout. Note that anyway for a node to be 397 * flagged as FAIL we need to have a local PFAIL state that is at least 398 * older than the global node timeout, so we don't just trust the number 399 * of failure reports from other nodes. */ 400 void clusterNodeCleanupFailureReports(clusterNode *node) { 401 list *l = node->fail_reports; 402 listNode *ln; 403 listIter li; 404 clusterNodeFailReport *fr; 405 time_t maxtime = server.cluster_node_timeout * 406 REDIS_CLUSTER_FAIL_REPORT_VALIDITY_MULT; 407 time_t now = time(NULL); 408 409 listRewind(l,&li); 410 while ((ln = listNext(&li)) != NULL) { 411 fr = ln->value; 412 if (now - fr->time > maxtime) listDelNode(l,ln); 413 } 414 } 415 416 /* Remove the failing report for 'node' if it was previously considered 417 * failing by 'sender'. This function is called when a node informs us via 418 * gossip that a node is OK from its point of view (no FAIL or PFAIL flags). 419 * 420 * Note that this function is called relatively often as it gets called even 421 * when there are no nodes failing, and is O(N), however when the cluster is 422 * fine the failure reports list is empty so the function runs in constant 423 * time. 424 * 425 * The function returns 1 if the failure report was found and removed. 426 * Otherwise 0 is returned. */ 427 int clusterNodeDelFailureReport(clusterNode *node, clusterNode *sender) { 428 list *l = node->fail_reports; 429 listNode *ln; 430 listIter li; 431 clusterNodeFailReport *fr; 432 433 /* Search for a failure report from this sender. */ 434 listRewind(l,&li); 435 while ((ln = listNext(&li)) != NULL) { 436 fr = ln->value; 437 if (fr->node == sender) break; 438 } 439 if (!ln) return 0; /* No failure report from this sender. */ 440 441 /* Remove the failure report. */ 442 listDelNode(l,ln); 443 clusterNodeCleanupFailureReports(node); 444 return 1; 445 } 446 447 /* Return the number of external nodes that believe 'node' is failing, 448 * not including this node, that may have a PFAIL or FAIL state for this 449 * node as well. */ 450 int clusterNodeFailureReportsCount(clusterNode *node) { 451 clusterNodeCleanupFailureReports(node); 452 return listLength(node->fail_reports); 453 } 454 455 int clusterNodeRemoveSlave(clusterNode *master, clusterNode *slave) { 456 int j; 457 458 for (j = 0; j < master->numslaves; j++) { 459 if (master->slaves[j] == slave) { 460 memmove(master->slaves+j,master->slaves+(j+1), 461 (master->numslaves-1)-j); 462 master->numslaves--; 463 return REDIS_OK; 464 } 465 } 466 return REDIS_ERR; 467 } 468 469 int clusterNodeAddSlave(clusterNode *master, clusterNode *slave) { 470 int j; 471 472 /* If it's already a slave, don't add it again. */ 473 for (j = 0; j < master->numslaves; j++) 474 if (master->slaves[j] == slave) return REDIS_ERR; 475 master->slaves = zrealloc(master->slaves, 476 sizeof(clusterNode*)*(master->numslaves+1)); 477 master->slaves[master->numslaves] = slave; 478 master->numslaves++; 479 return REDIS_OK; 480 } 481 482 void clusterNodeResetSlaves(clusterNode *n) { 483 zfree(n->slaves); 484 n->numslaves = 0; 485 } 486 487 void freeClusterNode(clusterNode *n) { 488 sds nodename; 489 490 nodename = sdsnewlen(n->name, REDIS_CLUSTER_NAMELEN); 491 redisAssert(dictDelete(server.cluster->nodes,nodename) == DICT_OK); 492 sdsfree(nodename); 493 if (n->slaveof) clusterNodeRemoveSlave(n->slaveof, n); 494 if (n->link) freeClusterLink(n->link); 495 listRelease(n->fail_reports); 496 zfree(n); 497 } 498 499 /* Add a node to the nodes hash table */ 500 int clusterAddNode(clusterNode *node) { 501 int retval; 502 503 retval = dictAdd(server.cluster->nodes, 504 sdsnewlen(node->name,REDIS_CLUSTER_NAMELEN), node); 505 return (retval == DICT_OK) ? REDIS_OK : REDIS_ERR; 506 } 507 508 /* Remove a node from the cluster: 509 * 1) Mark all the nodes handled by it as unassigned. 510 * 2) Remove all the failure reports sent by this node. 511 * 3) Free the node, that will in turn remove it from the hash table 512 * and from the list of slaves of its master, if it is a slave node. 513 */ 514 void clusterDelNode(clusterNode *delnode) { 515 int j; 516 dictIterator *di; 517 dictEntry *de; 518 519 /* 1) Mark slots as unassigned. */ 520 for (j = 0; j < REDIS_CLUSTER_SLOTS; j++) { 521 if (server.cluster->importing_slots_from[j] == delnode) 522 server.cluster->importing_slots_from[j] = NULL; 523 if (server.cluster->migrating_slots_to[j] == delnode) 524 server.cluster->migrating_slots_to[j] = NULL; 525 if (server.cluster->slots[j] == delnode) 526 clusterDelSlot(j); 527 } 528 529 /* 2) Remove failure reports. */ 530 di = dictGetIterator(server.cluster->nodes); 531 while((de = dictNext(di)) != NULL) { 532 clusterNode *node = dictGetVal(de); 533 534 if (node == delnode) continue; 535 clusterNodeDelFailureReport(node,delnode); 536 } 537 dictReleaseIterator(di); 538 539 /* 3) Free the node, unlinking it from the cluster. */ 540 freeClusterNode(delnode); 541 } 542 543 /* Node lookup by name */ 544 clusterNode *clusterLookupNode(char *name) { 545 sds s = sdsnewlen(name, REDIS_CLUSTER_NAMELEN); 546 struct dictEntry *de; 547 548 de = dictFind(server.cluster->nodes,s); 549 sdsfree(s); 550 if (de == NULL) return NULL; 551 return dictGetVal(de); 552 } 553 554 /* This is only used after the handshake. When we connect a given IP/PORT 555 * as a result of CLUSTER MEET we don't have the node name yet, so we 556 * pick a random one, and will fix it when we receive the PONG request using 557 * this function. */ 558 void clusterRenameNode(clusterNode *node, char *newname) { 559 int retval; 560 sds s = sdsnewlen(node->name, REDIS_CLUSTER_NAMELEN); 561 562 redisLog(REDIS_DEBUG,"Renaming node %.40s into %.40s", 563 node->name, newname); 564 retval = dictDelete(server.cluster->nodes, s); 565 sdsfree(s); 566 redisAssert(retval == DICT_OK); 567 memcpy(node->name, newname, REDIS_CLUSTER_NAMELEN); 568 clusterAddNode(node); 569 } 570 571 /* ----------------------------------------------------------------------------- 572 * CLUSTER messages exchange - PING/PONG and gossip 573 * -------------------------------------------------------------------------- */ 574 575 /* This function checks if a given node should be marked as FAIL. 576 * It happens if the following conditions are met: 577 * 578 * 1) We are a master node. Only master nodes can mark a node as failing. 579 * 2) We received enough failure reports from other nodes via gossip. 580 * Enough means that the majority of the masters believe the node is 581 * down. 582 * 3) We believe this node is in PFAIL state. 583 * 584 * If a failure is detected we also inform the whole cluster about this 585 * event trying to force every other node to set the FAIL flag for the node. 586 */ 587 void markNodeAsFailingIfNeeded(clusterNode *node) { 588 int failures; 589 int needed_quorum = (server.cluster->size / 2) + 1; 590 591 if (!(server.cluster->myself->flags & REDIS_NODE_MASTER)) return; 592 if (!(node->flags & REDIS_NODE_PFAIL)) return; /* We can reach it. */ 593 if (node->flags & REDIS_NODE_FAIL) return; /* Already FAILing. */ 594 595 failures = 1 + clusterNodeFailureReportsCount(node); /* +1 is for myself. */ 596 if (failures < needed_quorum) return; 597 598 redisLog(REDIS_NOTICE, 599 "Marking node %.40s as failing (quorum reached).", node->name); 600 601 /* Mark the node as failing. */ 602 node->flags &= ~REDIS_NODE_PFAIL; 603 node->flags |= REDIS_NODE_FAIL; 604 node->fail_time = time(NULL); 605 606 /* Broadcast the failing node name to everybody */ 607 clusterSendFail(node->name); 608 clusterUpdateState(); 609 clusterSaveConfigOrDie(); 610 } 611 612 /* This function is called only if a node is marked as FAIL, but we are able 613 * to reach it again. It checks if there are the conditions to undo the FAIL 614 * state. */ 615 void clearNodeFailureIfNeeded(clusterNode *node) { 616 int changes = 0; 617 time_t now = time(NULL); 618 619 redisAssert(node->flags & REDIS_NODE_FAIL); 620 621 /* For slaves we always clear the FAIL flag if we can contact the 622 * node again. */ 623 if (node->flags & REDIS_NODE_SLAVE) { 624 redisLog(REDIS_NOTICE, 625 "Clear FAIL state for node %.40s: slave is already reachable.", 626 node->name); 627 node->flags &= ~REDIS_NODE_FAIL; 628 changes++; 629 } 630 631 /* If it is a master and... 632 * 1) The FAIL state is old enough. We use our node timeout multiplicator 633 * plus some additional fixed time. The additional time is useful when 634 * the node timeout is extremely short and the reaction time of 635 * the cluster may be longer, so wait at least a few seconds always. 636 * 2) It is yet serving slots from our point of view (not failed over). 637 * Apparently no one is going to fix these slots, clear the FAIL flag. */ 638 if (node->flags & REDIS_NODE_MASTER && 639 node->numslots > 0 && 640 (now - node->fail_time) > 641 (server.cluster_node_timeout * REDIS_CLUSTER_FAIL_UNDO_TIME_MULT + 642 REDIS_CLUSTER_FAIL_UNDO_TIME_ADD)) 643 { 644 redisLog(REDIS_NOTICE, 645 "Clear FAIL state for node %.40s: is reachable again and nobody is serving its slots after some time.", 646 node->name); 647 node->flags &= ~REDIS_NODE_FAIL; 648 changes++; 649 } 650 651 /* Update state and save config. */ 652 if (changes) { 653 clusterUpdateState(); 654 clusterSaveConfigOrDie(); 655 } 656 } 657 658 /* Process the gossip section of PING or PONG packets. 659 * Note that this function assumes that the packet is already sanity-checked 660 * by the caller, not in the content of the gossip section, but in the 661 * length. */ 662 void clusterProcessGossipSection(clusterMsg *hdr, clusterLink *link) { 663 uint16_t count = ntohs(hdr->count); 664 clusterMsgDataGossip *g = (clusterMsgDataGossip*) hdr->data.ping.gossip; 665 clusterNode *sender = link->node ? link->node : clusterLookupNode(hdr->sender); 666 667 while(count--) { 668 sds ci = sdsempty(); 669 uint16_t flags = ntohs(g->flags); 670 clusterNode *node; 671 672 if (flags == 0) ci = sdscat(ci,"noflags,"); 673 if (flags & REDIS_NODE_MYSELF) ci = sdscat(ci,"myself,"); 674 if (flags & REDIS_NODE_MASTER) ci = sdscat(ci,"master,"); 675 if (flags & REDIS_NODE_SLAVE) ci = sdscat(ci,"slave,"); 676 if (flags & REDIS_NODE_PFAIL) ci = sdscat(ci,"fail?,"); 677 if (flags & REDIS_NODE_FAIL) ci = sdscat(ci,"fail,"); 678 if (flags & REDIS_NODE_HANDSHAKE) ci = sdscat(ci,"handshake,"); 679 if (flags & REDIS_NODE_NOADDR) ci = sdscat(ci,"noaddr,"); 680 if (flags & REDIS_NODE_PROMOTED) ci = sdscat(ci,"promoted,"); 681 if (ci[sdslen(ci)-1] == ',') ci[sdslen(ci)-1] = ' '; 682 683 redisLog(REDIS_DEBUG,"GOSSIP %.40s %s:%d %s", 684 g->nodename, 685 g->ip, 686 ntohs(g->port), 687 ci); 688 sdsfree(ci); 689 690 /* Update our state accordingly to the gossip sections */ 691 node = clusterLookupNode(g->nodename); 692 if (node != NULL) { 693 /* We already know this node. Let's start updating the last 694 * time PONG figure if it is newer than our figure. 695 * Note that it's not a problem if we have a PING already 696 * in progress against this node. */ 697 if (node->pong_received < (signed) ntohl(g->pong_received)) { 698 redisLog(REDIS_DEBUG,"Node pong_received updated by gossip"); 699 node->pong_received = ntohl(g->pong_received); 700 } 701 /* Handle failure reports, only when the sender is a master. */ 702 if (sender && sender->flags & REDIS_NODE_MASTER && 703 node != server.cluster->myself) 704 { 705 if (flags & (REDIS_NODE_FAIL|REDIS_NODE_PFAIL)) { 706 if (clusterNodeAddFailureReport(node,sender)) { 707 redisLog(REDIS_NOTICE, 708 "Node %.40s reported node %.40s as not reachable.", 709 sender->name, node->name); 710 } 711 markNodeAsFailingIfNeeded(node); 712 } else { 713 if (clusterNodeDelFailureReport(node,sender)) { 714 redisLog(REDIS_NOTICE, 715 "Node %.40s reported node %.40s is back online.", 716 sender->name, node->name); 717 } 718 } 719 } 720 } else { 721 /* If it's not in NOADDR state and we don't have it, we 722 * start an handshake process against this IP/PORT pairs. 723 * 724 * Note that we require that the sender of this gossip message 725 * is a well known node in our cluster, otherwise we risk 726 * joining another cluster. */ 727 if (sender && !(flags & REDIS_NODE_NOADDR)) { 728 clusterNode *newnode; 729 730 redisLog(REDIS_DEBUG,"Adding the new node"); 731 newnode = createClusterNode(NULL,REDIS_NODE_HANDSHAKE); 732 memcpy(newnode->ip,g->ip,sizeof(g->ip)); 733 newnode->port = ntohs(g->port); 734 clusterAddNode(newnode); 735 } 736 } 737 738 /* Next node */ 739 g++; 740 } 741 } 742 743 /* IP -> string conversion. 'buf' is supposed to at least be 16 bytes. */ 744 void nodeIp2String(char *buf, clusterLink *link) { 745 struct sockaddr_in sa; 746 socklen_t salen = sizeof(sa); 747 748 if (getpeername(link->fd, (struct sockaddr*) &sa, &salen) == -1) 749 redisPanic("getpeername() failed."); 750 strncpy(buf,inet_ntoa(sa.sin_addr),sizeof(link->node->ip)); 751 } 752 753 754 /* Update the node address to the IP address that can be extracted 755 * from link->fd, and at the specified port. */ 756 void nodeUpdateAddress(clusterNode *node, clusterLink *link, int port) { 757 /* TODO */ 758 } 759 760 /* When this function is called, there is a packet to process starting 761 * at node->rcvbuf. Releasing the buffer is up to the caller, so this 762 * function should just handle the higher level stuff of processing the 763 * packet, modifying the cluster state if needed. 764 * 765 * The function returns 1 if the link is still valid after the packet 766 * was processed, otherwise 0 if the link was freed since the packet 767 * processing lead to some inconsistency error (for instance a PONG 768 * received from the wrong sender ID). */ 769 int clusterProcessPacket(clusterLink *link) { 770 clusterMsg *hdr = (clusterMsg*) link->rcvbuf; 771 uint32_t totlen = ntohl(hdr->totlen); 772 uint16_t type = ntohs(hdr->type); 773 uint16_t flags = ntohs(hdr->flags); 774 clusterNode *sender; 775 776 redisLog(REDIS_DEBUG,"--- Processing packet of type %d, %lu bytes", 777 type, (unsigned long) totlen); 778 779 /* Perform sanity checks */ 780 if (totlen < 8) return 1; 781 if (totlen > sdslen(link->rcvbuf)) return 1; 782 if (type == CLUSTERMSG_TYPE_PING || type == CLUSTERMSG_TYPE_PONG || 783 type == CLUSTERMSG_TYPE_MEET) 784 { 785 uint16_t count = ntohs(hdr->count); 786 uint32_t explen; /* expected length of this packet */ 787 788 explen = sizeof(clusterMsg)-sizeof(union clusterMsgData); 789 explen += (sizeof(clusterMsgDataGossip)*count); 790 if (totlen != explen) return 1; 791 } else if (type == CLUSTERMSG_TYPE_FAIL) { 792 uint32_t explen = sizeof(clusterMsg)-sizeof(union clusterMsgData); 793 794 explen += sizeof(clusterMsgDataFail); 795 if (totlen != explen) return 1; 796 } else if (type == CLUSTERMSG_TYPE_PUBLISH) { 797 uint32_t explen = sizeof(clusterMsg)-sizeof(union clusterMsgData); 798 799 explen += sizeof(clusterMsgDataPublish) + 800 ntohl(hdr->data.publish.msg.channel_len) + 801 ntohl(hdr->data.publish.msg.message_len); 802 if (totlen != explen) return 1; 803 } else if (type == CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST || 804 type == CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK) { 805 uint32_t explen = sizeof(clusterMsg)-sizeof(union clusterMsgData); 806 807 if (totlen != explen) return 1; 808 } 809 810 /* Ready to process the packet. Dispatch by type. */ 811 sender = clusterLookupNode(hdr->sender); 812 if (type == CLUSTERMSG_TYPE_PING || type == CLUSTERMSG_TYPE_MEET) { 813 int update_config = 0; 814 redisLog(REDIS_DEBUG,"Ping packet received: %p", (void*)link->node); 815 816 /* Add this node if it is new for us and the msg type is MEET. 817 * In this stage we don't try to add the node with the right 818 * flags, slaveof pointer, and so forth, as this details will be 819 * resolved when we'll receive PONGs from the server. */ 820 if (!sender && type == CLUSTERMSG_TYPE_MEET) { 821 clusterNode *node; 822 823 node = createClusterNode(NULL,REDIS_NODE_HANDSHAKE); 824 nodeIp2String(node->ip,link); 825 node->port = ntohs(hdr->port); 826 clusterAddNode(node); 827 update_config = 1; 828 } 829 830 /* Get info from the gossip section */ 831 clusterProcessGossipSection(hdr,link); 832 833 /* Anyway reply with a PONG */ 834 clusterSendPing(link,CLUSTERMSG_TYPE_PONG); 835 836 /* Update config if needed */ 837 if (update_config) clusterSaveConfigOrDie(); 838 } else if (type == CLUSTERMSG_TYPE_PONG) { 839 int update_state = 0; 840 int update_config = 0; 841 842 redisLog(REDIS_DEBUG,"Pong packet received: %p", (void*)link->node); 843 if (link->node) { 844 if (link->node->flags & REDIS_NODE_HANDSHAKE) { 845 /* If we already have this node, try to change the 846 * IP/port of the node with the new one. */ 847 if (sender) { 848 redisLog(REDIS_WARNING, 849 "Handshake error: we already know node %.40s, updating the address if needed.", sender->name); 850 nodeUpdateAddress(sender,link,ntohs(hdr->port)); 851 freeClusterNode(link->node); /* will free the link too */ 852 return 0; 853 } 854 855 /* First thing to do is replacing the random name with the 856 * right node name if this was an handshake stage. */ 857 clusterRenameNode(link->node, hdr->sender); 858 redisLog(REDIS_DEBUG,"Handshake with node %.40s completed.", 859 link->node->name); 860 link->node->flags &= ~REDIS_NODE_HANDSHAKE; 861 link->node->flags |= flags&(REDIS_NODE_MASTER|REDIS_NODE_SLAVE); 862 update_config = 1; 863 } else if (memcmp(link->node->name,hdr->sender, 864 REDIS_CLUSTER_NAMELEN) != 0) 865 { 866 /* If the reply has a non matching node ID we 867 * disconnect this node and set it as not having an associated 868 * address. */ 869 redisLog(REDIS_DEBUG,"PONG contains mismatching sender ID"); 870 link->node->flags |= REDIS_NODE_NOADDR; 871 link->node->ip[0] = '\0'; 872 link->node->port = 0; 873 freeClusterLink(link); 874 update_config = 1; 875 /* FIXME: remove this node if we already have it. 876 * 877 * If we already have it but the IP is different, use 878 * the new one if the old node is in FAIL, PFAIL, or NOADDR 879 * status... */ 880 return 0; 881 } 882 } 883 884 /* Update our info about the node */ 885 if (link->node) link->node->pong_received = time(NULL); 886 887 /* Update master/slave state */ 888 if (sender) { 889 if (!memcmp(hdr->slaveof,REDIS_NODE_NULL_NAME, 890 sizeof(hdr->slaveof))) 891 { 892 /* Node is a master. */ 893 if (sender->flags & REDIS_NODE_SLAVE) { 894 /* Slave turned into master! */ 895 clusterNode *oldmaster = sender->slaveof; 896 897 /* Reconfigure node as master. */ 898 if (sender->slaveof) 899 clusterNodeRemoveSlave(sender->slaveof,sender); 900 sender->flags &= ~REDIS_NODE_SLAVE; 901 sender->flags |= REDIS_NODE_MASTER; 902 sender->slaveof = NULL; 903 904 /* If this node used to be our slave, and now has the 905 * PROMOTED flag set. We'll turn ourself into a slave 906 * of the new master. */ 907 if (flags & REDIS_NODE_PROMOTED && 908 oldmaster == server.cluster->myself) 909 { 910 redisLog(REDIS_WARNING,"One of my slaves took my place. Reconfiguring myself as a replica of %.40s", sender->name); 911 clusterDelNodeSlots(server.cluster->myself); 912 clusterSetMaster(sender); 913 } 914 915 /* If we are a slave, and this node used to be a slave 916 * of our master, and now has the PROMOTED flag set, we 917 * need to switch our replication setup over it. */ 918 if (flags & REDIS_NODE_PROMOTED && 919 server.cluster->myself->flags & REDIS_NODE_SLAVE && 920 server.cluster->myself->slaveof == oldmaster) 921 { 922 redisLog(REDIS_WARNING,"One of the slaves failed over my master. Reconfiguring myself as a replica of %.40s", sender->name); 923 clusterDelNodeSlots(server.cluster->myself); 924 clusterSetMaster(sender); 925 } 926 927 /* Update config and state. */ 928 update_state = 1; 929 update_config = 1; 930 } 931 } else { 932 /* Node is a slave. */ 933 clusterNode *master = clusterLookupNode(hdr->slaveof); 934 935 if (sender->flags & REDIS_NODE_MASTER) { 936 /* Master turned into a slave! Reconfigure the node. */ 937 clusterDelNodeSlots(sender); 938 sender->flags &= ~REDIS_NODE_MASTER; 939 sender->flags |= REDIS_NODE_SLAVE; 940 941 /* Remove the list of slaves from the node. */ 942 if (sender->numslaves) clusterNodeResetSlaves(sender); 943 944 /* Update config and state. */ 945 update_state = 1; 946 update_config = 1; 947 } 948 949 /* Master node changed for this slave? */ 950 if (sender->slaveof != master) { 951 if (sender->slaveof) 952 clusterNodeRemoveSlave(sender->slaveof,sender); 953 clusterNodeAddSlave(master,sender); 954 sender->slaveof = master; 955 } 956 } 957 } 958 959 /* Update our info about served slots. 960 * Note: this MUST happen after we update the master/slave state 961 * so that REDIS_NODE_MASTER flag will be set. */ 962 if (sender && sender->flags & REDIS_NODE_MASTER) { 963 int changes, j; 964 965 changes = 966 memcmp(sender->slots,hdr->myslots,sizeof(hdr->myslots)) != 0; 967 if (changes) { 968 for (j = 0; j < REDIS_CLUSTER_SLOTS; j++) { 969 if (bitmapTestBit(hdr->myslots,j)) { 970 /* If this slot was not served, or served by a node 971 * in FAIL state, update the table with the new node 972 * claiming to serve the slot. */ 973 if (server.cluster->slots[j] == sender) continue; 974 if (server.cluster->slots[j] == NULL || 975 server.cluster->slots[j]->flags & REDIS_NODE_FAIL) 976 { 977 clusterDelSlot(j); 978 clusterAddSlot(sender,j); 979 update_state = update_config = 1; 980 } 981 } else { 982 /* This node claims to no longer handling the slot, 983 * however we don't change our config as this is likely 984 * happening because a resharding is in progress, and 985 * it already knows where to redirect clients. */ 986 } 987 } 988 } 989 } 990 991 /* Get info from the gossip section */ 992 clusterProcessGossipSection(hdr,link); 993 994 /* Update the cluster state if needed */ 995 if (update_state) clusterUpdateState(); 996 if (update_config) clusterSaveConfigOrDie(); 997 } else if (type == CLUSTERMSG_TYPE_FAIL && sender) { 998 clusterNode *failing; 999 1000 failing = clusterLookupNode(hdr->data.fail.about.nodename); 1001 if (failing && !(failing->flags & (REDIS_NODE_FAIL|REDIS_NODE_MYSELF))) 1002 { 1003 redisLog(REDIS_NOTICE, 1004 "FAIL message received from %.40s about %.40s", 1005 hdr->sender, hdr->data.fail.about.nodename); 1006 failing->flags |= REDIS_NODE_FAIL; 1007 failing->fail_time = time(NULL); 1008 failing->flags &= ~REDIS_NODE_PFAIL; 1009 clusterUpdateState(); 1010 clusterSaveConfigOrDie(); 1011 } 1012 } else if (type == CLUSTERMSG_TYPE_PUBLISH) { 1013 robj *channel, *message; 1014 uint32_t channel_len, message_len; 1015 1016 /* Don't bother creating useless objects if there are no Pub/Sub subscribers. */ 1017 if (dictSize(server.pubsub_channels) || listLength(server.pubsub_patterns)) { 1018 channel_len = ntohl(hdr->data.publish.msg.channel_len); 1019 message_len = ntohl(hdr->data.publish.msg.message_len); 1020 channel = createStringObject( 1021 (char*)hdr->data.publish.msg.bulk_data,channel_len); 1022 message = createStringObject( 1023 (char*)hdr->data.publish.msg.bulk_data+channel_len, message_len); 1024 pubsubPublishMessage(channel,message); 1025 decrRefCount(channel); 1026 decrRefCount(message); 1027 } 1028 } else if (type == CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST) { 1029 if (!sender) return 0; /* We don't know that node. */ 1030 /* If we are not a master, ignore that message at all. */ 1031 if (!(server.cluster->myself->flags & REDIS_NODE_MASTER)) return 0; 1032 clusterSendFailoverAuthIfNeeded(sender); 1033 } else if (type == CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK) { 1034 if (!sender) return 0; /* We don't know that node. */ 1035 /* If this is a master, increment the number of acknowledges 1036 * we received so far. */ 1037 if (sender->flags & REDIS_NODE_MASTER) 1038 server.cluster->failover_auth_count++; 1039 } else { 1040 redisLog(REDIS_WARNING,"Received unknown packet type: %d", type); 1041 } 1042 return 1; 1043 } 1044 1045 /* This function is called when we detect the link with this node is lost. 1046 We set the node as no longer connected. The Cluster Cron will detect 1047 this connection and will try to get it connected again. 1048 1049 Instead if the node is a temporary node used to accept a query, we 1050 completely free the node on error. */ 1051 void handleLinkIOError(clusterLink *link) { 1052 freeClusterLink(link); 1053 } 1054 1055 /* Send data. This is handled using a trivial send buffer that gets 1056 * consumed by write(). We don't try to optimize this for speed too much 1057 * as this is a very low traffic channel. */ 1058 void clusterWriteHandler(aeEventLoop *el, int fd, void *privdata, int mask) { 1059 clusterLink *link = (clusterLink*) privdata; 1060 ssize_t nwritten; 1061 REDIS_NOTUSED(el); 1062 REDIS_NOTUSED(mask); 1063 1064 nwritten = write(fd, link->sndbuf, sdslen(link->sndbuf)); 1065 if (nwritten <= 0) { 1066 redisLog(REDIS_DEBUG,"I/O error writing to node link: %s", 1067 strerror(errno)); 1068 handleLinkIOError(link); 1069 return; 1070 } 1071 link->sndbuf = sdsrange(link->sndbuf,nwritten,-1); 1072 if (sdslen(link->sndbuf) == 0) 1073 aeDeleteFileEvent(server.el, link->fd, AE_WRITABLE); 1074 } 1075 1076 /* Read data. Try to read the first field of the header first to check the 1077 * full length of the packet. When a whole packet is in memory this function 1078 * will call the function to process the packet. And so forth. */ 1079 void clusterReadHandler(aeEventLoop *el, int fd, void *privdata, int mask) { 1080 char buf[4096]; 1081 ssize_t nread; 1082 clusterMsg *hdr; 1083 clusterLink *link = (clusterLink*) privdata; 1084 int readlen, rcvbuflen; 1085 REDIS_NOTUSED(el); 1086 REDIS_NOTUSED(mask); 1087 1088 again: 1089 rcvbuflen = sdslen(link->rcvbuf); 1090 if (rcvbuflen < 4) { 1091 /* First, obtain the first four bytes to get the full message 1092 * length. */ 1093 readlen = 4 - rcvbuflen; 1094 } else { 1095 /* Finally read the full message. */ 1096 hdr = (clusterMsg*) link->rcvbuf; 1097 if (rcvbuflen == 4) { 1098 /* Perform some sanity check on the message length. */ 1099 if (ntohl(hdr->totlen) < CLUSTERMSG_MIN_LEN) { 1100 redisLog(REDIS_WARNING, 1101 "Bad message length received from Cluster bus."); 1102 handleLinkIOError(link); 1103 return; 1104 } 1105 } 1106 readlen = ntohl(hdr->totlen) - rcvbuflen; 1107 } 1108 1109 nread = read(fd,buf,readlen); 1110 if (nread == -1 && errno == EAGAIN) return; /* No more data ready. */ 1111 1112 if (nread <= 0) { 1113 /* I/O error... */ 1114 redisLog(REDIS_DEBUG,"I/O error reading from node link: %s", 1115 (nread == 0) ? "connection closed" : strerror(errno)); 1116 handleLinkIOError(link); 1117 return; 1118 } else { 1119 /* Read data and recast the pointer to the new buffer. */ 1120 link->rcvbuf = sdscatlen(link->rcvbuf,buf,nread); 1121 hdr = (clusterMsg*) link->rcvbuf; 1122 rcvbuflen += nread; 1123 } 1124 1125 /* Total length obtained? read the payload now instead of burning 1126 * cycles waiting for a new event to fire. */ 1127 if (rcvbuflen == 4) goto again; 1128 1129 /* Whole packet in memory? We can process it. */ 1130 if (rcvbuflen == ntohl(hdr->totlen)) { 1131 if (clusterProcessPacket(link)) { 1132 sdsfree(link->rcvbuf); 1133 link->rcvbuf = sdsempty(); 1134 rcvbuflen = 0; /* Useless line of code currently... defensive. */ 1135 } 1136 } 1137 } 1138 1139 /* Put stuff into the send buffer. */ 1140 void clusterSendMessage(clusterLink *link, unsigned char *msg, size_t msglen) { 1141 if (sdslen(link->sndbuf) == 0 && msglen != 0) 1142 aeCreateFileEvent(server.el,link->fd,AE_WRITABLE, 1143 clusterWriteHandler,link); 1144 1145 link->sndbuf = sdscatlen(link->sndbuf, msg, msglen); 1146 } 1147 1148 /* Send a message to all the nodes that are part of the cluster having 1149 * a connected link. */ 1150 void clusterBroadcastMessage(void *buf, size_t len) { 1151 dictIterator *di; 1152 dictEntry *de; 1153 1154 di = dictGetIterator(server.cluster->nodes); 1155 while((de = dictNext(di)) != NULL) { 1156 clusterNode *node = dictGetVal(de); 1157 1158 if (!node->link) continue; 1159 if (node->flags & (REDIS_NODE_MYSELF|REDIS_NODE_HANDSHAKE)) 1160 continue; 1161 clusterSendMessage(node->link,buf,len); 1162 } 1163 dictReleaseIterator(di); 1164 } 1165 1166 /* Build the message header */ 1167 void clusterBuildMessageHdr(clusterMsg *hdr, int type) { 1168 int totlen = 0; 1169 1170 memset(hdr,0,sizeof(*hdr)); 1171 hdr->type = htons(type); 1172 memcpy(hdr->sender,server.cluster->myself->name,REDIS_CLUSTER_NAMELEN); 1173 memcpy(hdr->myslots,server.cluster->myself->slots, 1174 sizeof(hdr->myslots)); 1175 memset(hdr->slaveof,0,REDIS_CLUSTER_NAMELEN); 1176 if (server.cluster->myself->slaveof != NULL) { 1177 memcpy(hdr->slaveof,server.cluster->myself->slaveof->name, 1178 REDIS_CLUSTER_NAMELEN); 1179 } 1180 hdr->port = htons(server.port); 1181 hdr->flags = htons(server.cluster->myself->flags); 1182 hdr->state = server.cluster->state; 1183 1184 if (type == CLUSTERMSG_TYPE_FAIL) { 1185 totlen = sizeof(clusterMsg)-sizeof(union clusterMsgData); 1186 totlen += sizeof(clusterMsgDataFail); 1187 } 1188 hdr->totlen = htonl(totlen); 1189 /* For PING, PONG, and MEET, fixing the totlen field is up to the caller */ 1190 } 1191 1192 /* Send a PING or PONG packet to the specified node, making sure to add enough 1193 * gossip informations. */ 1194 void clusterSendPing(clusterLink *link, int type) { 1195 unsigned char buf[4096]; 1196 clusterMsg *hdr = (clusterMsg*) buf; 1197 int gossipcount = 0, totlen; 1198 /* freshnodes is the number of nodes we can still use to populate the 1199 * gossip section of the ping packet. Basically we start with the nodes 1200 * we have in memory minus two (ourself and the node we are sending the 1201 * message to). Every time we add a node we decrement the counter, so when 1202 * it will drop to <= zero we know there is no more gossip info we can 1203 * send. */ 1204 int freshnodes = dictSize(server.cluster->nodes)-2; 1205 1206 if (link->node && type == CLUSTERMSG_TYPE_PING) 1207 link->node->ping_sent = time(NULL); 1208 clusterBuildMessageHdr(hdr,type); 1209 1210 /* Populate the gossip fields */ 1211 while(freshnodes > 0 && gossipcount < 3) { 1212 struct dictEntry *de = dictGetRandomKey(server.cluster->nodes); 1213 clusterNode *this = dictGetVal(de); 1214 clusterMsgDataGossip *gossip; 1215 int j; 1216 1217 /* In the gossip section don't include: 1218 * 1) Myself. 1219 * 2) Nodes in HANDSHAKE state. 1220 * 3) Nodes with the NOADDR flag set. 1221 * 4) Disconnected nodes if they don't have configured slots. 1222 */ 1223 if (this == server.cluster->myself || 1224 this->flags & (REDIS_NODE_HANDSHAKE|REDIS_NODE_NOADDR) || 1225 (this->link == NULL && this->numslots == 0)) 1226 { 1227 freshnodes--; /* otherwise we may loop forever. */ 1228 continue; 1229 } 1230 1231 /* Check if we already added this node */ 1232 for (j = 0; j < gossipcount; j++) { 1233 if (memcmp(hdr->data.ping.gossip[j].nodename,this->name, 1234 REDIS_CLUSTER_NAMELEN) == 0) break; 1235 } 1236 if (j != gossipcount) continue; 1237 1238 /* Add it */ 1239 freshnodes--; 1240 gossip = &(hdr->data.ping.gossip[gossipcount]); 1241 memcpy(gossip->nodename,this->name,REDIS_CLUSTER_NAMELEN); 1242 gossip->ping_sent = htonl(this->ping_sent); 1243 gossip->pong_received = htonl(this->pong_received); 1244 memcpy(gossip->ip,this->ip,sizeof(this->ip)); 1245 gossip->port = htons(this->port); 1246 gossip->flags = htons(this->flags); 1247 gossipcount++; 1248 } 1249 totlen = sizeof(clusterMsg)-sizeof(union clusterMsgData); 1250 totlen += (sizeof(clusterMsgDataGossip)*gossipcount); 1251 hdr->count = htons(gossipcount); 1252 hdr->totlen = htonl(totlen); 1253 clusterSendMessage(link,buf,totlen); 1254 } 1255 1256 /* Send a PING packet to every connected node that's not in handshake state. 1257 * 1258 * Usually cluster nodes will ping just another node every second, however 1259 * in Redis Cluster pings are not just used for failure detection, but also 1260 * to carry important configuration informations. So broadcasting a ping is 1261 * useful when something changes in the configuration and we want to make 1262 * the cluster aware ASAP (for instance after a slave promotion). */ 1263 void clusterBroadcastPing(void) { 1264 dictIterator *di; 1265 dictEntry *de; 1266 1267 di = dictGetIterator(server.cluster->nodes); 1268 while((de = dictNext(di)) != NULL) { 1269 clusterNode *node = dictGetVal(de); 1270 1271 if (node->flags & (REDIS_NODE_MYSELF|REDIS_NODE_HANDSHAKE)) continue; 1272 clusterSendPing(node->link,CLUSTERMSG_TYPE_PONG); 1273 } 1274 dictReleaseIterator(di); 1275 } 1276 1277 /* Send a PUBLISH message. 1278 * 1279 * If link is NULL, then the message is broadcasted to the whole cluster. */ 1280 void clusterSendPublish(clusterLink *link, robj *channel, robj *message) { 1281 unsigned char buf[4096], *payload; 1282 clusterMsg *hdr = (clusterMsg*) buf; 1283 uint32_t totlen; 1284 uint32_t channel_len, message_len; 1285 1286 channel = getDecodedObject(channel); 1287 message = getDecodedObject(message); 1288 channel_len = sdslen(channel->ptr); 1289 message_len = sdslen(message->ptr); 1290 1291 clusterBuildMessageHdr(hdr,CLUSTERMSG_TYPE_PUBLISH); 1292 totlen = sizeof(clusterMsg)-sizeof(union clusterMsgData); 1293 totlen += sizeof(clusterMsgDataPublish) + channel_len + message_len; 1294 1295 hdr->data.publish.msg.channel_len = htonl(channel_len); 1296 hdr->data.publish.msg.message_len = htonl(message_len); 1297 hdr->totlen = htonl(totlen); 1298 1299 /* Try to use the local buffer if possible */ 1300 if (totlen < sizeof(buf)) { 1301 payload = buf; 1302 } else { 1303 payload = zmalloc(totlen); 1304 hdr = (clusterMsg*) payload; 1305 memcpy(payload,hdr,sizeof(*hdr)); 1306 } 1307 memcpy(hdr->data.publish.msg.bulk_data,channel->ptr,sdslen(channel->ptr)); 1308 memcpy(hdr->data.publish.msg.bulk_data+sdslen(channel->ptr), 1309 message->ptr,sdslen(message->ptr)); 1310 1311 if (link) 1312 clusterSendMessage(link,payload,totlen); 1313 else 1314 clusterBroadcastMessage(payload,totlen); 1315 1316 decrRefCount(channel); 1317 decrRefCount(message); 1318 if (payload != buf) zfree(payload); 1319 } 1320 1321 /* Send a FAIL message to all the nodes we are able to contact. 1322 * The FAIL message is sent when we detect that a node is failing 1323 * (REDIS_NODE_PFAIL) and we also receive a gossip confirmation of this: 1324 * we switch the node state to REDIS_NODE_FAIL and ask all the other 1325 * nodes to do the same ASAP. */ 1326 void clusterSendFail(char *nodename) { 1327 unsigned char buf[4096]; 1328 clusterMsg *hdr = (clusterMsg*) buf; 1329 1330 clusterBuildMessageHdr(hdr,CLUSTERMSG_TYPE_FAIL); 1331 memcpy(hdr->data.fail.about.nodename,nodename,REDIS_CLUSTER_NAMELEN); 1332 clusterBroadcastMessage(buf,ntohl(hdr->totlen)); 1333 } 1334 1335 /* ----------------------------------------------------------------------------- 1336 * CLUSTER Pub/Sub support 1337 * 1338 * For now we do very little, just propagating PUBLISH messages across the whole 1339 * cluster. In the future we'll try to get smarter and avoiding propagating those 1340 * messages to hosts without receives for a given channel. 1341 * -------------------------------------------------------------------------- */ 1342 void clusterPropagatePublish(robj *channel, robj *message) { 1343 clusterSendPublish(NULL, channel, message); 1344 } 1345 1346 /* ----------------------------------------------------------------------------- 1347 * SLAVE node specific functions 1348 * -------------------------------------------------------------------------- */ 1349 1350 /* This function sends a FAILOVE_AUTH_REQUEST message to every node in order to 1351 * see if there is the quorum for this slave instance to failover its failing 1352 * master. 1353 * 1354 * Note that we send the failover request to everybody, master and slave nodes, 1355 * but only the masters are supposed to reply to our query. */ 1356 void clusterRequestFailoverAuth(void) { 1357 unsigned char buf[4096]; 1358 clusterMsg *hdr = (clusterMsg*) buf; 1359 uint32_t totlen; 1360 1361 clusterBuildMessageHdr(hdr,CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST); 1362 totlen = sizeof(clusterMsg)-sizeof(union clusterMsgData); 1363 hdr->totlen = htonl(totlen); 1364 clusterBroadcastMessage(buf,totlen); 1365 } 1366 1367 /* Send a FAILOVER_AUTH_ACK message to the specified node. */ 1368 void clusterSendFailoverAuth(clusterNode *node) { 1369 unsigned char buf[4096]; 1370 clusterMsg *hdr = (clusterMsg*) buf; 1371 uint32_t totlen; 1372 1373 if (!node->link) return; 1374 clusterBuildMessageHdr(hdr,CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK); 1375 totlen = sizeof(clusterMsg)-sizeof(union clusterMsgData); 1376 hdr->totlen = htonl(totlen); 1377 clusterSendMessage(node->link,buf,totlen); 1378 } 1379 1380 /* If we believe 'node' is the "first slave" of it's master, reply with 1381 * a FAILOVER_AUTH_GRANTED packet. 1382 * 1383 * To be a first slave the sender must: 1384 * 1) Be a slave. 1385 * 2) Its master should be in FAIL state. 1386 * 3) Ordering all the slaves IDs for its master by run-id, it should be the 1387 * first (the smallest) among the ones not in FAIL / PFAIL state. 1388 */ 1389 void clusterSendFailoverAuthIfNeeded(clusterNode *node) { 1390 char first[REDIS_CLUSTER_NAMELEN]; 1391 clusterNode *master = node->slaveof; 1392 int j; 1393 1394 /* Node is a slave? Its master is down? */ 1395 if (!(node->flags & REDIS_NODE_SLAVE) || 1396 master == NULL || 1397 !(master->flags & REDIS_NODE_FAIL)) return; 1398 1399 /* Iterate all the master slaves to check what's the first one. */ 1400 memset(first,0xff,sizeof(first)); 1401 for (j = 0; j < master->numslaves; j++) { 1402 clusterNode *slave = master->slaves[j]; 1403 1404 if (slave->flags & (REDIS_NODE_FAIL|REDIS_NODE_PFAIL)) continue; 1405 if (memcmp(slave->name,first,sizeof(first)) < 0) { 1406 memcpy(first,slave->name,sizeof(first)); 1407 } 1408 } 1409 1410 /* Is 'node' the first slave? */ 1411 if (memcmp(node->name,first,sizeof(first)) != 0) return; 1412 1413 /* We can send the packet. */ 1414 clusterSendFailoverAuth(node); 1415 } 1416 1417 /* This function is called if we are a slave node and our master serving 1418 * a non-zero amount of hash slots is in FAIL state. 1419 * 1420 * The gaol of this function is: 1421 * 1) To check if we are able to perform a failover, is our data updated? 1422 * 2) Ask reachable masters the authorization to perform the failover. 1423 * 3) Check if there is the majority of masters agreeing we should failover. 1424 * 4) Perform the failover informing all the other nodes. 1425 */ 1426 void clusterHandleSlaveFailover(void) { 1427 time_t data_age = server.unixtime - server.repl_down_since; 1428 time_t auth_age = server.unixtime - server.cluster->failover_auth_time; 1429 int needed_quorum = (server.cluster->size / 2) + 1; 1430 int j; 1431 1432 /* Check if our data is recent enough. For now we just use a fixed 1433 * constant of ten times the node timeout since the cluster should 1434 * react much faster to a master down. */ 1435 if (data_age > 1436 server.cluster_node_timeout * REDIS_CLUSTER_SLAVE_VALIDITY_MULT) 1437 return; 1438 1439 /* TODO: check if we are the first slave as well? Or just rely on the 1440 * master authorization? */ 1441 1442 /* Ask masters if we are authorized to perform the failover. If there 1443 * is a pending auth request that's too old, reset it. */ 1444 if (server.cluster->failover_auth_time == 0 || 1445 auth_age > 1446 server.cluster_node_timeout * REDIS_CLUSTER_FAILOVER_AUTH_RETRY_MULT) 1447 { 1448 redisLog(REDIS_WARNING,"Asking masters if I can failover..."); 1449 server.cluster->failover_auth_time = time(NULL); 1450 server.cluster->failover_auth_count = 0; 1451 clusterRequestFailoverAuth(); 1452 return; /* Wait for replies. */ 1453 } 1454 1455 /* Check if we reached the quorum. */ 1456 if (server.cluster->failover_auth_count >= needed_quorum) { 1457 clusterNode *oldmaster = server.cluster->myself->slaveof; 1458 1459 redisLog(REDIS_WARNING, 1460 "Masters quorum reached: failing over my (failing) master."); 1461 /* We have the quorum, perform all the steps to correctly promote 1462 * this slave to a master. 1463 * 1464 * 1) Turn this node into a master. */ 1465 clusterNodeRemoveSlave(server.cluster->myself->slaveof, 1466 server.cluster->myself); 1467 server.cluster->myself->flags &= ~REDIS_NODE_SLAVE; 1468 server.cluster->myself->flags |= REDIS_NODE_MASTER; 1469 server.cluster->myself->flags |= REDIS_NODE_PROMOTED; 1470 server.cluster->myself->slaveof = NULL; 1471 replicationUnsetMaster(); 1472 1473 /* 2) Claim all the slots assigned to our master. */ 1474 for (j = 0; j < REDIS_CLUSTER_SLOTS; j++) { 1475 if (clusterNodeGetSlotBit(oldmaster,j)) { 1476 clusterDelSlot(j); 1477 clusterAddSlot(server.cluster->myself,j); 1478 } 1479 } 1480 1481 /* 3) Ping all the other nodes so that they can update the state 1482 * accordingly and detect that we switched to master role. */ 1483 clusterBroadcastPing(); 1484 1485 /* 4) Update state and save config. */ 1486 clusterUpdateState(); 1487 clusterSaveConfigOrDie(); 1488 } 1489 } 1490 1491 /* ----------------------------------------------------------------------------- 1492 * CLUSTER cron job 1493 * -------------------------------------------------------------------------- */ 1494 1495 /* This is executed 1 time every second */ 1496 void clusterCron(void) { 1497 dictIterator *di; 1498 dictEntry *de; 1499 int j, update_state = 0; 1500 time_t min_ping_sent = 0; 1501 clusterNode *min_ping_node = NULL; 1502 1503 /* Check if we have disconnected nodes and re-establish the connection. */ 1504 di = dictGetIterator(server.cluster->nodes); 1505 while((de = dictNext(di)) != NULL) { 1506 clusterNode *node = dictGetVal(de); 1507 1508 if (node->flags & (REDIS_NODE_MYSELF|REDIS_NODE_NOADDR)) continue; 1509 if (node->link == NULL) { 1510 int fd; 1511 clusterLink *link; 1512 1513 fd = anetTcpNonBlockConnect(server.neterr, node->ip, 1514 node->port+REDIS_CLUSTER_PORT_INCR); 1515 if (fd == -1) continue; 1516 link = createClusterLink(node); 1517 link->fd = fd; 1518 node->link = link; 1519 aeCreateFileEvent(server.el,link->fd,AE_READABLE,clusterReadHandler,link); 1520 /* If the node is flagged as MEET, we send a MEET message instead 1521 * of a PING one, to force the receiver to add us in its node 1522 * table. */ 1523 clusterSendPing(link, node->flags & REDIS_NODE_MEET ? 1524 CLUSTERMSG_TYPE_MEET : CLUSTERMSG_TYPE_PING); 1525 /* We can clear the flag after the first packet is sent. 1526 * If we'll never receive a PONG, we'll never send new packets 1527 * to this node. Instead after the PONG is received and we 1528 * are no longer in meet/handshake status, we want to send 1529 * normal PING packets. */ 1530 node->flags &= ~REDIS_NODE_MEET; 1531 1532 redisLog(REDIS_DEBUG,"Connecting with Node %.40s at %s:%d", node->name, node->ip, node->port+REDIS_CLUSTER_PORT_INCR); 1533 } 1534 } 1535 dictReleaseIterator(di); 1536 1537 /* Ping some random node. Check a few random nodes and ping the one with 1538 * the oldest ping_sent time */ 1539 for (j = 0; j < 5; j++) { 1540 de = dictGetRandomKey(server.cluster->nodes); 1541 clusterNode *this = dictGetVal(de); 1542 1543 if (this->link == NULL) continue; 1544 if (this->flags & (REDIS_NODE_MYSELF|REDIS_NODE_HANDSHAKE)) continue; 1545 if (min_ping_node == NULL || min_ping_sent > this->ping_sent) { 1546 min_ping_node = this; 1547 min_ping_sent = this->ping_sent; 1548 } 1549 } 1550 if (min_ping_node) { 1551 redisLog(REDIS_DEBUG,"Pinging node %40s", min_ping_node->name); 1552 clusterSendPing(min_ping_node->link, CLUSTERMSG_TYPE_PING); 1553 } 1554 1555 /* Iterate nodes to check if we need to flag something as failing */ 1556 di = dictGetIterator(server.cluster->nodes); 1557 while((de = dictNext(di)) != NULL) { 1558 clusterNode *node = dictGetVal(de); 1559 time_t now = time(NULL); 1560 int delay; 1561 1562 if (node->flags & 1563 (REDIS_NODE_MYSELF|REDIS_NODE_NOADDR|REDIS_NODE_HANDSHAKE)) 1564 continue; 1565 1566 /* If our ping is older than half the cluster timeout (may happen 1567 * in a cluster with many nodes), send a new ping. */ 1568 if (node->link && 1569 (now - node->ping_sent) > server.cluster_node_timeout/2) 1570 { 1571 clusterSendPing(node->link, CLUSTERMSG_TYPE_PING); 1572 continue; 1573 } 1574 1575 /* Check only if we already sent a ping and did not received 1576 * a reply yet. */ 1577 if (node->ping_sent == 0 || 1578 node->ping_sent <= node->pong_received) continue; 1579 1580 /* If we never received a pong, use the ping time to compute 1581 * the delay. */ 1582 if (node->pong_received) { 1583 delay = now - node->pong_received; 1584 } else { 1585 delay = now - node->ping_sent; 1586 } 1587 1588 if (delay < server.cluster_node_timeout) { 1589 /* The PFAIL condition can be reversed without external 1590 * help if it is not transitive (that is, if it does not 1591 * turn into a FAIL state). 1592 * 1593 * The FAIL condition is also reversible under specific 1594 * conditions detected by clearNodeFailureIfNeeded(). */ 1595 if (node->flags & REDIS_NODE_PFAIL) { 1596 node->flags &= ~REDIS_NODE_PFAIL; 1597 update_state = 1; 1598 } else if (node->flags & REDIS_NODE_FAIL) { 1599 clearNodeFailureIfNeeded(node); 1600 } 1601 } else { 1602 /* Timeout reached. Set the node as possibly failing if it is 1603 * not already in this state. */ 1604 if (!(node->flags & (REDIS_NODE_PFAIL|REDIS_NODE_FAIL))) { 1605 redisLog(REDIS_DEBUG,"*** NODE %.40s possibly failing", 1606 node->name); 1607 node->flags |= REDIS_NODE_PFAIL; 1608 update_state = 1; 1609 } 1610 } 1611 } 1612 dictReleaseIterator(di); 1613 1614 /* If we are a slave node but the replication is still turned off, 1615 * enable it if we know the address of our master and it appears to 1616 * be up. */ 1617 if (server.cluster->myself->flags & REDIS_NODE_SLAVE && 1618 server.masterhost == NULL && 1619 server.cluster->myself->slaveof && 1620 !(server.cluster->myself->slaveof->flags & REDIS_NODE_NOADDR)) 1621 { 1622 replicationSetMaster(server.cluster->myself->slaveof->ip, 1623 server.cluster->myself->slaveof->port); 1624 } 1625 1626 /* If we are a slave and our master is down, but is serving slots, 1627 * call the function that handles the failover. 1628 * This function is called with a small delay in order to let the 1629 * FAIL message to propagate after failure detection, this is not 1630 * strictly required but makes 99.99% of failovers mechanically 1631 * simpler. */ 1632 if (server.cluster->myself->flags & REDIS_NODE_SLAVE && 1633 server.cluster->myself->slaveof && 1634 server.cluster->myself->slaveof->flags & REDIS_NODE_FAIL && 1635 (server.unixtime - server.cluster->myself->slaveof->fail_time) > 1636 REDIS_CLUSTER_FAILOVER_DELAY && 1637 server.cluster->myself->slaveof->numslots != 0) 1638 { 1639 clusterHandleSlaveFailover(); 1640 } 1641 1642 if (update_state) clusterUpdateState(); 1643 } 1644 1645 /* ----------------------------------------------------------------------------- 1646 * Slots management 1647 * -------------------------------------------------------------------------- */ 1648 1649 /* Test bit 'pos' in a generic bitmap. Return 1 if the bit is zet, 1650 * otherwise 0. */ 1651 int bitmapTestBit(unsigned char *bitmap, int pos) { 1652 off_t byte = pos/8; 1653 int bit = pos&7; 1654 return (bitmap[byte] & (1<<bit)) != 0; 1655 } 1656 1657 /* Set the bit at position 'pos' in a bitmap. */ 1658 void bitmapSetBit(unsigned char *bitmap, int pos) { 1659 off_t byte = pos/8; 1660 int bit = pos&7; 1661 bitmap[byte] |= 1<<bit; 1662 } 1663 1664 /* Clear the bit at position 'pos' in a bitmap. */ 1665 void bitmapClearBit(unsigned char *bitmap, int pos) { 1666 off_t byte = pos/8; 1667 int bit = pos&7; 1668 bitmap[byte] &= ~(1<<bit); 1669 } 1670 1671 /* Set the slot bit and return the old value. */ 1672 int clusterNodeSetSlotBit(clusterNode *n, int slot) { 1673 int old = bitmapTestBit(n->slots,slot); 1674 bitmapSetBit(n->slots,slot); 1675 if (!old) n->numslots++; 1676 return old; 1677 } 1678 1679 /* Clear the slot bit and return the old value. */ 1680 int clusterNodeClearSlotBit(clusterNode *n, int slot) { 1681 int old = bitmapTestBit(n->slots,slot); 1682 bitmapClearBit(n->slots,slot); 1683 if (old) n->numslots--; 1684 return old; 1685 } 1686 1687 /* Return the slot bit from the cluster node structure. */ 1688 int clusterNodeGetSlotBit(clusterNode *n, int slot) { 1689 return bitmapTestBit(n->slots,slot); 1690 } 1691 1692 /* Add the specified slot to the list of slots that node 'n' will 1693 * serve. Return REDIS_OK if the operation ended with success. 1694 * If the slot is already assigned to another instance this is considered 1695 * an error and REDIS_ERR is returned. */ 1696 int clusterAddSlot(clusterNode *n, int slot) { 1697 if (server.cluster->slots[slot]) return REDIS_ERR; 1698 clusterNodeSetSlotBit(n,slot); 1699 server.cluster->slots[slot] = n; 1700 return REDIS_OK; 1701 } 1702 1703 /* Delete the specified slot marking it as unassigned. 1704 * Returns REDIS_OK if the slot was assigned, otherwise if the slot was 1705 * already unassigned REDIS_ERR is returned. */ 1706 int clusterDelSlot(int slot) { 1707 clusterNode *n = server.cluster->slots[slot]; 1708 1709 if (!n) return REDIS_ERR; 1710 redisAssert(clusterNodeClearSlotBit(n,slot) == 1); 1711 server.cluster->slots[slot] = NULL; 1712 return REDIS_OK; 1713 } 1714 1715 /* Delete all the slots associated with the specified node. 1716 * The number of deleted slots is returned. */ 1717 int clusterDelNodeSlots(clusterNode *node) { 1718 int deleted = 0, j; 1719 1720 for (j = 0; j < REDIS_CLUSTER_SLOTS; j++) { 1721 if (clusterNodeGetSlotBit(node,j)) clusterDelSlot(j); 1722 deleted++; 1723 } 1724 return deleted; 1725 } 1726 1727 /* ----------------------------------------------------------------------------- 1728 * Cluster state evaluation function 1729 * -------------------------------------------------------------------------- */ 1730 void clusterUpdateState(void) { 1731 int j, initial_state = server.cluster->state; 1732 int unreachable_masters = 0; 1733 1734 /* Start assuming the state is OK. We'll turn it into FAIL if there 1735 * are the right conditions. */ 1736 server.cluster->state = REDIS_CLUSTER_OK; 1737 1738 /* Check if all the slots are covered. */ 1739 for (j = 0; j < REDIS_CLUSTER_SLOTS; j++) { 1740 if (server.cluster->slots[j] == NULL || 1741 server.cluster->slots[j]->flags & (REDIS_NODE_FAIL)) 1742 { 1743 server.cluster->state = REDIS_CLUSTER_FAIL; 1744 break; 1745 } 1746 } 1747 1748 /* Compute the cluster size, that is the number of master nodes 1749 * serving at least a single slot. 1750 * 1751 * At the same time count the number of unreachable masters with 1752 * at least one node. */ 1753 { 1754 dictIterator *di; 1755 dictEntry *de; 1756 1757 server.cluster->size = 0; 1758 di = dictGetIterator(server.cluster->nodes); 1759 while((de = dictNext(di)) != NULL) { 1760 clusterNode *node = dictGetVal(de); 1761 1762 if (node->flags & REDIS_NODE_MASTER && node->numslots) { 1763 server.cluster->size++; 1764 if (node->flags & (REDIS_NODE_FAIL|REDIS_NODE_PFAIL)) 1765 unreachable_masters++; 1766 } 1767 } 1768 dictReleaseIterator(di); 1769 } 1770 1771 /* If we can't reach at least half the masters, change the cluster state 1772 * as FAIL, as we are not even able to mark nodes as FAIL in this side 1773 * of the netsplit because of lack of majority. */ 1774 { 1775 int needed_quorum = (server.cluster->size / 2) + 1; 1776 1777 if (unreachable_masters >= needed_quorum) 1778 server.cluster->state = REDIS_CLUSTER_FAIL; 1779 } 1780 1781 /* Log a state change */ 1782 if (initial_state != server.cluster->state) 1783 redisLog(REDIS_WARNING,"Cluster state changed: %s", 1784 server.cluster->state == REDIS_CLUSTER_OK ? "ok" : "fail"); 1785 } 1786 1787 /* This function is called after the node startup in order to verify that data 1788 * loaded from disk is in agreement with the cluster configuration: 1789 * 1790 * 1) If we find keys about hash slots we have no responsibility for, the 1791 * following happens: 1792 * A) If no other node is in charge according to the current cluster 1793 * configuration, we add these slots to our node. 1794 * B) If according to our config other nodes are already in charge for 1795 * this lots, we set the slots as IMPORTING from our point of view 1796 * in order to justify we have those slots, and in order to make 1797 * redis-trib aware of the issue, so that it can try to fix it. 1798 * 2) If we find data in a DB different than DB0 we return REDIS_ERR to 1799 * signal the caller it should quit the server with an error message 1800 * or take other actions. 1801 * 1802 * The function always returns REDIS_OK even if it will try to correct 1803 * the error described in "1". However if data is found in DB different 1804 * from DB0, REDIS_ERR is returned. 1805 * 1806 * The function also uses the logging facility in order to warn the user 1807 * about desynchronizations between the data we have in memory and the 1808 * cluster configuration. */ 1809 int verifyClusterConfigWithData(void) { 1810 int j; 1811 int update_config = 0; 1812 1813 /* If this node is a slave, don't perform the check at all as we 1814 * completely depend on the replication stream. */ 1815 if (server.cluster->myself->flags & REDIS_NODE_SLAVE) return REDIS_OK; 1816 1817 /* Make sure we only have keys in DB0. */ 1818 for (j = 1; j < server.dbnum; j++) { 1819 if (dictSize(server.db[j].dict)) return REDIS_ERR; 1820 } 1821 1822 /* Check that all the slots we see populated memory have a corresponding 1823 * entry in the cluster table. Otherwise fix the table. */ 1824 for (j = 0; j < REDIS_CLUSTER_SLOTS; j++) { 1825 if (!countKeysInSlot(j)) continue; /* No keys in this slot. */ 1826 /* Check if we are assigned to this slot or if we are importing it. 1827 * In both cases check the next slot as the configuration makes 1828 * sense. */ 1829 if (server.cluster->slots[j] == server.cluster->myself || 1830 server.cluster->importing_slots_from[j] != NULL) continue; 1831 1832 /* If we are here data and cluster config don't agree, and we have 1833 * slot 'j' populated even if we are not importing it, nor we are 1834 * assigned to this slot. Fix this condition. */ 1835 1836 update_config++; 1837 /* Case A: slot is unassigned. Take responsability for it. */ 1838 if (server.cluster->slots[j] == NULL) { 1839 redisLog(REDIS_WARNING, "I've keys about slot %d that is " 1840 "unassigned. Taking responsability " 1841 "for it.",j); 1842 clusterAddSlot(server.cluster->myself,j); 1843 } else { 1844 redisLog(REDIS_WARNING, "I've keys about slot %d that is " 1845 "already assigned to a different node. " 1846 "Setting it in importing state.",j); 1847 server.cluster->importing_slots_from[j] = server.cluster->slots[j]; 1848 } 1849 } 1850 if (update_config) clusterSaveConfigOrDie(); 1851 return REDIS_OK; 1852 } 1853 1854 /* ----------------------------------------------------------------------------- 1855 * SLAVE nodes handling 1856 * -------------------------------------------------------------------------- */ 1857 1858 /* Set the specified node 'n' as master. Setup the node as a slave if 1859 * needed. */ 1860 void clusterSetMaster(clusterNode *n) { 1861 clusterNode *myself = server.cluster->myself; 1862 1863 redisAssert(n != myself); 1864 redisAssert(myself->numslots == 0); 1865 1866 if (myself->flags & REDIS_NODE_MASTER) { 1867 myself->flags &= ~REDIS_NODE_MASTER; 1868 myself->flags |= REDIS_NODE_SLAVE; 1869 } 1870 /* Clear the promoted flag anyway if we are a slave, to ensure it will 1871 * be set only when the node turns into a master because of fail over. */ 1872 myself->flags &= ~REDIS_NODE_PROMOTED; 1873 myself->slaveof = n; 1874 replicationSetMaster(n->ip, n->port); 1875 } 1876 1877 /* ----------------------------------------------------------------------------- 1878 * CLUSTER command 1879 * -------------------------------------------------------------------------- */ 1880 1881 sds clusterGenNodesDescription(void) { 1882 sds ci = sdsempty(); 1883 dictIterator *di; 1884 dictEntry *de; 1885 int j, start; 1886 1887 di = dictGetIterator(server.cluster->nodes); 1888 while((de = dictNext(di)) != NULL) { 1889 clusterNode *node = dictGetVal(de); 1890 1891 /* Node coordinates */ 1892 ci = sdscatprintf(ci,"%.40s %s:%d ", 1893 node->name, 1894 node->ip, 1895 node->port); 1896 1897 /* Flags */ 1898 if (node->flags == 0) ci = sdscat(ci,"noflags,"); 1899 if (node->flags & REDIS_NODE_MYSELF) ci = sdscat(ci,"myself,"); 1900 if (node->flags & REDIS_NODE_MASTER) ci = sdscat(ci,"master,"); 1901 if (node->flags & REDIS_NODE_SLAVE) ci = sdscat(ci,"slave,"); 1902 if (node->flags & REDIS_NODE_PFAIL) ci = sdscat(ci,"fail?,"); 1903 if (node->flags & REDIS_NODE_FAIL) ci = sdscat(ci,"fail,"); 1904 if (node->flags & REDIS_NODE_HANDSHAKE) ci =sdscat(ci,"handshake,"); 1905 if (node->flags & REDIS_NODE_NOADDR) ci = sdscat(ci,"noaddr,"); 1906 if (node->flags & REDIS_NODE_PROMOTED) ci = sdscat(ci,"promoted,"); 1907 if (ci[sdslen(ci)-1] == ',') ci[sdslen(ci)-1] = ' '; 1908 1909 /* Slave of... or just "-" */ 1910 if (node->slaveof) 1911 ci = sdscatprintf(ci,"%.40s ",node->slaveof->name); 1912 else 1913 ci = sdscatprintf(ci,"- "); 1914 1915 /* Latency from the POV of this node, link status */ 1916 ci = sdscatprintf(ci,"%ld %ld %s", 1917 (long) node->ping_sent, 1918 (long) node->pong_received, 1919 (node->link || node->flags & REDIS_NODE_MYSELF) ? 1920 "connected" : "disconnected"); 1921 1922 /* Slots served by this instance */ 1923 start = -1; 1924 for (j = 0; j < REDIS_CLUSTER_SLOTS; j++) { 1925 int bit; 1926 1927 if ((bit = clusterNodeGetSlotBit(node,j)) != 0) { 1928 if (start == -1) start = j; 1929 } 1930 if (start != -1 && (!bit || j == REDIS_CLUSTER_SLOTS-1)) { 1931 if (j == REDIS_CLUSTER_SLOTS-1) j++; 1932 1933 if (start == j-1) { 1934 ci = sdscatprintf(ci," %d",start); 1935 } else { 1936 ci = sdscatprintf(ci," %d-%d",start,j-1); 1937 } 1938 start = -1; 1939 } 1940 } 1941 1942 /* Just for MYSELF node we also dump info about slots that 1943 * we are migrating to other instances or importing from other 1944 * instances. */ 1945 if (node->flags & REDIS_NODE_MYSELF) { 1946 for (j = 0; j < REDIS_CLUSTER_SLOTS; j++) { 1947 if (server.cluster->migrating_slots_to[j]) { 1948 ci = sdscatprintf(ci," [%d->-%.40s]",j, 1949 server.cluster->migrating_slots_to[j]->name); 1950 } else if (server.cluster->importing_slots_from[j]) { 1951 ci = sdscatprintf(ci," [%d-<-%.40s]",j, 1952 server.cluster->importing_slots_from[j]->name); 1953 } 1954 } 1955 } 1956 ci = sdscatlen(ci,"\n",1); 1957 } 1958 dictReleaseIterator(di); 1959 return ci; 1960 } 1961 1962 int getSlotOrReply(redisClient *c, robj *o) { 1963 long long slot; 1964 1965 if (getLongLongFromObject(o,&slot) != REDIS_OK || 1966 slot < 0 || slot > REDIS_CLUSTER_SLOTS) 1967 { 1968 addReplyError(c,"Invalid or out of range slot"); 1969 return -1; 1970 } 1971 return (int) slot; 1972 } 1973 1974 void clusterCommand(redisClient *c) { 1975 if (server.cluster_enabled == 0) { 1976 addReplyError(c,"This instance has cluster support disabled"); 1977 return; 1978 } 1979 1980 if (!strcasecmp(c->argv[1]->ptr,"meet") && c->argc == 4) { 1981 /* CLUSTER MEET <ip> <port> */ 1982 clusterNode *n; 1983 struct sockaddr_in sa; 1984 long port; 1985 1986 /* Perform sanity checks on IP/port */ 1987 if (inet_aton(c->argv[2]->ptr,&sa.sin_addr) == 0) { 1988 addReplyError(c,"Invalid IP address in MEET"); 1989 return; 1990 } 1991 if (getLongFromObjectOrReply(c, c->argv[3], &port, NULL) != REDIS_OK || 1992 port < 0 || port > (65535-REDIS_CLUSTER_PORT_INCR)) 1993 { 1994 addReplyError(c,"Invalid TCP port specified"); 1995 return; 1996 } 1997 1998 /* Finally add the node to the cluster with a random name, this 1999 * will get fixed in the first handshake (ping/pong). */ 2000 n = createClusterNode(NULL,REDIS_NODE_HANDSHAKE|REDIS_NODE_MEET); 2001 strncpy(n->ip,inet_ntoa(sa.sin_addr),sizeof(n->ip)); 2002 n->port = port; 2003 clusterAddNode(n); 2004 addReply(c,shared.ok); 2005 } else if (!strcasecmp(c->argv[1]->ptr,"nodes") && c->argc == 2) { 2006 /* CLUSTER NODES */ 2007 robj *o; 2008 sds ci = clusterGenNodesDescription(); 2009 2010 o = createObject(REDIS_STRING,ci); 2011 addReplyBulk(c,o); 2012 decrRefCount(o); 2013 } else if (!strcasecmp(c->argv[1]->ptr,"flushslots") && c->argc == 2) { 2014 /* CLUSTER FLUSHSLOTS */ 2015 if (dictSize(server.db[0].dict) != 0) { 2016 addReplyError(c,"DB must be empty to perform CLUSTER FLUSHSLOTS."); 2017 return; 2018 } 2019 clusterDelNodeSlots(server.cluster->myself); 2020 clusterUpdateState(); 2021 clusterSaveConfigOrDie(); 2022 addReply(c,shared.ok); 2023 } else if ((!strcasecmp(c->argv[1]->ptr,"addslots") || 2024 !strcasecmp(c->argv[1]->ptr,"delslots")) && c->argc >= 3) 2025 { 2026 /* CLUSTER ADDSLOTS <slot> [slot] ... */ 2027 /* CLUSTER DELSLOTS <slot> [slot] ... */ 2028 int j, slot; 2029 unsigned char *slots = zmalloc(REDIS_CLUSTER_SLOTS); 2030 int del = !strcasecmp(c->argv[1]->ptr,"delslots"); 2031 2032 memset(slots,0,REDIS_CLUSTER_SLOTS); 2033 /* Check that all the arguments are parsable and that all the 2034 * slots are not already busy. */ 2035 for (j = 2; j < c->argc; j++) { 2036 if ((slot = getSlotOrReply(c,c->argv[j])) == -1) { 2037 zfree(slots); 2038 return; 2039 } 2040 if (del && server.cluster->slots[slot] == NULL) { 2041 addReplyErrorFormat(c,"Slot %d is already unassigned", slot); 2042 zfree(slots); 2043 return; 2044 } else if (!del && server.cluster->slots[slot]) { 2045 addReplyErrorFormat(c,"Slot %d is already busy", slot); 2046 zfree(slots); 2047 return; 2048 } 2049 if (slots[slot]++ == 1) { 2050 addReplyErrorFormat(c,"Slot %d specified multiple times", 2051 (int)slot); 2052 zfree(slots); 2053 return; 2054 } 2055 } 2056 for (j = 0; j < REDIS_CLUSTER_SLOTS; j++) { 2057 if (slots[j]) { 2058 int retval; 2059 2060 /* If this slot was set as importing we can clear this 2061 * state as now we are the real owner of the slot. */ 2062 if (server.cluster->importing_slots_from[j]) 2063 server.cluster->importing_slots_from[j] = NULL; 2064 2065 retval = del ? clusterDelSlot(j) : 2066 clusterAddSlot(server.cluster->myself,j); 2067 redisAssertWithInfo(c,NULL,retval == REDIS_OK); 2068 } 2069 } 2070 zfree(slots); 2071 clusterUpdateState(); 2072 clusterSaveConfigOrDie(); 2073 addReply(c,shared.ok); 2074 } else if (!strcasecmp(c->argv[1]->ptr,"setslot") && c->argc >= 4) { 2075 /* SETSLOT 10 MIGRATING <node ID> */ 2076 /* SETSLOT 10 IMPORTING <node ID> */ 2077 /* SETSLOT 10 STABLE */ 2078 /* SETSLOT 10 NODE <node ID> */ 2079 int slot; 2080 clusterNode *n; 2081 2082 if ((slot = getSlotOrReply(c,c->argv[2])) == -1) return; 2083 2084 if (!strcasecmp(c->argv[3]->ptr,"migrating") && c->argc == 5) { 2085 if (server.cluster->slots[slot] != server.cluster->myself) { 2086 addReplyErrorFormat(c,"I'm not the owner of hash slot %u",slot); 2087 return; 2088 } 2089 if ((n = clusterLookupNode(c->argv[4]->ptr)) == NULL) { 2090 addReplyErrorFormat(c,"I don't know about node %s", 2091 (char*)c->argv[4]->ptr); 2092 return; 2093 } 2094 server.cluster->migrating_slots_to[slot] = n; 2095 } else if (!strcasecmp(c->argv[3]->ptr,"importing") && c->argc == 5) { 2096 if (server.cluster->slots[slot] == server.cluster->myself) { 2097 addReplyErrorFormat(c, 2098 "I'm already the owner of hash slot %u",slot); 2099 return; 2100 } 2101 if ((n = clusterLookupNode(c->argv[4]->ptr)) == NULL) { 2102 addReplyErrorFormat(c,"I don't know about node %s", 2103 (char*)c->argv[3]->ptr); 2104 return; 2105 } 2106 server.cluster->importing_slots_from[slot] = n; 2107 } else if (!strcasecmp(c->argv[3]->ptr,"stable") && c->argc == 4) { 2108 /* CLUSTER SETSLOT <SLOT> STABLE */ 2109 server.cluster->importing_slots_from[slot] = NULL; 2110 server.cluster->migrating_slots_to[slot] = NULL; 2111 } else if (!strcasecmp(c->argv[3]->ptr,"node") && c->argc == 5) { 2112 /* CLUSTER SETSLOT <SLOT> NODE <NODE ID> */ 2113 clusterNode *n = clusterLookupNode(c->argv[4]->ptr); 2114 2115 if (!n) { 2116 addReplyErrorFormat(c,"Unknown node %s", 2117 (char*)c->argv[4]->ptr); 2118 return; 2119 } 2120 /* If this hash slot was served by 'myself' before to switch 2121 * make sure there are no longer local keys for this hash slot. */ 2122 if (server.cluster->slots[slot] == server.cluster->myself && 2123 n != server.cluster->myself) 2124 { 2125 if (countKeysInSlot(slot) != 0) { 2126 addReplyErrorFormat(c, "Can't assign hashslot %d to a different node while I still hold keys for this hash slot.", slot); 2127 return; 2128 } 2129 } 2130 /* If this node was the slot owner and the slot was marked as 2131 * migrating, assigning the slot to another node will clear 2132 * the migratig status. */ 2133 if (server.cluster->slots[slot] == server.cluster->myself && 2134 server.cluster->migrating_slots_to[slot]) 2135 server.cluster->migrating_slots_to[slot] = NULL; 2136 2137 /* If this node was importing this slot, assigning the slot to 2138 * itself also clears the importing status. */ 2139 if (n == server.cluster->myself && 2140 server.cluster->importing_slots_from[slot]) 2141 server.cluster->importing_slots_from[slot] = NULL; 2142 clusterDelSlot(slot); 2143 clusterAddSlot(n,slot); 2144 } else { 2145 addReplyError(c,"Invalid CLUSTER SETSLOT action or number of arguments"); 2146 return; 2147 } 2148 clusterUpdateState(); 2149 clusterSaveConfigOrDie(); 2150 addReply(c,shared.ok); 2151 } else if (!strcasecmp(c->argv[1]->ptr,"info") && c->argc == 2) { 2152 /* CLUSTER INFO */ 2153 char *statestr[] = {"ok","fail","needhelp"}; 2154 int slots_assigned = 0, slots_ok = 0, slots_pfail = 0, slots_fail = 0; 2155 int j; 2156 2157 for (j = 0; j < REDIS_CLUSTER_SLOTS; j++) { 2158 clusterNode *n = server.cluster->slots[j]; 2159 2160 if (n == NULL) continue; 2161 slots_assigned++; 2162 if (n->flags & REDIS_NODE_FAIL) { 2163 slots_fail++; 2164 } else if (n->flags & REDIS_NODE_PFAIL) { 2165 slots_pfail++; 2166 } else { 2167 slots_ok++; 2168 } 2169 } 2170 2171 sds info = sdscatprintf(sdsempty(), 2172 "cluster_state:%s\r\n" 2173 "cluster_slots_assigned:%d\r\n" 2174 "cluster_slots_ok:%d\r\n" 2175 "cluster_slots_pfail:%d\r\n" 2176 "cluster_slots_fail:%d\r\n" 2177 "cluster_known_nodes:%lu\r\n" 2178 "cluster_size:%d\r\n" 2179 , statestr[server.cluster->state], 2180 slots_assigned, 2181 slots_ok, 2182 slots_pfail, 2183 slots_fail, 2184 dictSize(server.cluster->nodes), 2185 server.cluster->size 2186 ); 2187 addReplySds(c,sdscatprintf(sdsempty(),"$%lu\r\n", 2188 (unsigned long)sdslen(info))); 2189 addReplySds(c,info); 2190 addReply(c,shared.crlf); 2191 } else if (!strcasecmp(c->argv[1]->ptr,"keyslot") && c->argc == 3) { 2192 /* CLUSTER KEYSLOT <key> */ 2193 sds key = c->argv[2]->ptr; 2194 2195 addReplyLongLong(c,keyHashSlot(key,sdslen(key))); 2196 } else if (!strcasecmp(c->argv[1]->ptr,"countkeysinslot") && c->argc == 3) { 2197 /* CLUSTER COUNTKEYSINSLOT <slot> */ 2198 long long slot; 2199 2200 if (getLongLongFromObjectOrReply(c,c->argv[2],&slot,NULL) != REDIS_OK) 2201 return; 2202 if (slot < 0 || slot >= REDIS_CLUSTER_SLOTS) { 2203 addReplyError(c,"Invalid slot"); 2204 return; 2205 } 2206 addReplyLongLong(c,countKeysInSlot(slot)); 2207 } else if (!strcasecmp(c->argv[1]->ptr,"getkeysinslot") && c->argc == 4) { 2208 /* CLUSTER GETKEYSINSLOT <slot> <count> */ 2209 long long maxkeys, slot; 2210 unsigned int numkeys, j; 2211 robj **keys; 2212 2213 if (getLongLongFromObjectOrReply(c,c->argv[2],&slot,NULL) != REDIS_OK) 2214 return; 2215 if (getLongLongFromObjectOrReply(c,c->argv[3],&maxkeys,NULL) != REDIS_OK) 2216 return; 2217 if (slot < 0 || slot >= REDIS_CLUSTER_SLOTS || maxkeys < 0) { 2218 addReplyError(c,"Invalid slot or number of keys"); 2219 return; 2220 } 2221 2222 keys = zmalloc(sizeof(robj*)*maxkeys); 2223 numkeys = getKeysInSlot(slot, keys, maxkeys); 2224 addReplyMultiBulkLen(c,numkeys); 2225 for (j = 0; j < numkeys; j++) addReplyBulk(c,keys[j]); 2226 zfree(keys); 2227 } else if (!strcasecmp(c->argv[1]->ptr,"forget") && c->argc == 3) { 2228 /* CLUSTER FORGET <NODE ID> */ 2229 clusterNode *n = clusterLookupNode(c->argv[2]->ptr); 2230 2231 if (!n) { 2232 addReplyErrorFormat(c,"Unknown node %s", (char*)c->argv[2]->ptr); 2233 return; 2234 } 2235 clusterDelNode(n); 2236 clusterUpdateState(); 2237 clusterSaveConfigOrDie(); 2238 addReply(c,shared.ok); 2239 } else if (!strcasecmp(c->argv[1]->ptr,"replicate") && c->argc == 3) { 2240 /* CLUSTER REPLICATE <NODE ID> */ 2241 clusterNode *n = clusterLookupNode(c->argv[2]->ptr); 2242 2243 /* Lookup the specified node in our table. */ 2244 if (!n) { 2245 addReplyErrorFormat(c,"Unknown node %s", (char*)c->argv[2]->ptr); 2246 return; 2247 } 2248 2249 /* I can't replicate myself. */ 2250 if (n == server.cluster->myself) { 2251 addReplyError(c,"Can't replicate myself"); 2252 return; 2253 } 2254 2255 /* Can't replicate a slave. */ 2256 if (n->slaveof != NULL) { 2257 addReplyError(c,"I can only replicate a master, not a slave."); 2258 return; 2259 } 2260 2261 /* We should have no assigned slots to accept to replicate some 2262 * other node. */ 2263 if (server.cluster->myself->numslots != 0 || 2264 dictSize(server.db[0].dict) != 0) 2265 { 2266 addReplyError(c,"To set a master the node must be empty and without assigned slots."); 2267 return; 2268 } 2269 2270 /* Set the master. */ 2271 clusterSetMaster(n); 2272 clusterUpdateState(); 2273 clusterSaveConfigOrDie(); 2274 addReply(c,shared.ok); 2275 } else { 2276 addReplyError(c,"Wrong CLUSTER subcommand or number of arguments"); 2277 } 2278 } 2279 2280 /* ----------------------------------------------------------------------------- 2281 * DUMP, RESTORE and MIGRATE commands 2282 * -------------------------------------------------------------------------- */ 2283 2284 /* Generates a DUMP-format representation of the object 'o', adding it to the 2285 * io stream pointed by 'rio'. This function can't fail. */ 2286 void createDumpPayload(rio *payload, robj *o) { 2287 unsigned char buf[2]; 2288 uint64_t crc; 2289 2290 /* Serialize the object in a RDB-like format. It consist of an object type 2291 * byte followed by the serialized object. This is understood by RESTORE. */ 2292 rioInitWithBuffer(payload,sdsempty()); 2293 redisAssert(rdbSaveObjectType(payload,o)); 2294 redisAssert(rdbSaveObject(payload,o)); 2295 2296 /* Write the footer, this is how it looks like: 2297 * ----------------+---------------------+---------------+ 2298 * ... RDB payload | 2 bytes RDB version | 8 bytes CRC64 | 2299 * ----------------+---------------------+---------------+ 2300 * RDB version and CRC are both in little endian. 2301 */ 2302 2303 /* RDB version */ 2304 buf[0] = REDIS_RDB_VERSION & 0xff; 2305 buf[1] = (REDIS_RDB_VERSION >> 8) & 0xff; 2306 payload->io.buffer.ptr = sdscatlen(payload->io.buffer.ptr,buf,2); 2307 2308 /* CRC64 */ 2309 crc = crc64(0,(unsigned char*)payload->io.buffer.ptr, 2310 sdslen(payload->io.buffer.ptr)); 2311 memrev64ifbe(&crc); 2312 payload->io.buffer.ptr = sdscatlen(payload->io.buffer.ptr,&crc,8); 2313 } 2314 2315 /* Verify that the RDB version of the dump payload matches the one of this Redis 2316 * instance and that the checksum is ok. 2317 * If the DUMP payload looks valid REDIS_OK is returned, otherwise REDIS_ERR 2318 * is returned. */ 2319 int verifyDumpPayload(unsigned char *p, size_t len) { 2320 unsigned char *footer; 2321 uint16_t rdbver; 2322 uint64_t crc; 2323 2324 /* At least 2 bytes of RDB version and 8 of CRC64 should be present. */ 2325 if (len < 10) return REDIS_ERR; 2326 footer = p+(len-10); 2327 2328 /* Verify RDB version */ 2329 rdbver = (footer[1] << 8) | footer[0]; 2330 if (rdbver != REDIS_RDB_VERSION) return REDIS_ERR; 2331 2332 /* Verify CRC64 */ 2333 crc = crc64(0,p,len-8); 2334 memrev64ifbe(&crc); 2335 return (memcmp(&crc,footer+2,8) == 0) ? REDIS_OK : REDIS_ERR; 2336 } 2337 2338 /* DUMP keyname 2339 * DUMP is actually not used by Redis Cluster but it is the obvious 2340 * complement of RESTORE and can be useful for different applications. */ 2341 void dumpCommand(redisClient *c) { 2342 robj *o, *dumpobj; 2343 rio payload; 2344 2345 /* Check if the key is here. */ 2346 if ((o = lookupKeyRead(c->db,c->argv[1])) == NULL) { 2347 addReply(c,shared.nullbulk); 2348 return; 2349 } 2350 2351 /* Create the DUMP encoded representation. */ 2352 createDumpPayload(&payload,o); 2353 2354 /* Transfer to the client */ 2355 dumpobj = createObject(REDIS_STRING,payload.io.buffer.ptr); 2356 addReplyBulk(c,dumpobj); 2357 decrRefCount(dumpobj); 2358 return; 2359 } 2360 2361 /* RESTORE key ttl serialized-value [REPLACE] */ 2362 void restoreCommand(redisClient *c) { 2363 long ttl; 2364 rio payload; 2365 int j, type, replace = 0; 2366 robj *obj; 2367 2368 /* Parse additional options */ 2369 for (j = 4; j < c->argc; j++) { 2370 if (!strcasecmp(c->argv[j]->ptr,"replace")) { 2371 replace = 1; 2372 } else { 2373 addReply(c,shared.syntaxerr); 2374 return; 2375 } 2376 } 2377 2378 /* Make sure this key does not already exist here... */ 2379 if (!replace && lookupKeyWrite(c->db,c->argv[1]) != NULL) { 2380 addReplyError(c,"Target key name is busy."); 2381 return; 2382 } 2383 2384 /* Check if the TTL value makes sense */ 2385 if (getLongFromObjectOrReply(c,c->argv[2],&ttl,NULL) != REDIS_OK) { 2386 return; 2387 } else if (ttl < 0) { 2388 addReplyError(c,"Invalid TTL value, must be >= 0"); 2389 return; 2390 } 2391 2392 /* Verify RDB version and data checksum. */ 2393 if (verifyDumpPayload(c->argv[3]->ptr,sdslen(c->argv[3]->ptr)) == REDIS_ERR) { 2394 addReplyError(c,"DUMP payload version or checksum are wrong"); 2395 return; 2396 } 2397 2398 rioInitWithBuffer(&payload,c->argv[3]->ptr); 2399 if (((type = rdbLoadObjectType(&payload)) == -1) || 2400 ((obj = rdbLoadObject(type,&payload)) == NULL)) 2401 { 2402 addReplyError(c,"Bad data format"); 2403 return; 2404 } 2405 2406 /* Remove the old key if needed. */ 2407 if (replace) dbDelete(c->db,c->argv[1]); 2408 2409 /* Create the key and set the TTL if any */ 2410 dbAdd(c->db,c->argv[1],obj); 2411 if (ttl) setExpire(c->db,c->argv[1],mstime()+ttl); 2412 signalModifiedKey(c->db,c->argv[1]); 2413 addReply(c,shared.ok); 2414 server.dirty++; 2415 } 2416 2417 /* MIGRATE socket cache implementation. 2418 * 2419 * We take a map between host:ip and a TCP socket that we used to connect 2420 * to this instance in recent time. 2421 * This sockets are closed when the max number we cache is reached, and also 2422 * in serverCron() when they are around for more than a few seconds. */ 2423 #define MIGRATE_SOCKET_CACHE_ITEMS 64 /* max num of items in the cache. */ 2424 #define MIGRATE_SOCKET_CACHE_TTL 10 /* close cached socekts after 10 sec. */ 2425 2426 typedef struct migrateCachedSocket { 2427 int fd; 2428 time_t last_use_time; 2429 } migrateCachedSocket; 2430 2431 /* Return a TCP scoket connected with the target instance, possibly returning 2432 * a cached one. 2433 * 2434 * This function is responsible of sending errors to the client if a 2435 * connection can't be established. In this case -1 is returned. 2436 * Otherwise on success the socket is returned, and the caller should not 2437 * attempt to free it after usage. 2438 * 2439 * If the caller detects an error while using the socket, migrateCloseSocket() 2440 * should be called so that the connection will be craeted from scratch 2441 * the next time. */ 2442 int migrateGetSocket(redisClient *c, robj *host, robj *port, long timeout) { 2443 int fd; 2444 sds name = sdsempty(); 2445 migrateCachedSocket *cs; 2446 2447 /* Check if we have an already cached socket for this ip:port pair. */ 2448 name = sdscatlen(name,host->ptr,sdslen(host->ptr)); 2449 name = sdscatlen(name,":",1); 2450 name = sdscatlen(name,port->ptr,sdslen(port->ptr)); 2451 cs = dictFetchValue(server.migrate_cached_sockets,name); 2452 if (cs) { 2453 sdsfree(name); 2454 cs->last_use_time = server.unixtime; 2455 return cs->fd; 2456 } 2457 2458 /* No cached socket, create one. */ 2459 if (dictSize(server.migrate_cached_sockets) == MIGRATE_SOCKET_CACHE_ITEMS) { 2460 /* Too many items, drop one at random. */ 2461 dictEntry *de = dictGetRandomKey(server.migrate_cached_sockets); 2462 cs = dictGetVal(de); 2463 close(cs->fd); 2464 zfree(cs); 2465 dictDelete(server.migrate_cached_sockets,dictGetKey(de)); 2466 } 2467 2468 /* Create the socket */ 2469 fd = anetTcpNonBlockConnect(server.neterr,c->argv[1]->ptr, 2470 atoi(c->argv[2]->ptr)); 2471 if (fd == -1) { 2472 sdsfree(name); 2473 addReplyErrorFormat(c,"Can't connect to target node: %s", 2474 server.neterr); 2475 return -1; 2476 } 2477 anetEnableTcpNoDelay(server.neterr,fd); 2478 2479 /* Check if it connects within the specified timeout. */ 2480 if ((aeWait(fd,AE_WRITABLE,timeout) & AE_WRITABLE) == 0) { 2481 sdsfree(name); 2482 addReplySds(c,sdsnew("-IOERR error or timeout connecting to the client\r\n")); 2483 close(fd); 2484 return -1; 2485 } 2486 2487 /* Add to the cache and return it to the caller. */ 2488 cs = zmalloc(sizeof(*cs)); 2489 cs->fd = fd; 2490 cs->last_use_time = server.unixtime; 2491 dictAdd(server.migrate_cached_sockets,name,cs); 2492 return fd; 2493 } 2494 2495 /* Free a migrate cached connection. */ 2496 void migrateCloseSocket(robj *host, robj *port) { 2497 sds name = sdsempty(); 2498 migrateCachedSocket *cs; 2499 2500 name = sdscatlen(name,host->ptr,sdslen(host->ptr)); 2501 name = sdscatlen(name,":",1); 2502 name = sdscatlen(name,port->ptr,sdslen(port->ptr)); 2503 cs = dictFetchValue(server.migrate_cached_sockets,name); 2504 if (!cs) { 2505 sdsfree(name); 2506 return; 2507 } 2508 2509 close(cs->fd); 2510 zfree(cs); 2511 dictDelete(server.migrate_cached_sockets,name); 2512 sdsfree(name); 2513 } 2514 2515 void migrateCloseTimedoutSockets(void) { 2516 dictIterator *di = dictGetSafeIterator(server.migrate_cached_sockets); 2517 dictEntry *de; 2518 2519 while((de = dictNext(di)) != NULL) { 2520 migrateCachedSocket *cs = dictGetVal(de); 2521 2522 if ((server.unixtime - cs->last_use_time) > MIGRATE_SOCKET_CACHE_TTL) { 2523 close(cs->fd); 2524 zfree(cs); 2525 dictDelete(server.migrate_cached_sockets,dictGetKey(de)); 2526 } 2527 } 2528 dictReleaseIterator(di); 2529 } 2530 2531 /* MIGRATE host port key dbid timeout [COPY | REPLACE] */ 2532 void migrateCommand(redisClient *c) { 2533 int fd, copy, replace, j; 2534 long timeout; 2535 long dbid; 2536 long long ttl, expireat; 2537 robj *o; 2538 rio cmd, payload; 2539 int retry_num = 0; 2540 2541 try_again: 2542 /* Initialization */ 2543 copy = 0; 2544 replace = 0; 2545 ttl = 0; 2546 2547 /* Parse additional options */ 2548 for (j = 6; j < c->argc; j++) { 2549 if (!strcasecmp(c->argv[j]->ptr,"copy")) { 2550 copy = 1; 2551 } else if (!strcasecmp(c->argv[j]->ptr,"replace")) { 2552 replace = 1; 2553 } else { 2554 addReply(c,shared.syntaxerr); 2555 return; 2556 } 2557 } 2558 2559 /* Sanity check */ 2560 if (getLongFromObjectOrReply(c,c->argv[5],&timeout,NULL) != REDIS_OK) 2561 return; 2562 if (getLongFromObjectOrReply(c,c->argv[4],&dbid,NULL) != REDIS_OK) 2563 return; 2564 if (timeout <= 0) timeout = 1000; 2565 2566 /* Check if the key is here. If not we reply with success as there is 2567 * nothing to migrate (for instance the key expired in the meantime), but 2568 * we include such information in the reply string. */ 2569 if ((o = lookupKeyRead(c->db,c->argv[3])) == NULL) { 2570 addReplySds(c,sdsnew("+NOKEY\r\n")); 2571 return; 2572 } 2573 2574 /* Connect */ 2575 fd = migrateGetSocket(c,c->argv[1],c->argv[2],timeout); 2576 if (fd == -1) return; /* error sent to the client by migrateGetSocket() */ 2577 2578 /* Create RESTORE payload and generate the protocol to call the command. */ 2579 rioInitWithBuffer(&cmd,sdsempty()); 2580 redisAssertWithInfo(c,NULL,rioWriteBulkCount(&cmd,'*',2)); 2581 redisAssertWithInfo(c,NULL,rioWriteBulkString(&cmd,"SELECT",6)); 2582 redisAssertWithInfo(c,NULL,rioWriteBulkLongLong(&cmd,dbid)); 2583 2584 expireat = getExpire(c->db,c->argv[3]); 2585 if (expireat != -1) { 2586 ttl = expireat-mstime(); 2587 if (ttl < 1) ttl = 1; 2588 } 2589 redisAssertWithInfo(c,NULL,rioWriteBulkCount(&cmd,'*',replace ? 5 : 4)); 2590 if (server.cluster_enabled) 2591 redisAssertWithInfo(c,NULL, 2592 rioWriteBulkString(&cmd,"RESTORE-ASKING",14)); 2593 else 2594 redisAssertWithInfo(c,NULL,rioWriteBulkString(&cmd,"RESTORE",7)); 2595 redisAssertWithInfo(c,NULL,c->argv[3]->encoding == REDIS_ENCODING_RAW); 2596 redisAssertWithInfo(c,NULL,rioWriteBulkString(&cmd,c->argv[3]->ptr,sdslen(c->argv[3]->ptr))); 2597 redisAssertWithInfo(c,NULL,rioWriteBulkLongLong(&cmd,ttl)); 2598 2599 /* Emit the payload argument, that is the serialized object using 2600 * the DUMP format. */ 2601 createDumpPayload(&payload,o); 2602 redisAssertWithInfo(c,NULL,rioWriteBulkString(&cmd,payload.io.buffer.ptr, 2603 sdslen(payload.io.buffer.ptr))); 2604 sdsfree(payload.io.buffer.ptr); 2605 2606 /* Add the REPLACE option to the RESTORE command if it was specified 2607 * as a MIGRATE option. */ 2608 if (replace) 2609 redisAssertWithInfo(c,NULL,rioWriteBulkString(&cmd,"REPLACE",7)); 2610 2611 /* Transfer the query to the other node in 64K chunks. */ 2612 errno = 0; 2613 { 2614 sds buf = cmd.io.buffer.ptr; 2615 size_t pos = 0, towrite; 2616 int nwritten = 0; 2617 2618 while ((towrite = sdslen(buf)-pos) > 0) { 2619 towrite = (towrite > (64*1024) ? (64*1024) : towrite); 2620 nwritten = syncWrite(fd,buf+pos,towrite,timeout); 2621 if (nwritten != (signed)towrite) goto socket_wr_err; 2622 pos += nwritten; 2623 } 2624 } 2625 2626 /* Read back the reply. */ 2627 { 2628 char buf1[1024]; 2629 char buf2[1024]; 2630 2631 /* Read the two replies */ 2632 if (syncReadLine(fd, buf1, sizeof(buf1), timeout) <= 0) 2633 goto socket_rd_err; 2634 if (syncReadLine(fd, buf2, sizeof(buf2), timeout) <= 0) 2635 goto socket_rd_err; 2636 if (buf1[0] == '-' || buf2[0] == '-') { 2637 addReplyErrorFormat(c,"Target instance replied with error: %s", 2638 (buf1[0] == '-') ? buf1+1 : buf2+1); 2639 } else { 2640 robj *aux; 2641 2642 if (!copy) { 2643 /* No COPY option: remove the local key, signal the change. */ 2644 dbDelete(c->db,c->argv[3]); 2645 signalModifiedKey(c->db,c->argv[3]); 2646 } 2647 addReply(c,shared.ok); 2648 server.dirty++; 2649 2650 /* Translate MIGRATE as DEL for replication/AOF. */ 2651 aux = createStringObject("DEL",3); 2652 rewriteClientCommandVector(c,2,aux,c->argv[3]); 2653 decrRefCount(aux); 2654 } 2655 } 2656 2657 sdsfree(cmd.io.buffer.ptr); 2658 return; 2659 2660 socket_wr_err: 2661 sdsfree(cmd.io.buffer.ptr); 2662 migrateCloseSocket(c->argv[1],c->argv[2]); 2663 if (errno != ETIMEDOUT && retry_num++ == 0) goto try_again; 2664 addReplySds(c, 2665 sdsnew("-IOERR error or timeout writing to target instance\r\n")); 2666 return; 2667 2668 socket_rd_err: 2669 sdsfree(cmd.io.buffer.ptr); 2670 migrateCloseSocket(c->argv[1],c->argv[2]); 2671 if (errno != ETIMEDOUT && retry_num++ == 0) goto try_again; 2672 addReplySds(c, 2673 sdsnew("-IOERR error or timeout reading from target node\r\n")); 2674 return; 2675 } 2676 2677 /* The ASKING command is required after a -ASK redirection. 2678 * The client should issue ASKING before to actually send the command to 2679 * the target instance. See the Redis Cluster specification for more 2680 * information. */ 2681 void askingCommand(redisClient *c) { 2682 if (server.cluster_enabled == 0) { 2683 addReplyError(c,"This instance has cluster support disabled"); 2684 return; 2685 } 2686 c->flags |= REDIS_ASKING; 2687 addReply(c,shared.ok); 2688 } 2689 2690 /* ----------------------------------------------------------------------------- 2691 * Cluster functions related to serving / redirecting clients 2692 * -------------------------------------------------------------------------- */ 2693 2694 /* Return the pointer to the cluster node that is able to serve the command. 2695 * For the function to succeed the command should only target a single 2696 * key (or the same key multiple times). 2697 * 2698 * If the returned node should be used only for this request, the *ask 2699 * integer is set to '1', otherwise to '0'. This is used in order to 2700 * let the caller know if we should reply with -MOVED or with -ASK. 2701 * 2702 * If the command contains multiple keys, and as a consequence it is not 2703 * possible to handle the request in Redis Cluster, NULL is returned. */ 2704 clusterNode *getNodeByQuery(redisClient *c, struct redisCommand *cmd, robj **argv, int argc, int *hashslot, int *ask) { 2705 clusterNode *n = NULL; 2706 robj *firstkey = NULL; 2707 multiState *ms, _ms; 2708 multiCmd mc; 2709 int i, slot = 0; 2710 2711 /* We handle all the cases as if they were EXEC commands, so we have 2712 * a common code path for everything */ 2713 if (cmd->proc == execCommand) { 2714 /* If REDIS_MULTI flag is not set EXEC is just going to return an 2715 * error. */ 2716 if (!(c->flags & REDIS_MULTI)) return server.cluster->myself; 2717 ms = &c->mstate; 2718 } else { 2719 /* In order to have a single codepath create a fake Multi State 2720 * structure if the client is not in MULTI/EXEC state, this way 2721 * we have a single codepath below. */ 2722 ms = &_ms; 2723 _ms.commands = &mc; 2724 _ms.count = 1; 2725 mc.argv = argv; 2726 mc.argc = argc; 2727 mc.cmd = cmd; 2728 } 2729 2730 /* Check that all the keys are the same key, and get the slot and 2731 * node for this key. */ 2732 for (i = 0; i < ms->count; i++) { 2733 struct redisCommand *mcmd; 2734 robj **margv; 2735 int margc, *keyindex, numkeys, j; 2736 2737 mcmd = ms->commands[i].cmd; 2738 margc = ms->commands[i].argc; 2739 margv = ms->commands[i].argv; 2740 2741 keyindex = getKeysFromCommand(mcmd,margv,margc,&numkeys, 2742 REDIS_GETKEYS_ALL); 2743 for (j = 0; j < numkeys; j++) { 2744 if (firstkey == NULL) { 2745 /* This is the first key we see. Check what is the slot 2746 * and node. */ 2747 firstkey = margv[keyindex[j]]; 2748 2749 slot = keyHashSlot((char*)firstkey->ptr, sdslen(firstkey->ptr)); 2750 n = server.cluster->slots[slot]; 2751 redisAssertWithInfo(c,firstkey,n != NULL); 2752 } else { 2753 /* If it is not the first key, make sure it is exactly 2754 * the same key as the first we saw. */ 2755 if (!equalStringObjects(firstkey,margv[keyindex[j]])) { 2756 getKeysFreeResult(keyindex); 2757 return NULL; 2758 } 2759 } 2760 } 2761 getKeysFreeResult(keyindex); 2762 } 2763 if (ask) *ask = 0; /* This is the default. Set to 1 if needed later. */ 2764 /* No key at all in command? then we can serve the request 2765 * without redirections. */ 2766 if (n == NULL) return server.cluster->myself; 2767 if (hashslot) *hashslot = slot; 2768 /* This request is about a slot we are migrating into another instance? 2769 * Then we need to check if we have the key. If we have it we can reply. 2770 * If instead is a new key, we pass the request to the node that is 2771 * receiving the slot. */ 2772 if (n == server.cluster->myself && 2773 server.cluster->migrating_slots_to[slot] != NULL) 2774 { 2775 if (lookupKeyRead(&server.db[0],firstkey) == NULL) { 2776 if (ask) *ask = 1; 2777 return server.cluster->migrating_slots_to[slot]; 2778 } 2779 } 2780 /* Handle the case in which we are receiving this hash slot from 2781 * another instance, so we'll accept the query even if in the table 2782 * it is assigned to a different node, but only if the client 2783 * issued an ASKING command before. */ 2784 if (server.cluster->importing_slots_from[slot] != NULL && 2785 (c->flags & REDIS_ASKING || cmd->flags & REDIS_CMD_ASKING)) { 2786 return server.cluster->myself; 2787 } 2788 /* It's not a -ASK case. Base case: just return the right node. */ 2789 return n; 2790 } 2791