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的方式
归根到底一张图:

- Redis Client先询问Sentinels,Sentinel返回Master (IP,Port)
- 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
总结输入
本文记录两个内容:
- Redis-Sentinel在Docker环境因NAT,Forward_Port触发的问题, 以及Redis官方给出的方案
- C#两个Redis客户端如何感知Redis-Sentinel的Master查询节点
C#两大知名Redis客户端连接哨兵集群的姿势的更多相关文章
- 阿里云ECS部署Redis主备哨兵集群遇到的问题
一.部署 详细部署步骤:https://blog.csdn.net/lihongtai/article/details/82826809 Redis5.0版本需要注意的参数配置:https://www ...
- redis系列--深入哨兵集群
一.前言 在之前的系列文章中介绍了redis的入门.持久化以及复制功能,如果不了解请移步至redis系列进行阅读,当然我也是抱着学习的知识分享,如果有什么问题欢迎指正,也欢迎大家转载.而本次将介绍哨兵 ...
- Redis集合 安装 哨兵集群 配置
redis相关 redis基础 redis发布订阅 redis持久化RDB与AOF redis不重启,切换RDB备份到AOF备份 redis安全配置 redis主从同步 redis哨兵集群 redis ...
- 客户端连接Codis集群
新建maven webapp项目 添加相关依赖: <dependency> <groupId>redis.clients</groupId> <artifac ...
- Java客户端连接kafka集群报错
往kafka集群发送消息时,报错如下: page_visits-1: 30005 ms has passed since batch creation plus linger time 加入log4j ...
- SpringCloud之客户端连接Eureka集群
客户端分别yml: ###服务启动端口号 server: port: 8002 ###服务名称(服务注册到eureka名称) spring: application: name: app-toov5- ...
- Redis Sentinel哨兵集群
Redis Sentinel(哨兵集群)是一种高可用的redis部署方案.在集群中的redis-master服务挂掉时,无需人为干预,即可通过哨兵集群的自我调整,实现redis服务的持续可用. 哨兵集 ...
- redis基础之redis-cluster(集群)(七)
前言 redis的主流高可用集群模式为redis-cluster.从redis3.0+版本后开始支持,自带集群管理工具redis-trib.rb. 安装redis 参考:https://www.cnb ...
- docker搭建redis主从集群和sentinel哨兵集群,springboot客户端连接
花了两天搭建redis主从集群和sentinel哨兵集群,讲一下springboot客户端连接测试情况 redis主从集群 从网上查看说是有两种方式:一种是指定配置文件,一种是不指定配置文件 引用地址 ...
随机推荐
- 服务发现组件之 — Eureka
前言 现在流行的微服务体系结构正在改变我们构建应用程序的方式,从单一的单体服务转变为越来越小的可单独部署的服务(称为微服务),共同构成了我们的应用程序.当进行一个业务时不可避免就会存在多个服务之间调用 ...
- net core天马行空系列:移植Feign,结合Polly,实现回退,熔断,重试,超时,做最好用的声明式http服务调用端
系列目录 1.net core天马行空系列:原生DI+AOP实现spring boot注解式编程 2.net core天马行空系列: 泛型仓储和声明式事物实现最优雅的crud操作 3.net core ...
- PDIUSBD12指令
PDIUSBD12指令 端点描述 PDIUSBD12的端点适用于不同类型的设备,端点可通过[Set mode]命令配置为4种不同的模式,分别为: 模式0(NON-ISO模式):非同步模式 模式1(IS ...
- Django 配置使用日志
一. Django中使用日志 Django中使用日志其实非常简单,只需要在项目使用的配置文件中(如果没有自定义,那么就是settings.py中)加以下设置即可,同时可以根据自己的需求进行修改: # ...
- C语言结构体实现类似C++的构造函数
其主要依靠函数指针来实现,具体看代码吧~ #include <stdio.h> #include <stdlib.h> #include <string.h> ty ...
- [Docker7]Harbor
harbor download harbor offline tar package wget https://github.com/vmware/harbor/releases/download/v ...
- 题解 P2755 【洗牌问题】
这是本人的第一篇题解 请多多宽恕 这一道题其实不要用数组 我们来观察一下n=3时的情况: 原: 1 2 3 4 5 6 4 1 5 2 6 3 2 4 6 1 3 5 1 2 3 4 5 6 我们去观 ...
- Magento2(麦进斗) docker 安装
Magento 介绍 Magento(麦进斗)是一套专业开源的电子商务系统,采用php进行开发,使用Zend Framework框架.Magento设计得非常灵活,具有模块化架构体系和丰富的功能.易于 ...
- javascript正则表达式入门先了解这些
前言 此内容由学习<JavaScript正则表达式迷你书(1.1版)>整理而来(于2020年3月30日看完).此外还参考了MDN上关于Regex和String的相关内容,还有ECMAScr ...
- AC自动机(初步学习)
一开始讲AC自动机就是在字典树上做一个KMP,吓得我感觉好难,不过了解了以后,感觉也就是有点难度,不吓人. 它只是在字典树上用了KMP的思想 典型问题:给n个模式串和一个文本串,问有多少个模式串在文本 ...