参考文档:
https://blog.csdn.net/smj20170417/article/details/79928228
https://www.jianshu.com/p/0b3be884d2f5
Redis链接字符串可以提出来放到 Config文件当中:
<connectionStrings>
<add name="Connection_Redis" connectionString="127.0.0.1:6379,127.0.0.1:6380,127.0.0.1:6381,127.0.0.1:6382,password=123456,abortConnect=false" />
</connectionStrings>
当有多个Redis实例时,可以设置链接多个实例,中间用逗号分隔即可(比如:使用Redis集群)。
1 public class RedisCacheHelper
2 {
3 private readonly Logger _log = LogManager.GetCurrentClassLogger();
4
5 /// <summary>
6 /// 连接字符串
7 /// </summary>
8 private static string _connectionString;
9
10 /// <summary>
11 /// redis 连接对象
12 /// </summary>
13 private static IConnectionMultiplexer _connMultiplexer;
14
15 /// <summary>
16 /// 实例化对象
17 /// </summary>
18 private static RedisCacheHelper _cacheHelper;
19 /// <summary>
20 /// 实例
21 /// </summary>
22 private static RedisCacheHelper _instance;
23
24 /// <summary>
25 /// 锁
26 /// </summary>
27 private static readonly object Locker = new object();
28
29 /// <summary>
30 /// 数据库
31 /// </summary>
32 private IDatabase _db;
33
34
35 /// <summary>
36 /// 默认链接实例
37 /// </summary>
38 private RedisCacheHelper()
39 {
40 _connectionString = ConfigurationManager.ConnectionStrings["Connection_Redis"].ConnectionString;
41 _connMultiplexer = ConnectionMultiplexer.Connect(_connectionString);
42 //添加注册事件
43 AddRegisterEvent();
44 }
45
46 /// <summary>
47 /// 获取 Redis 连接对象
48 /// </summary>
49 private IConnectionMultiplexer Connnection
50 {
51 get
52 {
53 if (_connMultiplexer == null || !_connMultiplexer.IsConnected)
54 {
55 lock (Locker)
56 {
57 if (_connMultiplexer == null || !_connMultiplexer.IsConnected)
58 {
59 _connMultiplexer = ConnectionMultiplexer.Connect(_connectionString);
60 }
61 }
62 }
63 return _connMultiplexer;
64 }
65 }
66
67 /// <summary>
68 /// 获取指定db,默认不指定
69 /// </summary>
70 /// <param name="db"></param>
71 /// <returns></returns>
72 private IDatabase GetDatabase(int db = -1)
73 {
74 return Connnection.GetDatabase(db);
75 }
76
77 /// <summary>
78 /// 调用实例,通过该实例调用Redis
79 /// </summary>
80 public static RedisCacheHelper Instance
81 {
82 get
83 {
84 if (_cacheHelper != null) return _cacheHelper;
85 lock (Locker)
86 {
87 if (_cacheHelper != null) return _cacheHelper;
88 _cacheHelper = new RedisCacheHelper();
89 }
90 return _cacheHelper;
91 }
92 }
93
94 #region 注册事件
95
96 /// <summary>
97 /// 添加注册事件
98 /// </summary>
99 private void AddRegisterEvent()
100 {
101 _connMultiplexer.ConnectionRestored += ConnMultiplexer_ConnectionRestored;
102 _connMultiplexer.ConnectionFailed += ConnMultiplexer_ConnectionFailed;
103 _connMultiplexer.ErrorMessage += ConnMultiplexer_ErrorMessage;
104 _connMultiplexer.ConfigurationChanged += ConnMultiplexer_ConfigurationChanged;
105 _connMultiplexer.HashSlotMoved += ConnMultiplexer_HashSlotMoved;
106 _connMultiplexer.InternalError += ConnMultiplexer_InternalError;
107 _connMultiplexer.ConfigurationChangedBroadcast += ConnMultiplexer_ConfigurationChangedBroadcast;
108 }
109
110 /// <summary>
111 /// 重新配置广播时(通常意味着主从同步更改)
112 /// </summary>
113 /// <param name="sender"></param>
114 /// <param name="e"></param>
115 private void ConnMultiplexer_ConfigurationChangedBroadcast(object sender, EndPointEventArgs e)
116 {
117 _log.Info($"{nameof(ConnMultiplexer_ConfigurationChangedBroadcast)}: {e.EndPoint}");
118 }
119
120 /// <summary>
121 /// 发生内部错误时(主要用于调试)
122 /// </summary>
123 /// <param name="sender"></param>
124 /// <param name="e"></param>
125 private void ConnMultiplexer_InternalError(object sender, InternalErrorEventArgs e)
126 {
127 _log.Error($"{nameof(ConnMultiplexer_InternalError)}: {e.Exception}");
128 }
129
130 /// <summary>
131 /// 更改集群时
132 /// </summary>
133 /// <param name="sender"></param>
134 /// <param name="e"></param>
135 private void ConnMultiplexer_HashSlotMoved(object sender, HashSlotMovedEventArgs e)
136 {
137 _log.Info(
138 $"{nameof(ConnMultiplexer_HashSlotMoved)}: {nameof(e.OldEndPoint)}-{e.OldEndPoint} To {nameof(e.NewEndPoint)}-{e.NewEndPoint}");
139 }
140
141 /// <summary>
142 /// 配置更改时
143 /// </summary>
144 /// <param name="sender"></param>
145 /// <param name="e"></param>
146 private void ConnMultiplexer_ConfigurationChanged(object sender, EndPointEventArgs e)
147 {
148 _log.Info($"{nameof(ConnMultiplexer_ConfigurationChanged)}: {e.EndPoint}");
149 }
150
151 /// <summary>
152 /// 发生错误时
153 /// </summary>
154 /// <param name="sender"></param>
155 /// <param name="e"></param>
156 private void ConnMultiplexer_ErrorMessage(object sender, RedisErrorEventArgs e)
157 {
158 _log.Error($"{nameof(ConnMultiplexer_ErrorMessage)}: {e.Message}");
159 }
160
161 /// <summary>
162 /// 物理连接失败时
163 /// </summary>
164 /// <param name="sender"></param>
165 /// <param name="e"></param>
166 private void ConnMultiplexer_ConnectionFailed(object sender, ConnectionFailedEventArgs e)
167 {
168 _log.Fatal($"{nameof(ConnMultiplexer_ConnectionFailed)}: {e.Exception}");
169 }
170
171 /// <summary>
172 /// 建立物理连接时
173 /// </summary>
174 /// <param name="sender"></param>
175 /// <param name="e"></param>
176 private void ConnMultiplexer_ConnectionRestored(object sender, ConnectionFailedEventArgs e)
177 {
178 _log.Info($"{nameof(ConnMultiplexer_ConnectionRestored)}: {e.Exception}");
179 }
180
181 #endregion
182 }
以上Redis链接就配置好了,使用方式如下:首先在把集群中的主从服务都开启,3主、3从

然后在代码中进行操作验证,向缓存中插入一条数据,然后循环读写数据,循环的时候手动任意关闭Redis服务当中的 1~2个 服务器
1 while (true)
2 {
3 //设置age
4 RedisCacheHelper.Instance.Set("age", "10", new TimeSpan(0, 5, 0));
5
6 //获取age
7 var getage = RedisCacheHelper.Instance.Get("age");
8 Console.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff") + ":" + getage);
9
10 Thread.Sleep(1000); // 等待1s
11 }
成功将缓存存入到服务器当中,运行效果如下:
此时查看Redis集群,发现主从实例都有数据了,接下来我们把其中任意1个 Redis实例关掉 (上边运行的循环代码程序不要关闭)
发现程序正常运行:
但是上边的步骤,我经过多次测试,在任意关闭某个实例的时候,偶尔会报如下错误:集群挂了
我们把写的方法注释掉,只保留读取的代码,同样会偶尔报异常。
但是大部分情况下,关掉其中一个实例,程序都正常运行:
作者:PeterZhang
出处:https://www.cnblogs.com/peterzhang123
本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。