- clone https://github.com/LuBu0505/redis-copy-net8.git
- {
- "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
- }
- 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 <******************>
- 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()}");
- }
- }
- }
- 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();
- }
- }
- 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;
- }
- }