Redis的slot迁移工具
时间:2022-07-23
本文章向大家介绍Redis的slot迁移工具,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
工具下载: https://github.com/eyjian/redis-tools/blob/master/move_redis_slot.sh 支持迁移已有的keys。
#!/bin/sh
# Writed by yijian on 2020/8/10
# 迁移 slot 工具,但一次只能迁移一个 slot
#
# 使用时,需要指定如下几个参数:
# 1)参数1:必选参数,用于指定被迁移的 slot
# 2)参数2:必选参数,用于指定源节点(格式为:ip:port)
# 3)参数3:必选参数,用于指定目标节点(格式为:ip:port)
# 6)参数4:可选参数,用于指定访问 redis 的密码
#
# 使用示例(将2020从10.9.12.8:1383迁移到10.9.12.9:1386):
# move_redis_slot.sh 2020 10.9.12.8:1383 10.9.12.9:1386
#
# 执行本脚本时,有两个“确认”,
# 第一个“确认”是提示参数是否正确,
# 第二个“确认”是提示是否迁移已有的keys,
# 如果输入非yes则只迁移slot,不迁移已有keys。
# 确保redis-cli可用
REDIS_CLI=${REDIS_CLI:-redis-cli}
which "$REDIS_CLI" > /dev/null 2>&1
if test $? -ne 0; then
echo "`redis-cli` not exists or not executable"
exit 1
fi
# 参数检查
if test $# -ne 3 -a $# -ne 4; then
echo -e "Usage: `basename $0` 33[1;33mslot 33[m source_node destition_node redis_password"
echo -e "Example1: `basename $0` 33[1;33m2020 33[m 127.0.0.1:6379 127.0.0.1:6380"
echo -e "Example2: `basename $0` 33[1;33m2020 33[m 127.0.0.1:6379 127.0.0.1:6380 password123456"
exit 1
fi
SLOT=$1
SRC_NODE="$2"
DEST_NODE="$3"
REDIS_PASSOWRD="$4"
# 得到指定节点的 nodeid
function get_node_id()
{
node="$1"
node_ip="`echo $node|cut -d':' -f1`"
node_port=`echo $node|cut -d':' -f2`
# 得到对应的 nodeid
$REDIS_CLI --raw --no-auth-warning -a "$REDIS_PASSOWRD"
-h $node_ip -p $node_port
CLUSTER NODES | awk -v node=$node '{if ($2==node) printf("%s",$1);}'
}
SRC_NODE_ID="`get_node_id $SRC_NODE`"
SRC_NODE_IP="`echo $SRC_NODE|cut -d':' -f1`"
SRC_NODE_PORT=`echo $SRC_NODE|cut -d':' -f2`
DEST_NODE_ID="`get_node_id $DEST_NODE`"
DEST_NODE_IP="`echo $DEST_NODE|cut -d':' -f1`"
DEST_NODE_PORT=`echo $DEST_NODE|cut -d':' -f2`
echo -e " 33[1;33mSource 33[m node: $SRC_NODE_IP:$SRC_NODE_PORT"
echo -e " 33[1;33mDestition 33[m node: $DEST_NODE_IP:$DEST_NODE_PORT"
echo -en "Confirm to continue? [ 33[1;33myes 33[m/ 33[1;33mno 33[m]"
read -r -p " " input
if test "$input" != "yes"; then
exit 1
fi
echo "........."
# 目标节点上执行 IMPORTING 操作
# 如果 $SLOT 已在目标节点,则执行时报错“ERR I'm already the owner of hash slot 1987”
echo -e " 33[1;33mImporting 33[m $SLOT from $SRC_NODE to $DEST_NODE ..."
err=`$REDIS_CLI --raw --no-auth-warning -a "$REDIS_PASSOWRD"
-h $DEST_NODE_IP -p $DEST_NODE_PORT
CLUSTER SETSLOT $SLOT IMPORTING $SRC_NODE_ID`
if test "X$err" != "XOK"; then
echo "[destition://$DEST_NODE_IP:$DEST_NODE_PORT] $err"
exit 1
fi
# 源节点上执行 MIGRATING 操作
# 如果 $SLOT 并不在源节点上,则执行时报错“ERR I'm not the owner of hash slot 1987”
echo -e " 33[1;33mMigrating 33[m $SLOT from $SRC_NODE to $DEST_NODE ..."
err=`$REDIS_CLI --raw --no-auth-warning -a "$REDIS_PASSOWRD"
-h $SRC_NODE_IP -p $SRC_NODE_PORT
CLUSTER SETSLOT $SLOT MIGRATING $DEST_NODE_ID`
if test "X$err" != "XOK"; then
echo "[source://$SRC_NODE_IP:$SRC_NODE_PORT] $err"
exit 1
fi
# 是否迁移已有的keys?
echo -en "Migrate keys in slot://$SLOT? [ 33[1;33myes 33[m/ 33[1;33mno 33[m]"
read -r -p " " input
if test "$input" = "yes"; then
first=1 # 是否第一轮keys迁移操作
batch=100 # 一次批量迁移的keys数
timeout_ms=60000 # 超时时长(单位:毫秒)
destination_db=0 # 对于redis集群,取值总是为0
num_keys=0
echo "........."
echo -e "Migrating keys in slot://$SLOT ..."
while true
do
# 在源节点上执行:
# 借助命令“CLUSTER GETKEYSINSLOT”和命令“MIGRATE”迁移已有的keys
keys="`$REDIS_CLI --raw --no-auth-warning -a '$REDIS_PASSOWRD'
-h $SRC_NODE_IP -p $SRC_NODE_PORT
CLUSTER GETKEYSINSLOT $SLOT $batch | tr 'n' ' ' | xargs`"
if test -z "$keys"; then
if test $first -eq 1; then
echo -e "No any keys to migrate in slot://$SLOT"
else
echo -e "Finished migrating all keys ($num_keys) in slot://$SLOT"
fi
break
fi
first=0
n=`echo "$keys" | tr -cd ' ' | wc -c`
num_keys=$(($num_keys + $n))
# 在源节点上执行命令“MIGRATE”迁移到目标节点
# MIGRATE returns OK on success,
# or NOKEY if no keys were found in the source instance
if test -z "$REDIS_PASSOWRD"; then
err=`$REDIS_CLI --raw
-h $SRC_NODE_IP -p $SRC_NODE_PORT
MIGRATE $DEST_NODE_IP $DEST_NODE_PORT "" $destination_db $timeout_ms
REPLACE KEYS $keys`
else
err=`$REDIS_CLI --raw --no-auth-warning -a "$REDIS_PASSOWRD"
-h $SRC_NODE_IP -p $SRC_NODE_PORT
MIGRATE $DEST_NODE_IP $DEST_NODE_PORT "" $destination_db $timeout_ms
REPLACE AUTH "$REDIS_PASSOWRD" KEYS $keys`
fi
if test "X$err" = "XNOKEY"; then
break
fi
done
fi
# 取得所有 master 节点
nodes=(`$REDIS_CLI --raw --no-auth-warning -a "$REDIS_PASSOWRD" -h $DEST_NODE_IP -p $DEST_NODE_PORT
CLUSTER NODES | awk '{if (match($3,"master")) printf("%sn",$2);}'`)
# 在所有 master 节点上执行 NODE 操作
# 实际上,只可对源节点和目标节点执行 NODE 操作,
# 新的配置会自动在集群中传播。
echo "........."
for node in ${nodes[*]}; do
node_ip="`echo $node|cut -d':' -f1`"
node_port=`echo $node|cut -d':' -f2`
echo -en "NODE: $node_ip:$node_port "
err=`$REDIS_CLI --raw --no-auth-warning -a "$REDIS_PASSOWRD"
-h $node_ip -p $node_port
CLUSTER SETSLOT $SLOT NODE $DEST_NODE_ID`
echo -e " 33[1;33m$err 33[m"
done
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 微信小程序开发实战(18):地图组件
- 教你几招,快速创建 MySQL 五百万级数据,愉快的学习各种优化技巧
- 【Pyecharts】2014-2019年高考数据可视化~
- 25.Python的循环与递归
- 26.Python文件内容的迭代
- 28.Python中对象的特性
- 如何基于jackson动态序列化指定字段
- c/c++补完计划(五): 平衡二叉树和二叉搜索树
- 【原创】Java并发编程系列30 | ThreadLocal
- c/c++补完计划(六): 语法糖lambda
- 从别人的代码中学习golang系列--03
- Flink写出数据到HBase的Sink实现
- 「MoreThanJava」Day 4:面向对象基础
- RTSP协议视频平台EasyNVR接入EasyNVS通道不显示任何数据怎么处理?
- RTSP协议视频平台EasyNVR接入视频综合管理平台EasyNVS可以自由修改配置吗?