通過擴展redis-cli來實現在redis集群中移動槽位


下面的擴展代碼基於redis 5.0.2進行擴展, 對於其他的redis版本, 我沒有進行相關的測試。考慮到redis集群的修改頻率,這段代碼應該同時適用於其他的redis版本。

下面為修改的代碼:

static clusterManagerNode *clusterManagerByIpPort(const char* ip, int port);
static
int clusterManagerCommandMoveSlot(int argc, char **argv);
{"move-slot", clusterManagerCommandMoveSlot, 3,
"from-host:from-port to-host:to-port slotNo", NULL},
// 根據ip和端口號來獲取對應的redis集群節點
clusterManagerNode *clusterManagerByIpPort(const char* ip, int port) { if (cluster_manager.nodes == NULL) return NULL; clusterManagerNode *found = NULL; sds lcip = sdsempty(); lcip = sdscpy(lcip, ip); sdstolower(lcip); listIter li; listNode *ln; listRewind(cluster_manager.nodes, &li); while ((ln = listNext(&li)) != NULL) { clusterManagerNode *n = ln->value; if (n->ip && !sdscmp(n->ip, lcip) && (n->port == port)) { found = n; break; } } sdsfree(lcip); return found; }
// 在redis集群中實現移動槽位功能
static
int clusterManagerCommandMoveSlot(int argc, char **argv) { assert(argc == 3); char *to_ip = NULL, *from_ip = NULL; int to_port = 0, from_port = 0; if (!getClusterHostFromCmdArgs(1, argv + 1, &to_ip, &to_port)) goto invalid_args; if (!getClusterHostFromCmdArgs(1, argv, &from_ip, &from_port)) goto invalid_args; char *end = NULL; char *slotStr = argv[2]; int slotNo = strtol(slotStr, &end, 10); if ((size_t)(end - slotStr) != strlen(slotStr)) { clusterManagerLogErr("*** the slotNo should be number.\n"); return 0; } clusterManagerLogInfo("Moving slot number: %d from node %s:%d to node %s:%d\n", slotNo, from_ip, from_port, to_ip, to_port); clusterManagerNode *tonode = clusterManagerNewNode(to_ip, to_port); if (!clusterManagerLoadInfoFromNode(tonode, 0)) return 0; clusterManagerCheckCluster(0); if (cluster_manager.errors && listLength(cluster_manager.errors) > 0) { fflush(stdout); fprintf(stderr, "*** Please fix your cluster problems before moving slot\n"); return 0; } clusterManagerNode *fromnode = clusterManagerByIpPort(from_ip, from_port); // check fromnode and tonode is valid const char *invalid_node_msg = "*** The specified node (%s:%d) is not known " "or not a master, please retry.\n"; if (!fromnode || (fromnode->flags & CLUSTER_MANAGER_FLAG_SLAVE)) { clusterManagerLogErr(invalid_node_msg, from_ip, from_port); return 0; } else if (!tonode || (tonode->flags & CLUSTER_MANAGER_FLAG_SLAVE)) { clusterManagerLogErr(invalid_node_msg, to_ip, to_port); return 0; } else if (!strcmp(fromnode->name, tonode->name) && (fromnode->port == tonode->port)){ clusterManagerLogErr( "*** It is not possible to use " "the target node as " "source node.\n"); return 0; } // check fromnode has the slot if (slotNo < 0 || slotNo >= CLUSTER_MANAGER_SLOTS) { // Don't give a range hint for using it when someone is familiar with redis clusterManagerLogErr("*** The slotNo is invalid, slotNo: %d\n", slotNo); return 0; } else if (fromnode->slots[slotNo] == (uint8_t)(0)) { clusterManagerLogErr("*** From node don't have the slot: %d\n", slotNo); return 0; } int opts = CLUSTER_MANAGER_OPT_VERBOSE | CLUSTER_MANAGER_OPT_UPDATE; char *err = NULL; int result = clusterManagerMoveSlot(fromnode, tonode, slotNo, opts, &err); if (!result) { if (err != NULL) { //clusterManagerLogErr("\n%s\n", err); zfree(err); } } else { clusterManagerLogInfo("Moving finished with success.\n"); } return result; invalid_args: fprintf(stderr, CLUSTER_MANAGER_INVALID_HOST_ARG); return 0; }

上述代碼, 就是新增的在集群中移動槽位的功能, 使用方法如下:

(1)在redis-cli.c文件中添加上述代碼

(2)在redis根目錄調用make命令, 編譯代碼

(3)對編譯生成的redis-cli執行如下的命令:

  $ src/redis-cli --cluster help

其中的move-slot from-host:from-port to-host:to-port slotNo就是新增的子命令。假設192.168.5.1:6379分配了槽位0-5460,192.168.5.2:6379分配了槽位5461-10922,192.168.5.3:6379分配了槽位10923-16383, 通過調用src/redis-cli --cluster move-slot 192.168.5.1:6379 192.168.5.2:6379 10,這樣192.168.5.1:6379當前擁有槽位0-9,11-5460,而192.168.5.2:6379擁有槽位10,5461-10922。

對於redis5.0.2的redis-cli.c文件的修改后的文件可以參考:

https://github.com/ss-torres/redis-cli-addition.git

如果有什么好的建議或者提議,歡迎提出。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM