问题描述
当使用Azure Redis服务时,需要把一个Redis服务的数据导入到另一个Redis上,因为Redis服务没有使用高级版,所以不支持直接导入/导出RDB文件。
以编程方式来读取数据并写入到新的Redis服务端,使用开源工具 Redis-Copy 却遇见了 6379 端口无法连接的问题。而用 redis-cli.exe 却正常连接。
redis-copy 工具使用 6379 端口
redis-copy.exe
--se xxxxx.redis.cache.chinacloudapi.cn --sa <your source password> --sp 6379 --sssl false
--de xxxxx.redis.cache.chinacloudapi.cn --da <your destination password> --dp 6379 --dssl false
报错:
- UnableToConnect on xxxxxxxx.redis.cache.chinacloudapi.cn:6379/Interactive
- No connection is available to service this operation
-
It was not possible to connect to the redis server.
Redis-cli.exe 工具使用 6379 端口,正常连接
redis-cli.exe -h yourcachename.redis.cache.chinacloudapi.cn -p 6379 -a YourAccessKey
那么,这是什么情况呢?如何才能正确使用 redis-copy.exe 工具呢?
问题解答
根据 redis-cli.exe 工具的验证,Redis服务器的 6379端口在同一个客户端机器上,是可以正常连接的。那么问题就需要转移到 redis-copy.exe 的这个开源工具上来研究了。
第一步:去 github 上下载 redis-copy的源码:https://github.com/deepakverma/redis-copy
第二步:本地Visual Studio 工具打开后,把启动指令后面携带的参数填入Debug Start options中
第三步:调试代码,发现问题根源是SSL的参数值依旧为True,而端口为 6379。 用SSL的方式去链接非SSL端口,这就是问题的根源。
问题出现在 CommandLine.Parser.Default.ParseArguments<Options>(args) 这句代码上,经过反复实现,发现CommandLine在转换 bool 类型的时候,只要携带了这个参数,不管内容是什么,都会被转换为 true
第四步:解决办法
最快的解决办法 ---- 使用6380端口连接
redis-copy.exe --se xxxxx.redis.cache.chinacloudapi.cn --sa <your source password> --sp 6380
--de xxxxx.redis.cache.chinacloudapi.cn --da <your destination password> --dp 6380
修改Redis-Copy源码 ---- 解决SSL赋值问题
[主要]方案一:在Options.cs 文件中,修改 SourceSSL 和 DestinationSSL 的默认值为False。当需要使用6380端口连接时,携带 --sssl , --dssl参数
[Option("sssl", Required = false, Default = false, HelpText = "Connect Source over ssl" )] public bool SourceSSL { get; set; }
... ...
[Option("dssl", Required = false, Default = false, HelpText = "Destination Source over ssl" )] public bool DestinationSSL { get; set; }
修改代码,重新编译exe文件后。
使用6379端口的命令为: redis-copy.exe --se xxxx --sa **** --sp 6379 --de xxxx --da **** --dp 6379
使用6380端口的命令为: redis-copy.exe --se xxxx --sa **** --sp 6380 --sssl true --de xxxx --da **** --dp 6380 --dssl true
[其他]方案二:在Options.cs 文件中,修改 SourceSSL 和 DestinationSSL 的类型为String,然后再初始化Redis连接字符串的时候转换为bool类型。
[Option("sssl", Required = false, Default = true, HelpText = "Connect Source over ssl" )] public string SourceSSL { get; set; }
... ...
[Option("dssl", Required = false, Default = true, HelpText = "Destination Source over ssl" )] public string DestinationSSL { get; set; }
.... ....
ConfigurationOptions configsource = new ConfigurationOptions();
configsource.Ssl =Convert.ToBoolean(options.SourceSSL);
configsource.Password = options.SourcePassword;
configsource.AllowAdmin = true;
configsource.SyncTimeout = 60000; // increasing timeout for source for SCAN command
sourcecon = GetConnectionMultiplexer(options.SourceEndpoint, options.SourcePort, configsource);
... ...
ConfigurationOptions configdestination = new ConfigurationOptions();
configdestination.Ssl = Convert.ToBoolean(options.DestinationSSL);
configdestination.Password = options.DestinationPassword;
configdestination.AllowAdmin = true;
destcon = GetConnectionMultiplexer(options.DestinationEndpoint, options.DestinationPort, configdestination);
参考资料
以编程方式迁移 : https://docs.azure.cn/zh-cn/azure-cache-for-redis/cache-migration-guide#migrate-programmatically
使用 Redis 命令行工具进行连接: https://docs.azure.cn/zh-cn/azure-cache-for-redis/cache-how-to-redis-cli-tool#connect-using-the-redis-command-line-tool
redis-copy : https://github.com/deepakverma/redis-copy
当在复杂的环境中面临问题,格物之道需:浊而静之徐清,安以动之徐生。 云中,恰是如此!