下面的扩展代码基于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

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

通过扩展redis-cli来实现在redis集群中移动槽位的更多相关文章

  1. 通过memcached来实现对tomcat集群中Session的共享策略

    近期在做一套集群的实现,实现的方案是在Linux下完成对Apache + Tomcat 负载均衡的功能. 上述功能已经实现,有需要了解的朋友可以看我另外一篇博文. Linux下Apache与Tomca ...

  2. Redis系列5:深入分析Cluster 集群模式

    Redis系列1:深刻理解高性能Redis的本质 Redis系列2:数据持久化提高可用性 Redis系列3:高可用之主从架构 Redis系列4:高可用之Sentinel(哨兵模式) 1 背景 前面我们 ...

  3. redis之(十八)redis的支持水平扩容的集群特性,以及插槽的相关操作

    [一]主从集群的缺点,客户端分片的缺点 (1)主从+哨兵的redis集群,只是做主从备份,数据冗余的一种处理.但在存储空间的扩展上还是有限制.因为集群中的节点都是存储同样的数据.单一节点的容量,就可以 ...

  4. redis 与java的连接 和集群环境下Session管理

    redis 的安装与设置开机自启(https://www.cnblogs.com/zhulina-917/p/11746993.html)  第一步: a) 搭建环境 引入 jedis jar包 co ...

  5. 使用redis进行基于shiro的session集群共享

    之前写过一篇nginx多tomcat负载均衡,主要记录了使用nginx对多个tomcat 进行负载均衡,其实进行负载均衡之前还有一个问题没有解决,那就是集群间的session共享,不然用户在登录网站之 ...

  6. Redis数据库 02事务| 持久化| 主从复制| 集群

    1. Redis事务 Redis不支持事务,此事务不是关系型数据库中的事务: Redis事务是一个单独的隔离操作:事务中的所有命令都会序列化.按顺序地执行.事务在执行的过程中,不会被其他客户端发送来的 ...

  7. Linux下redis 的部署、主从与集群

    老男孩Python全栈6期——redis--------------------------Linux 操作系统 默认的内存管理机制RSS:page cache:anno page:Linux操作系统 ...

  8. Linux--6 redis订阅发布、持久化、集群cluster、nginx入门

    一.redis发布订阅 Redis 通过 PUBLISH .SUBSCRIBE 等命令实现了订阅与发布模式. 其实从Pub/Sub的机制来看,它更像是一个广播系统,多个Subscriber可以订阅多个 ...

  9. Redis安装(单机及各类集群,阿里云)

    Redis安装(单机及各类集群,阿里云) 前言 上周,我朋友突然悄悄咪咪地指着手机上的一篇博客说,这是你的博客吧.我看了一眼,是之前发布的<Rabbit安装(单机及集群,阿里云>.我朋友很 ...

随机推荐

  1. 强化学习——如何提升样本效率 ( DeepMind 综述深度强化学习:智能体和人类相似度竟然如此高!)

    强化学习     如何提升样本效率 参考文章: https://news.html5.qq.com/article?ch=901201&tabId=0&tagId=0&docI ...

  2. Redis 主从、哨兵Sentinel、Jedis

    Redis 主从.哨兵Sentinel.Jedis 2017年02月15日 15:52:48 有且仅有 阅读数 6183 文章标签: redis主从sentineljedis 更多 分类专栏: 7/1 ...

  3. svn密码找回

    TortoiseSVN Password Decrypterhttp://www.leapbeyond.com/ric/TSvnPD/点击打开链接去这个地址下载这个,然后直接运行,就可以看到你的use ...

  4. 【神经网络与深度学习】Win10+VS2015 caffe环境搭建(极其详细)

    caffe是好用,可是配置其环境实在是太痛苦了,依赖的库很多不说,在VS上编译还各种报错,你能想象那种被一百多个红色提示所笼罩的恐惧.  且网上很多教程是VS2013环境下编译的,问人很多也说让我把1 ...

  5. 【神经网络与深度学习】【计算机视觉】Faster R-CNN

    Faster R-CNN Fast-RCNN基本实现端对端(除了proposal阶段外),下一步自然就是要把proposal阶段也用CNN实现(放到GPU上).这就出现了Faster-RCNN,一个完 ...

  6. Ant Design Vue select下拉列表设置默认值

    在项目中需要为Ant Design Vue 的 select 组件设置一个默认值,如下图所示的状态下拉选择框,默认选择全部 代码如下: <a-select v-model="query ...

  7. 【C++札记】友元

    C++封装的类增加了对类中数据成员的访问限制,从而保证了安全性.如想访问类中的私有成员需要通过类中提供的公共接口来访问,这样间接的访问方式,无疑使得程序的运行效率有所降低. 友元的提出可以使得类外的函 ...

  8. 函数的练习1——python编程从入门到实践

    8-1 消息: 编写一个名为display_message()的函数,它打印一个句子指出你在本章学的是什么.调用这个函数,确认显示的消息正确无误. def display_message(): pri ...

  9. 使用ImagesPipeline时候报错为:ModuleNotFoundError: No module named 'scrapy.contrib'

    刚开始我是这样写的: 报错为: 哈哈,经过查阅资料,其实他是存在的,接下来修改如下: 经过运行结果如下: 问题解决,哈哈哈,搞定!!!!!!!!!!!!

  10. python实战项目 — 爬取 妹子图网,保存图片到本地

    重点: 1. 用def函数 2. 使用 os.path.dirname("路径保存") , 实现每组图片保存在独立的文件夹中 方法1: import requests from l ...