Browse Source

Redsis数据库迁移

v3
超级管理员 2 years ago
parent
commit
441180a038
  1. 24
      src/api/system/redis/api.ts
  2. 17
      src/api/system/redis/types.ts
  3. 2
      src/views/dashboard/index.vue
  4. 2
      src/views/knowledge/knowledge/components/KnowledgeContent.vue
  5. 373
      src/views/redismanage/datamigration/index.vue

24
src/api/system/redis/api.ts

@ -0,0 +1,24 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import {
redisConfing,
copyRedisDatabase
} from './types';
//测试Redis数据库链接
export const testRedisLink = (data: redisConfing):any => {
return request({
url: '/systemapi/redis/testRedisLink',
method: 'post',
data: data
})
}
//迁移Redis数据库
export const moveOldRedisToNewRedis = (data: copyRedisDatabase):any => {
return request({
url: '/systemapi/redis/moveOldRedisToNewRedis',
method: 'post',
data: data
})
}

17
src/api/system/redis/types.ts

@ -0,0 +1,17 @@
export interface redisConfing {
ip: string;
port: number;
pwd: string;
state: number;
}
//Redis数据及含有的键数量
export interface redisKeysNumber {
dbName:number;
dbNumber:number;
}
//迁移Redis数据库参数
export interface copyRedisDatabase {
originRedis:redisConfing;
targetRedis:redisConfing;
dblist:Number[];
}

2
src/views/dashboard/index.vue

@ -51,7 +51,7 @@ onMounted(() => {
drawerWidht.value = masterBody.value?.clientWidth
getOrgList();
console.log("热门新闻----100---->",drawerWidht.value)
// console.log("----100---->",drawerWidht.value)
})
</script>
<template>

2
src/views/knowledge/knowledge/components/KnowledgeContent.vue

@ -57,7 +57,7 @@ onMounted(() => {
<template>
<el-dialog v-model="boxShow" class="dialogStyle" :show-close="true">
<template #header="{ close, titleId, titleClass }">
<template #header="{ titleId, titleClass }">
<div class="my-header">
<h4 :id="titleId" :class="titleClass" style="margin-top: 5px;">{{ props.contentSource?.gTitle }}</h4>
<!-- <h4 :id="titleId" :class="titleClass" style="margin-top: 5px;">{{ props.contentSource?.gContent }}</h4> -->

373
src/views/redismanage/datamigration/index.vue

@ -0,0 +1,373 @@
<!--
@ 作者: 秦东
@ 时间: 2023-11-13 10:44:48
@ 备注: Redis数据迁移
-->
<script lang='ts' setup>
import { Eleme } from '@element-plus/icons-vue'
import { redisConfing,redisKeysNumber } from '@/api/system/redis/types'
import { testRedisLink,moveOldRedisToNewRedis } from '@/api/system/redis/api'
const svg = `
<path class="path" d="
M 30 15
L 28 17
M 25.61 25.61
A 15 15, 0, 0, 1, 15 30
A 15 15, 0, 1, 1, 27.99 7.5
L 15 15
" style="stroke-width: 4px; fill: rgba(0, 0, 0, 0)"/>
`
const originConfig = reactive<redisConfing>({
ip:"127.0.0.1",
port:6379,
pwd:"",
state:0
})
const targetConfig = reactive<redisConfing>({
ip:"127.0.0.1",
port:6379,
pwd:"",
state:0
})
const originTestLoad = ref(false); //
const originTextType = ref<string>("info")
const originDbNumber = ref<number>(0)
const originCheckList = ref<number[]>([])
const originKeyList = reactive<redisKeysNumber[]>([])
//Redis
const originTestLink = () =>{
originTestLoad.value=true
originConfig.port = originConfig.port*1
originConfig.state = originConfig.state*1
testRedisLink(originConfig)
.then((data:any)=>{
if(data.data.isTrue){
if(data.data.isTrue == 1){
originConfig.state = 1
originTextType.value = "success"
}else{
originConfig.state = 2
originTextType.value = "danger"
}
}else{
originConfig.state = 2
}
if(data.data.dbNumber){
originDbNumber.value = data.data.dbNumber
}
originKeyList.splice(0,originKeyList.length);
if(data.data.redisList && data.data.redisList.length > 0){
data.data.redisList.forEach((item:any)=>{
originKeyList.push({
dbName: item.dbName,
dbNumber: item.dbNumber
})
})
}
// console.log("Redis",originConfig,originKeyList)
})
.finally(()=>{
originTestLoad.value=false
})
}
const targetTestLoad = ref(false); //
const targetTextType = ref<string>("info")
const targetDbNumber = ref<number>(1)
const targetKeyList = reactive<redisKeysNumber[]>([])
//Redis
const targetTestLink = () =>{
targetTestLoad.value=true
targetConfig.port = targetConfig.port*1
targetConfig.state = targetConfig.state*1
testRedisLink(targetConfig)
.then((data:any)=>{
if(data.data.isTrue){
if(data.data.isTrue == 1){
targetConfig.state = 1
targetTextType.value = "success"
}else{
targetConfig.state = 2
targetTextType.value = "danger"
}
}else{
targetConfig.state = 2
}
// targetDbNumber.value = new Array
if(data.data.dbNumber){
targetDbNumber.value = data.data.dbNumber
}
targetKeyList.splice(0,targetKeyList.length);
if(data.data.redisList && data.data.redisList.length > 0){
data.data.redisList.forEach((item:any)=>{
targetKeyList.push({
dbName: item.dbName,
dbNumber: item.dbNumber
})
})
}
})
.finally(()=>{
targetTestLoad.value=false
})
}
//
const migrateLoad = ref(false)
const logList = ref<any[]>([])
const migrateRedisInfo = () =>{
migrateLoad.value = true
if(originConfig.state != 1){
migrateLoad.value = false;
ElMessageBox({
title: '温馨提示!',
// message: "Redis",
message:h('p', null, [
h('span', null, '您未进行'),
h('span', { style: 'color: #ff0000' }, '源Redis连通性测试!'),
h('span', null, '为确保迁移正常进行,请先测试一下'),
h('span', { style: 'color: #ff0000' }, '是否可以连通!'),
])
})
return
}
if(targetConfig.state != 1){
migrateLoad.value = false;
ElMessageBox({
title: '温馨提示!',
// message: "Redis",
message:h('p', null, [
h('span', null, '您未进行'),
h('span', { style: 'color: #ff0000' }, '目标Redis连通性测试!'),
h('span', null, '为确保迁移正常进行,请先测试一下'),
h('span', { style: 'color: #ff0000' }, '是否可以连通!'),
])
})
return
}
if(targetConfig.ip == originConfig.ip && targetConfig.port == originConfig.port){
migrateLoad.value = false;
ElMessageBox({
title: '温馨提示!',
// message: "Redis",
message:h('p', null, [
h('span', { style: 'color: #ff0000' }, '源Redis与目标Redis相同!'),
h('span', null, '不能进行迁移!'),
])
})
return
}
let sendInfo = {
originRedis:originConfig, //
targetRedis:targetConfig, //
dblist:originCheckList.value //
}
moveOldRedisToNewRedis(sendInfo)
.then((data)=>{
console.log("进行源Redis连接测试",data)
logList.value = data.data
})
.finally(()=>{
migrateLoad.value = false;
})
}
</script>
<template>
<div class="app-main body_cont">
<table border="1" class="table_body">
<tr>
<td rowspan="4" width="10%" align="center">源Redsi</td>
<td width="35%">
<table border="0">
<tr>
<td width="60">IP地址</td>
<td><el-input v-model="originConfig.ip" clearable placeholder="请输入Redis源IP"></el-input></td>
</tr>
</table>
</td>
<td rowspan="4" colspan="2" width="10%" align="center">
<el-button :loading-icon="Eleme" :loading="migrateLoad" type="primary" style="width:100%" @click="migrateRedisInfo">迁移</el-button>
</td>
<td width="35%">
<table border="0">
<tr>
<td width="60">IP地址</td>
<td><el-input v-model="targetConfig.ip" clearable placeholder="请输入Redis源IP"></el-input></td>
</tr>
</table>
</td>
<td rowspan="4" width="10%" align="center">目标Redis</td>
</tr>
<tr>
<td>
<table border="0">
<tr>
<td width="60">端口</td>
<td><el-input v-model="originConfig.port" type="number" clearable placeholder="请输入Redis源IP"></el-input></td>
</tr>
</table>
</td>
<td>
<table border="0">
<tr>
<td width="60">端口</td>
<td><el-input v-model="targetConfig.port" type="number" clearable placeholder="请输入Redis源IP"></el-input></td>
</tr>
</table>
</td>
</tr>
<tr>
<td>
<table border="0">
<tr>
<td width="60">密码</td>
<td><el-input v-model="originConfig.pwd" type="password" show-password clearable placeholder="请输入Redis源IP"></el-input></td>
</tr>
</table>
</td>
<td>
<table border="0">
<tr>
<td width="60">密码</td>
<td><el-input v-model="targetConfig.pwd" type="password" show-password clearable placeholder="请输入Redis源IP"></el-input></td>
</tr>
</table>
</td>
</tr>
<tr>
<td>
<table border="0">
<tr>
<td width="50">
<el-button :loading-icon="Eleme" :loading="originTestLoad" type="primary" @click="originTestLink">测试链接</el-button>
</td>
<td align="right">
<el-text class="mx-1" :type="originTextType">
<i v-if="originConfig.state == 1" class="fa fa-check"></i>
<i v-else-if="originConfig.state == 2" class="fa fa-close"></i>
<span v-else>未测试</span>
</el-text>
</td>
</tr>
</table>
</td>
<td>
<table border="0">
<tr>
<td align="left">
<el-text class="mx-1" :type="targetTextType">
<i v-if="targetConfig.state == 1" class="fa fa-check"></i>
<i v-else-if="targetConfig.state == 2" class="fa fa-close"></i>
<span v-else>未测试</span>
</el-text>
</td>
<td width="50">
<el-button :loading-icon="Eleme" :loading="targetTestLoad" type="primary" @click="targetTestLink">测试链接</el-button>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td valign="top" align="center">数据库列表</td>
<td valign="top" colspan="2" class="min_td_height" width="40%" style="table-layout:fixed">
<el-checkbox-group v-model="originCheckList">
<el-row :gutter="10">
<el-col v-for="(item,index) in originKeyList" :key="index" :span="6" class="row_col_body">
<el-checkbox :label="item.dbName" border size="small">DB{{item.dbName}}(Keys:{{item.dbNumber}})</el-checkbox>
</el-col>
</el-row>
</el-checkbox-group>
</td>
<td valign="top" colspan="2" class="min_td_height" width="40%" style="table-layout:fixed">
<el-row :gutter="10">
<el-col v-for="(item,index) in targetKeyList" :key="index" :span="6" class="row_col_body">
<el-button size="small">DB{{item.dbName}}(Keys:{{item.dbNumber}})</el-button>
</el-col>
</el-row>
</td>
<td valign="top" align="center">数据库列表</td>
</tr>
<tr>
<td valign="top" align="center">处理结果</td>
<td colspan="5" valign="top">
<div
v-loading="migrateLoad"
element-loading-text="Loading..."
:element-loading-spinner="svg"
element-loading-svg-view-box="-10, -10, 50, 50"
element-loading-background="rgba(122, 122, 122, 0.8)"
class="chuli_jieguo"
>
<div v-for="(item,index) in logList" :key="index" class="text_width">
<el-text type="warning" >开始迁移Rdis:{{ item.dbName }}</el-text>
<el-text v-for="(logCont,lgindex) in item.msgList" :key="lgindex" :type="logCont.state==1?'success':'warning'" >{{ logCont.keys }}{{ logCont.msg }}</el-text>
<el-text type="primary" >Rdis:{{ item.dbName }}库迁移完成</el-text>
</div>
</div>
</td>
</tr>
</table>
</div>
</template>
<style lang='scss' scoped>
.body_cont{
padding:20px;
}
.table_body{
background-color: #FFFFFF;
width:100%;
border-collapse: collapse;
/*
* 设置边框
*/
td,th {
border: 1px solid black;
padding: 5px;
table{
width:100%;
td,th{
border: 0px solid black;
padding: 0px;
}
}
}
}
.left_border{
border-left: 1px solid black;
}
.min_td_height{
height:150px;
}
.chuli_jieguo{
height: calc(100vh - 480px);
overflow: hidden;
overflow-y: auto;
}
.checkbox_group{
max-width:300px;
}
.row_col_body{
margin-top:10px;
}
.text_width{
border-bottom: 1px solid #EEEEEE;
padding:5px 0;
span {
display: block;
width: 100%;
margin-top: 5px;
}
}
</style>
Loading…
Cancel
Save