下面的扩展代码基于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, ,
"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 == ); char *to_ip = NULL, *from_ip = NULL;
int to_port = , from_port = ;
if (!getClusterHostFromCmdArgs(, argv + , &to_ip, &to_port))
goto invalid_args;
if (!getClusterHostFromCmdArgs(, argv, &from_ip, &from_port))
goto invalid_args;
char *end = NULL;
char *slotStr = argv[];
int slotNo = strtol(slotStr, &end, );
if ((size_t)(end - slotStr) != strlen(slotStr)) {
clusterManagerLogErr("*** the slotNo should be number.\n");
return ;
}
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, )) return ; clusterManagerCheckCluster();
if (cluster_manager.errors && listLength(cluster_manager.errors) > ) {
fflush(stdout);
fprintf(stderr,
"*** Please fix your cluster problems before moving slot\n");
return ;
} 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 ;
} else if (!tonode || (tonode->flags & CLUSTER_MANAGER_FLAG_SLAVE)) {
clusterManagerLogErr(invalid_node_msg, to_ip, to_port);
return ;
} 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 ;
} // check fromnode has the slot
if (slotNo < || 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 ;
} else if (fromnode->slots[slotNo] == (uint8_t)()) {
clusterManagerLogErr("*** From node don't have the slot: %d\n", slotNo);
return ;
} 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 ;
}

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

(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

如果有什么好的建议或者提议,欢迎提出。

最新文章

  1. 問題排查:F5啟動偵錯後所提示的錯誤 (2)
  2. 北邮新生排位赛1解题报告d-e
  3. MySQL之选择字段数据类型
  4. &quot;Could not load type &#39;System.Runtime.CompilerServices.ExtensionAttribute&#39; from assembly &#39;mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b7
  5. [翻译][MVC 5 + EF 6] 8:更新相关数据
  6. UVALive 5111 Soccer Teams (动态规划)
  7. ios的Ping++支付接入步骤-b
  8. 动画原理——绘制正弦函数&amp;环绕运动&amp;椭圆运动
  9. tcpdump使用技巧
  10. 设置DIV根据内容自动调整高度的三个方法
  11. JS的组成部分、引入页面的方法以及命名规范
  12. (转)Awsome Domain-Adaptation
  13. 《剑指offer》第六十四题(求1+2+…+n)
  14. 58-63用ssh远程连接linux系统
  15. final评论2
  16. 使用Beetle简单构建聊天室程序
  17. [AWS vs Azure] 云计算里AWS和Azure的探究(4)
  18. SpringBoot2 上传文件 上传多文件
  19. python的list()列表数据类型的方法详解
  20. 计算机作业(HTML简单框架网页制作) 物联网 王罗红

热门文章

  1. 进行编译时提示&#39;error: unrecognized command line option &quot;-std=gnu11&quot;&#39;如何处理?
  2. 前台页面long类型数字被四舍五入的解决办法
  3. Appium 退出和启动
  4. Linux开机报错,提示根目录有错误,无法通过检测进入系统
  5. Centos7.3使用脚本自动静默安装oracle11.2.0.4数据库
  6. 解决ScrollView嵌套百度地图滑动冲突
  7. python的进修之路
  8. 关于最火爆的服务器Tomcat你真的了解吗?
  9. 21 javaweb开发--bug调试技巧
  10. ES6新增的一些特性