首页 > 数据库 >【Azure Developer】一个复制Redis Key到另一个Redis服务的工具(redis_copy_net8)

【Azure Developer】一个复制Redis Key到另一个Redis服务的工具(redis_copy_net8)

时间:2024-07-11 20:29:44浏览次数:13  
标签:Key -- Redis redis key var

介绍一个简单的工具,用于将Redis数据从一个redis端点复制到另一个redis端点,基于原始存储库转换为.NET 8:https://github.com/LuBu0505/redis-copy-net8

 

Redis Copy .NET8

Redis Copy 控制台工具允许将 Redis 数据从一个 Redis 服务端复制到另一个。

 Note: 不支持redis集群

 

软件要求

运行 Redis Copy 工具需要以下软件。它可能会在其他版本上运行.

  • .NET 8
  • VS Code / Visual Studio 2022

下载源代码

clone https://github.com/LuBu0505/redis-copy-net8.git

 

使用方式

选项 1 -- 使用 AppSetting.json

将“< ... >”替换为真实的redis端点

{
  "SourceRedisConnectionString": "<source redis name>:6380,password=<your password>,ssl=True,abortConnect=False", //Source Redis ConnectionString
  "DestRedisConnectionString": "<Destination redis name>:6380,password=<your password>,ssl=True,abortConnect=False" //Destination Redis ConnectionString
}

 

选项 2 -- 使用命令参数

redis-copy-net8.exe
Parameter Description:
  --se           Required. SourceEndpoint *.redis.cache.windows.net
  --sa           Required. Source password
  --sp           (Default: 6380) Source port
  --sssl         (Default: true) Connect Source over ssl

  --de           Required. DestinationEndpoint *.redis.cache.windows.net
  --da           Required. Destination Password
  --dp           (Default: 6380) Destination port
  --dssl         (Default: true) Destination Source over ssl
  --help         Display this help screen.
  --version      Display version information.

eg:

redis-copy-net8.exe --se <xxxxxx.redis.cache.chinacloudapi.cn> --sa <******************> --de <xxxxxx.redis.cache.chinacloudapi.cn> --da <******************> 

 

Redis Copy 工具的工作流程

第 1 阶段:准备Redis源和目标信息

  • 使用 StackExchange.Redis ConnectionMultiplexer 类,默认创建20个连接。
  • 检查源redis的Used Memory、Keyspace信息
  • 根据Keys数量拆分成更多子任务
            var infoGroup = sourcecon.BasicRetryInfo((conn) => conn.GetServer(conn.GetEndPoints()[0]).Info());

            foreach (var info in infoGroup)
            {
                if (info.Key.Equals("Memory"))
                {
                    Console.WriteLine($"==\t# {info.Key}");
                    var lists = info.ToList().Where(i => i.Key.Equals("used_memory_human") || i.Key.Equals("maxmemory_human")).ToList();
                    foreach (var list in lists)
                        Console.WriteLine($"==\t  {list.ToString()}");
                }

                if (info.Key.Equals("Keyspace"))
                {
                    Console.WriteLine($"==\t# {info.Key}");
                    foreach (var list in info.ToList())
                    {
                        long dbindex, dbkeys = 0;

                        long.TryParse(Regex.Match(list.Key, @"\d+\.*\d*").Value, out dbindex);
                        long.TryParse(list.Value.Split(new char[] { ',' })[0].Split(new char[] { '=' })[1], out dbkeys);

                        dictdbIdxKeysNum[dbindex] = dbkeys;

                        totalKeysSource += dbkeys;

                        Console.WriteLine($"==\t  {list.ToString()}");
                    }
                }
            }

 

第二阶段:复制

  • 循环执行复制Redis Keys的子任务,SCAN列出所有Keys。
  • 创建更多子任务以使用 StackExchange.Redis bacth 操作进行 TTL,验证Key是否过期,DUMP出Key的byte[]信息
  • 使用批量操作将Key恢复到目标Redis
  • 如果遇到异常,则将Key信息添加到失败队列中。
  • 检查移动的keys的进度,同时检查失败的队列,如果不为空,将重新运行移动任务
 var allkeys = sourcecon.BasicRetryInfo((conn) => conn.GetServer(conn.GetEndPoints()[0]).Keys(dbindex).Skip(skipKeys).Take(takeKeys)).ToArray();
var sourcedb = sourcecon.GetConection().GetDatabase(dbindex);
 var destdb = destcon.GetConection().GetDatabase(dbindex);

 foreach (var keys in SplitKeys(allkeys))
 {
     var rbatch = sourcedb.CreateBatch();
     var ttltask = new List<Task<TimeSpan?>>();
     var dumptask = new List<Task<byte[]?>>();
     foreach (var key in keys)
     {
         ttltask.Add(rbatch.KeyTimeToLiveAsync(key));

         dumptask.Add(rbatch.KeyDumpAsync(key));
     }
     rbatch.Execute();

     var ttlResults = Task.WhenAll(ttltask).Result;
     var dumpkResults = Task.WhenAll(dumptask).Result;

     //Restore the key to destation DB.
     var destBatch = destdb.CreateBatch();

     var i = 0;
     foreach (var key in keys)
     {
         destBatch.KeyRestoreAsync(key, dumpkResults[i], ttlResults[i]);
         i++;
     }
     destBatch.Execute();

     //Random select one key to verify in Phase 3. 
     if (keys.Count() > 0)
     {
         int index = RandomNumberGenerator.GetInt32(keys.Count());
         verifiedKeys.Add((dbindex, keys.ElementAt<RedisKey>(index).ToString()));
     }


     lock (lockObject)
     {
         totalKeysCopied += keys.Count();
     }
 }

 

第三阶段:验证

  • 随机选取某个key, 一个一个的检查他们的值在两个Redis服务器之间是否相同
            foreach (var key in verifiedKeys)
            {
                try
                {
                    var sourdump = await sourcecon.BasicRetryInfo(async (sc) => sc.GetDatabase(key.Item1).KeyDumpAsync(key.Item2));
                    var destdump = await destcon.BasicRetryInfo(async (sc) => sc.GetDatabase(key.Item1).KeyDumpAsync(key.Item2));

                    if (!sourdump.Result.SequenceEqual(destdump.Result))
                    {
                        Console.Write($"\n");
                        Console.WriteLine($"== {key} Verify Failed");
                    }
                    else
                    {
                        Console.Write($"{key}, ");
                    }
                }
                catch (Exception ex)
                {
                    Console.BackgroundColor = ConsoleColor.Red;
                    Console.WriteLine($"=={DateTime.Now.ToLocalTime()} Verify {key} failed ({ex.Message})");
                    Console.BackgroundColor = ConsoleColor.Black;
                }
            }

 

测试结果

Copied 369886 keys(812MB) from Redis1 to Redis2 in 233 seconds

 

 

 

标签:Key,--,Redis,redis,key,var
From: https://www.cnblogs.com/lulight/p/18297088

相关文章

  • AutoHotKey自动热键(五)添加WINDOWS秘笈指令-输入瞬间启动功能
    在AUTOHOTKEY的使用中,不仅仅可以监听组合热键,还可以监听正常文本击键录入,这是另一种监听方式,比如依次击键jsq之后直接弹出<计算器>工具,或者依次击键sj之后直接输出135****5564的手机号码,等等,这就是autohotkey的录入击键监听,以双冒号为开头::因这种录入监听像极了......
  • Redis高可用之持久化、主从复制
    一、Redis高可用策略概述持久化持久化是最简单的高可用方法,主要作用是数据备份,即将数据存储在硬盘,保证数据不会因进程退出而丢失。主从复制主从复制是高可用Redis的基础,主要实现了数据的多机备份,以及对于读操作的负载均衡和简单的故障恢复哨兵在主从复制的基础上,......
  • NoSQL之Redis配置与优化
    目录NoSQL之Redis配置与优化一、关系数据库和非关系数据库1.关系型数据库2.非关系型数据库3.非关系型数据库产生背景4.关系型数据库和非关系型数据库的区别4.1数据存储方式不同4.2扩展方式不同4.3对事务性的支持不同5.总结二、Redis的基础概念1.Redis简介2.Red......
  • redis
    一、redis概述(一)什么是redis?        Redis(RemoteDictionaryServer)是一个开源的、基于内存的、可选持久化的日志型Key-Value数据库编写,支持网络操作,并提供多种语言的API。Redis支持多种数据结构,包括字符串(string)、列表(list)、集合(set)、有序集合(zset)和哈希(hash),并且这......
  • Redis实现延迟任务
    @DatapublicclassTaskimplementsSerializable{/***任务id*/privateLongtaskId;/***类型*/privateIntegertaskType;/***优先级*/privateIntegerpriority;/***执行id*/......
  • Redis中设置增量缓存,减少对数据库的交互查询;启动@Async;异步线程
    //当属于这个分支的报文传入调用processMessage方法if((newJSONObject(dataMessage).optString("documentStatus")).equals("carWeizi_redis_service")){processMessage(dataMessage);}//processMessage中先把增量数据插入数据库,同时缓存redispublic......
  • RedisTemplate 中序列化方式辨析
    在SpringDataRedis中,RedisTemplate是操作Redis的核心类,它提供了丰富的API来与Redis进行交互。由于Redis是一个键值存储系统,它存储的是字节序列,因此在使用RedisTemplate时,需要指定键(Key)和值(Value)的序列化方式。不同的序列化方式适用于不同的场景。下面将详细介绍几种序列......
  • redis 5 安装配置以及脚本
     redis6.2安装配置以及脚本(147)  wgethttp://download.redis.io/releases/redis-6.2.14.tar.gz tar-xfredis-5.0.10.tar.gz-C/usr/local/ cd/usr/local/redis-5.0.10&&make ...... vimredis.conf daemonizeyesbind127.0.0.1192.168.1.252 ......
  • 实战篇——SSRF漏洞Redis反弹shell实战
    实战篇——SSRF漏洞Redis反弹shell实战SSRF之Redis实战上一章中利用file伪协议实现了内网的主机探测,发现存在192.168.118.151,对其进行端口探测:可见开放了6379端口,结合响应判断为Redis服务。而Redis存在未授权访问漏洞,可以利用该漏洞实现信息泄露、数据删除以及反弹shell,下面......
  • redis-benchmark压力测试
    01测试-redis-benchmark压力测试redis自带有redis-benchmark工具做压力测试,经常用来测试新版本,新特性对基准测试性能的影响。参数场景变化下的性能状况。主要参数: -h<hostname>   服务器地址(default127.0.0.1) -p<port>     端口(default6379) -s<so......