zoukankan      html  css  js  c++  java
  • 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查询节点
  • 相关阅读:
    smdkv210
    wireshark常用过滤规则
    go json序列化不填充默认值
    refactoring.guru-重构-如何重构
    refactoring.guru--重构--何时重构
    refactoring.guru--重构--技术债务
    refactoring.guru学习记录--重构--整洁的代码
    window7下python3 编译pjsua
    go 单元测试框架介绍
    算法图解学习笔记之算法
  • 原文地址:https://www.cnblogs.com/JulianHuang/p/12687090.html
Copyright © 2011-2022 走看看