C#两大知名Redis客户端连接哨兵集群的姿势StackExchange.Redis & CSRedisCore连接Redis哨兵


C#两大知名Redis客户端连接哨兵集群的姿势

 

前言

前面利用《Docker-Compose搭建Redis高可用哨兵集群》,
我们的思路是将Redis、Sentinel、Redis Client App链接到同一个网桥网络,这个网桥内的Redis Client App就可以使用ContainerIP访问网桥内任意redis节点。

同一网桥网络访问规避了Docker上发生的NAT,端口映射的复杂性, 但实际上并不是最常规的做法(今天咱们也不说Docker host形式部署Redis-Sentinel了)。

Redis Client App独立组网遇到的问题

很多时候,Redis-Sentinel与Redis Client App独立组网,涉及Docker宿主机NAT转换和 Port映射。

Sentinel,Docker或其他形式的网络地址转换或端口映射应谨慎混合。
我实际测试发现,如果将前文Sentinel.conf中Master(ContainerIP,Port) 换成(宿主机IP,映射Port),
确实会引起混乱,无法找到正确的Slaves, 无法正常故障转移。

为了解决Redis-Sentinel在Docker环境下因为NAT,Forward Port导致的无法正确获知Slaves和正确故障转移的问题。
Redis3.2之后可以强制让Slave声明自己的(IP,Port);强制让Sentinel声明自己的(IP,Port)

 # since Redis 3.2.2, to force a replica to announce an arbitrary pair of IP and port to the master. The two configurations directives to use are: replica-announce-ip <ip> replica-announce-port <port> 

上述配置可以写在Docker Command参数指定或通过Volume redis.conf 加载进redis容器

# you can use the following two Sentinel configuration directives in order to force Sentinel to announce a specific set of IP and port: sentinel announce-ip <ip> sentinel announce-port <port> 

sentinel.conf的配置只能通过Config加载进sentinel容器。

通过明牌方式通知 所有交互对象,redis实例就是在这个(IP,Port)上发生了NAT转化,Port映射,上述搭建Docker搭建Redis-sentinel才是常规实践。

C#两大客户端访问Redis-Sentinel的方式

归根到底一张图:

  1. Redis Client先询问Sentinels,Sentinel返回Master (IP,Port)
  2. Redis Client再与以上Master (IP,Port)建立连接

Redis-Sentinel

这里我们采用Docker-compose在单机上部署了Redis-Sentinel集群,
1Master- 2 Slave- 3Sentinel,
分别占据宿主机6380、6381、6382、 26379、26380、26381端口.

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 484da8d832f1 redis "docker-entrypoint.s…" 2 hours ago Up 2 hours 6379/tcp, 0.0.0.0:26380->26379/tcp redis-sentinel-2 50599c15adba redis "docker-entrypoint.s…" 2 hours ago Up 2 hours 6379/tcp, 0.0.0.0:26379->26379/tcp redis-sentinel-1 51ce90cc52d7 redis "docker-entrypoint.s…" 2 hours ago Up 2 hours 6379/tcp, 0.0.0.0:26381->26379/tcp redis-sentinel-3 d58d6973de28 redis "docker-entrypoint.s…" 2 hours ago Up 2 hours 0.0.0.0:6381->6379/tcp redis-slave-1 b88bd85ac109 redis "docker-entrypoint.s…" 2 hours ago Up 8 seconds 0.0.0.0:6382->6379/tcp redis-slave-2 3dc26c01a90d redis "docker-entrypoint.s…" 2 hours ago Up About an hour 0.0.0.0:6380->6379/tcp redis-master 

进入任意Sentinel节点,使用sentinel master mymaster确认集群信息

添加测试键值: testKey:hello Redis-sentinel!

StackExchange.Redis & CSRedisCore连接Redis哨兵

老牌StackExchange.Redis 今年才真正支持Sentinel, Github上有关Sentinel的Issue、PR历时久远,PR像便秘一样最近才关闭。
https://github.com/StackExchange/StackExchange.Redis/pull/692#issuecomment-375298108
https://github.com/StackExchange/StackExchange.Redis/pull/1067

CSRedisCore得到真传,很早就支持了,而且编程写法更简单,清晰。

话不多说:

using StackExchange.Redis; using System; namespace ConsoleApp { class Program { static void Main(string[] args) { var sw = new Stopwatch(); sw.Start(); UseStackExchangeRedis(); sw.Stop(); Console.WriteLine("连接+查询测试key,耗时"+sw.ElapsedMilliseconds); sw.Reset(); sw.Start(); UseCSRedisCore(); sw.Stop(); Console.WriteLine("连接+查询测试key,耗时" + sw.ElapsedMilliseconds); Console.ReadKey(); } // StackExchange.Reids连接Redis-Sentinel public static void UseStackExchangeRedis() { ConfigurationOptions sentinelOptions = new ConfigurationOptions(); sentinelOptions.EndPoints.Add("180.76.*.*", 26379); sentinelOptions.EndPoints.Add("180.76.*.*", 26380); sentinelOptions.EndPoints.Add("180.76.*.*", 26381); sentinelOptions.TieBreaker = ""; sentinelOptions.CommandMap = CommandMap.Sentinel; sentinelOptions.AbortOnConnectFail = false; // Connect! ConnectionMultiplexer sentinelConnection = ConnectionMultiplexer.Connect(sentinelOptions); // Get a connection to the master ConfigurationOptions redisServiceOptions = new ConfigurationOptions(); redisServiceOptions.ServiceName = "mymaster1"; //master名称 redisServiceOptions.Password = "redis_pwd"; //master访问密码 redisServiceOptions.AbortOnConnectFail = true; ConnectionMultiplexer masterConnection = sentinelConnection.GetSentinelMasterConnection(redisServiceOptions); var db = masterConnection.GetDatabase(); var value= db.StringGet("testKey"); Console.WriteLine($"[Use StackExchange-Redis] The remote redis-sentinel test key value:{value}"); } // CSRedisCore连接Redis-Sentinel public static void UseCSRedisCore() { var csredis = new CSRedis.CSRedisClient("mymaster1,password=redis_pwd", new[] { "180.76.*.*:26379", "180.76.*.*:26380", "180.76.*.*:26381" }); var value = csredis.Get("testKey"); Console.WriteLine($"[Use CSRedisCore] The remote redis-sentinel test key value:{value}"); } } } 

执行输出:

本文长话短说,快速介绍两块C#常见的Redis客户端连接Redis哨兵集群的方式,各有千秋。
StackExchange.Redis更能体现连接的实质过程: 先查询,再连接。
CSRedisCore 小白写法,无感知。

Github地址:https://github.com/zaozaoniao/Redis-sentinel-with-docker-compose

总结输入

本文记录两个内容:

  1. Redis-Sentinel在Docker环境因NAT,Forward_Port触发的问题, 以及Redis官方给出的方案
  2. C#两个Redis客户端如何感知Redis-Sentinel的Master查询节点

如果您觉得本文对您有帮助,请点一下左下角 “推荐”按钮,您的 将是我最大的写作动力!另外您也可以选择 关注我】,可以很方便找到我!
    本文版权归作者和博客园共有,来源网址: http://www.cnblogs.com/julianhuang 欢迎各位转载,转载文章务必在文章页面显著位置给出作者和原文连接,否则保留追究法律责任的权利!


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM