Redis Sentinel高可用配置及C#访问

转自:https://www.cnblogs.com/madyina/p/4198768.html

本文环境如下:

操作系统:ubuntu-14.04.1-desktop-amd64

Redis:2.8.19

如果使用虚拟机则将每台的网络设置为桥接,否则他们之间能连上,局域网连不上。

系统设计如图:

image

一、安装Redis

可以参考之前文章,采用离线安装,本次以Sentinel配置为重,所以以联网安装为例。

呼出ubuntu终端,依次执行下面命令:

wget http://download.redis.io/releases/redis-2.8.19.tar.gz
tar xzf redis-2.8.19.tar.gz
cd redis-2.8.19
make

即可安装成功,4台机器依次按照相同步骤安装。

二、配置主从关系(主子关系)

本部分和Data4无关。

如上图Data1为Master机,则不用做任何配置,直接启动就行,启动命令和下面的一样,跳过。

依次进入Data2、Data3的Redis-2.8.19目录,将redis.conf文件原目录复制粘贴一份,改名为redis10.conf、redis11.conf(就当是为了怕配置坏而备份吧),然后打开这个配置文件找到主从配置项,配置成如下:

slaveof 192.168.1.9 6379

注意将前面的#去掉。

然后依次启动3个服务,新开一个终端,启动命令如:

cd redis-2.8.19
src/redis-server redis.conf

其他机器为:

src/redis-server redis10.conf

然后在Master上面再次新开一个终端,存入Key/value数据:

cd redis-2.8.19
src/redis-cli
set name zhangsan
get name

如果能看到”zhangsan”则成功,然后依次到各Slave机器上打开终端键入:

get name

同样应该能看到”zhangsan”

相反如果键入

set name lisi

则会报错。

原因是:Master-Slave模式只有主可以读写,然后分发给各个从机,从机只能读,不能写。由此可以实现读写分离和备份。

三、配置Sentinel

Data4至此还未动过,进入redis-2.8.19目录,新建一个文本文件,名为SentinelMaster.conf,内容为(只有这几行,再没其他的了):

复制代码
复制代码
port 6379
logfile log.log
#master1
sentinel monitor master1 192.168.9.18 6379 1
sentinel down-after-milliseconds master1 5000
sentinel failover-timeout master1 900000
sentinel can-failover master1 yes
sentinel parallel-syncs master1 2
复制代码
复制代码

以上配置说明如下:

monitor :表示监控哪个Master主机。

down-after-milliseconds:是当一个sentinel在以毫秒为单位的时间段内无法达到一个实例时(或者实例不答复PINGs亦或者答复错误)它就认为实例已经关闭所需要的时间值。

can-failover用来决定一个sentinel是否在实例处于objectively down状态时启动故障转移。你可以配置所有的Sentinels执行故障切换,如果需要的话,你还可以配置为只用几个哨兵达成协议,另一些实际负责执行故障转移。

parallel-syncs 选项指定了在执行故障转移时, 最多可以有多少个从服务器同时对新的主服务器进行同步, 这个数字越小, 完成故障转移所需的时间就越长,但越大就意味着越多的从服务器因为复制而不可用。可以通过将这个值设为 1 来保证每次只有一个从服务器处于不能处理命令请求的状态。

然后启动Sentinel:

cd redis-2.8.19
src/redis-sentinel SentinelMaster.conf

然后打开日志文件即可看到已经连上主机并且已经获取到从机信息。

四、模拟故障转移:

在Data1上新开一个终端,键入:

cd redis-2.8.19
src/redis-cli
shutdown

查看服务启动终端或者日志最后一行应该是bye bye说明下线成功。

然后,在Data2和Data3上面分别写入和读出一个Key/Value测试出哪个成为新的主机,然后去Data4的日志中去对照即可。

当Data1重新启动之后就成为一个新的Slave而不再是Master了。

五、使用C#连接集群一(csredis)

本例使用csredis这个客户端,自从某个开源客户端商业化之后,浪费了不少时间寻找新的全功能客户端(至少要支持Sentinel)。

思路是先连接Sentinel获取在线服务地址和端口号,然后只读操作连接Slave,增删改操作连接Master即可。获取Sentinel信息的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
public class RedisManager
   {
       /// <summary>
       /// redis配置文件信息
       /// </summary>
       private static string[] RediswritePath = null;
       private static string[] RedisReadPath = null;
       private static PooledRedisClientManager _prcm;
       /// <summary>
       /// 静态构造方法,初始化链接池管理对象
       /// </summary>
       static RedisManager()
       {
           using (var sentinel = new RedisSentinelClient("192.168.148.131", 26379))
           {              
               var master = sentinel.Master("mymaster");//得到主机器信息 
               
               Console.WriteLine("master:" + master);
               var slave = sentinel.Slaves("mymaster");
               RediswritePath = new string[] { master.Ip + ":" + master.Port };
               RedisReadPath = new string[slave.Length];
               int i = 0;
               foreach (var item in slave)
               {
                   RedisReadPath[i] = item.Ip + ":" + item.Port;
                   i++;              
               }
           }
 
           CreateManager();
       }
       /// <summary>
       /// 创建链接池管理对象
       /// </summary>
       private static void CreateManager()
       {
           _prcm = CreateManager(RediswritePath, RedisReadPath);
       }
       private static PooledRedisClientManager CreateManager(string[] readWriteHosts, string[] readOnlyHosts)
       {
           return new PooledRedisClientManager(readWriteHosts, readOnlyHosts, new RedisClientManagerConfig
           {
               MaxWritePoolSize = 5000, // “写”链接池链接数
               MaxReadPoolSize = 5000, // “读”链接池链接数
               AutoStart = true,
           });
       }
       private static IEnumerable<string> SplitString(string strSource, string split)
       {
           return strSource.Split(split.ToArray());
       }
       /// <summary>
       /// 客户端缓存操作对象
       /// </summary>
       public static ServiceStack.Redis.IRedisClient GetClient()
       {
           if (_prcm == null)
           {
               CreateManager();
           }
           return _prcm.GetClient();
       }
 
   }

调用方式

  using (IRedisClient Redis = RedisManager.GetClient())

  {
    List<string> tts = Redis.Get<List<string>>($"dianxin{i}");
    Console.WriteLine(i);
  }

 

 

六、使用C#连接集群二(ServiceStack.Redis)

推荐使用这种方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
public class redistest
   {
       private static IRedisClientsManager redisManager = GetRedisSentinel();
       private static IRedisClientsManager GetRedisSentinel()
       {
           IRedisClientsManager redisManager = null;
 
           try
           {
               List<string> listSentinels = new List<string>();
               listSentinels.Add("192.168.148.131:26379");//sentinel地址1
               listSentinels.Add("192.168.148.132:26379");// 地址2
               listSentinels.Add("192.168.148.133:26379");// 地址3  集群可做负载 或者高可用
 
               RedisSentinel redisSentinel = new RedisSentinel(listSentinels, "mymaster");
               redisSentinel.SentinelWorkerConnectTimeoutMs = 500;
               redisManager = redisSentinel.Start();
           }
           catch (Exception ex)
           {
 
           }
 
           return redisManager;
       }
 
       public static object GetRedisCache<T>(string key)
       {
           object myObject = null;
 
           //naming convention [PLATFORM]:[PROJECT]:[FUNCTION]:[PARAMETERS…]
           string redisKey = key;
           //Open Redis
           if (redisManager != null)
           {
               try
               {
                   using (RedisClient redis = (RedisClient)redisManager.GetClient())
                   {
                       redis.Get<T>(redisKey);
                   }
               }
               catch (Exception ex)
               {
                   throw;
               }
           }
 
 
           return myObject;
       }
 
       public static int SaveRedisCache(string myObject, string key, DateTime? expireDateTime = null)
       {
           if (expireDateTime == null)
               expireDateTime = DateTime.Now.AddMinutes(20);
 
           //naming convention [PLATFORM]:[PROJECT]:[FUNCTION]:[PARAMETERS…]
           string redisKey = key;
 
           if (myObject != null)
           {             
 
               if (redisManager != null)
               {
                   try
                   {
                       using (RedisClient redis = (RedisClient)redisManager.GetClient())
                       {
                           bool b= redis.Set(redisKey, myObject, (DateTime)expireDateTime);
                       }
                       return 0;
                   }
                   catch (Exception ex)
                   {
                       return -1;
                       throw;
                   }
               }
           }
 
 
           return -1;
       }     
   }

 调用方式

1
2
int b = redistest.SaveRedisCache(value, $"yuyu{k}");
var yu = redistest.GetRedisCache<string>($"yuyu{k}");

ps aux | grep redis

src/redis-cli -h 127.0.0.1 -p 6000 shutdown

 

posted @   steven.木子  阅读(1480)  评论(0编辑  收藏  举报
(评论功能已被禁用)
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示