Bash实践:抽样检测数据迁移至Redis集群后的数据一致性

时间:2023-03-10 06:23:29
Bash实践:抽样检测数据迁移至Redis集群后的数据一致性

熟悉了一段时间的Bash编程,因此借此任务操作一把bash编程,主要涉及到Redis单节点与Redis集群的操作

1. 任务背景

近日有个任务需要将历史的Redis(主从节点)中的数据迁移至Redis集群中。相关条件与要求如下:

(1) 历史Redis以及新的Redis集群分别部署在北京、合肥、广州三地

(2) 待迁移的Redis数据只存在合肥环境

(3) 需要从一个节点访问三地的Redis集群或历史Redis节点

(4) 待迁移的Redis中的数据量大概为2000W+

(5) 迁移完成后需抽样检测数据迁移后的准确性、以及整体数量是否匹配

2. 实现流程

(1) 网络打通

需要从合肥节点能够同时访问北京、合肥、广州三地的Redis主从或集群,因此需要打通网络。

(2) 三地Redis集群访问

打通网络后,需要访问三地的Redis集群,采用Predixy中间件分别配置访问三地,Prodixy中间件使得对Redis集群的操作,像操作Redis单节点那样简单

(3) 数据迁移

Predixy部署好之后,执行数据迁移,由于数据量较大,使用hadoop或Spark进行迁移

(4) 迁移后的验证

需要验证迁移后的数据总量是否对等、且抽样检测迁移的数据是否准确。因此编写Bash脚本,进行抽样检测。具体内容如下:

1) 抽样检测数据的一致性

#!/bin/bash

source ~/.bashrc

old_port=(  )
new_port=( ) init_pre=c_music
ip="127.0.0.1"
old_passwd="test1"
new_passwd="test2" type=$
to_check_id=$
if [ -z "$type" -o -z "$to_check_id" ];then
printf "Error paramter: <type(cr|tag|tpl|vu2sid|ao2u|vo2sid|so2u)> <to_check_id>\n"
exit
fi ## Redis集群需增加前缀,Redis主从需指定db
case "$type" in
"cr") old_db=; pre="$init_pre"_cr2sid_ ;;
"tag") old_db=; pre="$init_pre"_tg2sid_ ;;
"tpl") old_db=; pre="$init_pre"_topl_ ;;
"vu2sid") old_db=; pre="$init_pre"_vid2sid_ ;;
"ao2u") old_db=; pre="$init_pre"_al_o2u_ ;;
"vo2sid") old_db=; pre="$init_pre"_void2sid_ ;;
"so2u") old_db=; pre="$init_pre"_si_o2u_ ;;
*) "Invalid Type" && exit
esac printf "type:%s\t\tori_db:%s\t\tkey:%s\n" "$type" "$old_db" "$pre$to_check_id" ## 查找原始Redis主从的id信息
for port in ${old_port[@]}
do
ty=$(redis-cli -h $ip -p $port -n $old_db -a $old_passwd type $to_check_id)
if [ ! -z "$ty" ];then
printf "%s:%s\t\t" "$ip" "$port"
case $ty in
"list") redis-cli -h $ip -p $port -n $old_db -a $old_passwd lrange $to_check_id ; redis-cli -h $ip -p $port -n $old_db -a $old_passwd llen $to_check_id ;;
"string") redis-cli -h $ip -p $port -n $old_db -a $old_passwd get $to_check_id ;;
"hash") redis-cli -h $ip -p $port -n $old_db -a $old_passwd hgetall $to_check_id ;;
esac
break;
fi
done printf "\n" ## 查看迁移后的Redis集群中的id是否一致
for port in ${new_port[@]}
do
printf "%s:%s\t\t" "$ip" "$port"
case $ty in
"list") redis-cli -h $ip -p $port -c -a $new_passwd lrange "$pre$to_check_id" ; redis-cli -h $ip -p $port -c -a $new_passwd llen "$pre$to_check_id" ;;
"string") redis-cli -h $ip -p $port -c -a $new_passwd get "$pre$to_check_id" ;;
"hash") redis-cli -h $ip -p $port -c -a $new_passwd hgetall "$pre$to_check_id";;
esac
done 

2) 校验总量是否一致

主要使用redis-cli中的--scan参数,下面的脚本主要是提取Redis集群中指定前缀(以下脚本中前缀为c_kg_vpo2u_)的key,注意使用keys "*"命令会导致阻塞,redis中建议禁止使用。

#!/bin/bash

redis_bin=/bin
passwd="test" for ip in 127.0..{..} ## redis集群中的主节点
do
for port in {..} ## 相关的端口信息
do
echo "starting......"
$redis_bin/redis-cli -h $ip -p $port -a $passwd --scan --pattern "c_kg_vpo2u_*" >> c_kg_vpo2u.txt
echo "ending......"
done
done