StackExchange.Redis 之 操作Redis链接字符串配置(链接Redis集群)

参考文档:

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实例关掉 (上边运行的循环代码程序不要关闭)

发现程序正常运行:

但是上边的步骤,我经过多次测试,在任意关闭某个实例的时候,偶尔会报如下错误:集群挂了

我们把写的方法注释掉,只保留读取的代码,同样会偶尔报异常。

但是大部分情况下,关掉其中一个实例,程序都正常运行:

 

posted @ 2020-03-19 16:46  找.net工作(北京)  阅读(6968)  评论(1编辑  收藏  举报