deles 发表于 2017-12-21 20:33:11

redis的安装、启动、主从配置,以及.Net下StackExchange.Redis的使用

1   public static>
2   {  

3         private static string Constr = "";  

4  
5         private static object _locker = new Object();
  

6         private static ConnectionMultiplexer _instance = null;  

7  
8         /// <summary>
  
9         /// 使用一个静态属性来返回已连接的实例,如下列中所示。这样,一旦 ConnectionMultiplexer 断开连接,便可以初始化新的连接实例。
  
10         /// </summary>
  
11         public static ConnectionMultiplexer Instance
  
12         {
  
13             get
  
14             {
  
15               if(Constr.Length == 0)
  
16               {
  
17                     throw new Exception("连接字符串为设置!");
  
18               }
  
19               if (_instance == null)
  
20               {
  
21                     lock (_locker)
  
22                     {
  
23                         if (_instance == null || !_instance.IsConnected)
  
24                         {
  
25                           _instance = ConnectionMultiplexer.Connect(Constr);
  
26                         }
  
27                     }
  
28               }
  
29               //注册如下事件
  
30               _instance.ConnectionFailed += MuxerConnectionFailed;
  
31               _instance.ConnectionRestored += MuxerConnectionRestored;
  
32               _instance.ErrorMessage += MuxerErrorMessage;
  
33               _instance.ConfigurationChanged += MuxerConfigurationChanged;
  
34               _instance.HashSlotMoved += MuxerHashSlotMoved;
  
35               _instance.InternalError += MuxerInternalError;
  
36               return _instance;
  
37             }
  
38         }
  
39
  
40         static StackExchangeRedisHelper()
  
41         {
  
42         }
  
43
  
44         public static void SetCon(string config)
  
45         {
  
46             Constr = config;
  
47         }
  
48
  
49         /// <summary>
  
50         ///
  
51         /// </summary>
  
52         /// <returns></returns>

  
53         public static>  
54         {
  
55             return Instance.GetDatabase();
  
56         }
  
57
  
58         /// <summary>
  
59         /// 这里的 MergeKey 用来拼接 Key 的前缀,具体不同的业务模块使用不同的前缀。
  
60         /// </summary>
  
61         /// <param name="key"></param>
  
62         /// <returns></returns>
  
63         private static string MergeKey(string key)
  
64         {
  
65             return key;
  
66             //return BaseSystemInfo.SystemCode + key;
  
67         }
  
68
  
69         /// <summary>
  
70         /// 根据key获取缓存对象
  
71         /// </summary>
  
72         /// <typeparam name="T"></typeparam>
  
73         /// <param name="key"></param>
  
74         /// <returns></returns>
  
75         public static T Get<T>(string key)
  
76         {
  
77             key = MergeKey(key);
  
78             return Deserialize<T>(GetDatabase().StringGet(key));
  
79         }
  
80
  
81         /// <summary>
  
82         /// 根据key获取缓存对象
  
83         /// </summary>
  
84         /// <param name="key"></param>
  
85         /// <returns></returns>
  
86         public static object Get(string key)
  
87         {
  
88             key = MergeKey(key);
  
89             return Deserialize<object>(GetDatabase().StringGet(key));
  
90         }
  
91
  
92         /// <summary>
  
93         /// 设置缓存
  
94         /// </summary>
  
95         /// <param name="key"></param>
  
96         /// <param name="value"></param>
  
97         /// <param name="expireMinutes"></param>
  
98         public static void Set(string key, object value, int expireMinutes = 0)
  
99         {
  
100             key = MergeKey(key);
  
101             if (expireMinutes > 0)
  
102             {
  
103               GetDatabase().StringSet(key, Serialize(value), TimeSpan.FromMinutes(expireMinutes));
  
104             }
  
105             else
  
106             {
  
107               GetDatabase().StringSet(key, Serialize(value));
  
108             }
  
109            
  
110         }
  
111
  
112         /// <summary>
  
113         /// 判断在缓存中是否存在该key的缓存数据
  
114         /// </summary>
  
115         /// <param name="key"></param>
  
116         /// <returns></returns>
  
117         public static bool Exists(string key)
  
118         {
  
119             key = MergeKey(key);
  
120             return GetDatabase().KeyExists(key); //可直接调用
  
121         }
  
122
  
123         /// <summary>
  
124         /// 移除指定key的缓存
  
125         /// </summary>
  
126         /// <param name="key"></param>
  
127         /// <returns></returns>
  
128         public static bool Remove(string key)
  
129         {
  
130             key = MergeKey(key);
  
131             return GetDatabase().KeyDelete(key);
  
132         }
  
133
  
134         /// <summary>
  
135         /// 异步设置
  
136         /// </summary>
  
137         /// <param name="key"></param>
  
138         /// <param name="value"></param>
  
139         public static async Task SetAsync(string key, object value)
  
140         {
  
141             key = MergeKey(key);
  
142             await GetDatabase().StringSetAsync(key, Serialize(value));
  
143         }
  
144
  
145         /// <summary>
  
146         /// 根据key获取缓存对象
  
147         /// </summary>
  
148         /// <param name="key"></param>
  
149         /// <returns></returns>
  
150         public static async Task<object> GetAsync(string key)
  
151         {
  
152             key = MergeKey(key);
  
153             object value = await GetDatabase().StringGetAsync(key);
  
154             return value;
  
155         }
  
156
  
157         /// <summary>
  
158         /// 实现递增
  
159         /// </summary>
  
160         /// <param name="key"></param>
  
161         /// <returns></returns>
  
162         public static long Increment(string key)
  
163         {
  
164             key = MergeKey(key);
  
165             //三种命令模式
  
166             //Sync,同步模式会直接阻塞调用者,但是显然不会阻塞其他线程。
  
167             //Async,异步模式直接走的是Task模型。
  
168             //Fire - and - Forget,就是发送命令,然后完全不关心最终什么时候完成命令操作。
  
169             //即发即弃:通过配置 CommandFlags 来实现即发即弃功能,在该实例中该方法会立即返回,如果是string则返回null 如果是int则返回0.这个操作将会继续在后台运行,一个典型的用法页面计数器的实现:
  
170             return GetDatabase().StringIncrement(key, flags: CommandFlags.FireAndForget);
  
171         }
  
172
  
173         /// <summary>
  
174         /// 实现递减
  
175         /// </summary>
  
176         /// <param name="key"></param>
  
177         /// <param name="value"></param>
  
178         /// <returns></returns>
  
179         public static long Decrement(string key, string value)
  
180         {
  
181             key = MergeKey(key);
  
182             return GetDatabase().HashDecrement(key, value, flags: CommandFlags.FireAndForget);
  
183         }
  
184
  
185         /// <summary>
  
186         /// 序列化对象
  
187         /// </summary>
  
188         /// <param name="o"></param>
  
189         /// <returns></returns>
  
190         private static byte[] Serialize(object o)
  
191         {
  
192             if (o == null)
  
193             {
  
194               return null;
  
195             }
  
196             BinaryFormatter binaryFormatter = new BinaryFormatter();
  
197             using (MemoryStream memoryStream = new MemoryStream())
  
198             {
  
199               binaryFormatter.Serialize(memoryStream, o);
  
200               byte[] objectDataAsStream = memoryStream.ToArray();
  
201               return objectDataAsStream;
  
202             }
  
203         }
  
204
  
205         /// <summary>
  
206         /// 反序列化对象
  
207         /// </summary>
  
208         /// <typeparam name="T"></typeparam>
  
209         /// <param name="stream"></param>
  
210         /// <returns></returns>
  
211         private static T Deserialize<T>(byte[] stream)
  
212         {
  
213             if (stream == null)
  
214             {
  
215               return default(T);
  
216             }
  
217             BinaryFormatter binaryFormatter = new BinaryFormatter();
  
218             using (MemoryStream memoryStream = new MemoryStream(stream))
  
219             {
  
220               T result = (T) binaryFormatter.Deserialize(memoryStream);
  
221               return result;
  
222             }
  
223         }
  
224
  
225         /// <summary>
  
226         /// 配置更改时
  
227         /// </summary>
  
228         /// <param name="sender"></param>
  
229         /// <param name="e"></param>
  
230         private static void MuxerConfigurationChanged(object sender, EndPointEventArgs e)
  
231         {
  
232             //LogHelper.SafeLogMessage("Configuration changed: " + e.EndPoint);
  
233         }
  
234
  
235         /// <summary>
  
236         /// 发生错误时
  
237         /// </summary>
  
238         /// <param name="sender"></param>
  
239         /// <param name="e"></param>
  
240         private static void MuxerErrorMessage(object sender, RedisErrorEventArgs e)
  
241         {
  
242             //LogHelper.SafeLogMessage("ErrorMessage: " + e.Message);
  
243         }
  
244
  
245         /// <summary>
  
246         /// 重新建立连接之前的错误
  
247         /// </summary>
  
248         /// <param name="sender"></param>
  
249         /// <param name="e"></param>
  
250         private static void MuxerConnectionRestored(object sender, ConnectionFailedEventArgs e)
  
251         {
  
252             //LogHelper.SafeLogMessage("ConnectionRestored: " + e.EndPoint);
  
253         }
  
254
  
255         /// <summary>
  
256         /// 连接失败 , 如果重新连接成功你将不会收到这个通知
  
257         /// </summary>
  
258         /// <param name="sender"></param>
  
259         /// <param name="e"></param>
  
260         private static void MuxerConnectionFailed(object sender, ConnectionFailedEventArgs e)
  
261         {
  
262             //LogHelper.SafeLogMessage("重新连接:Endpoint failed: " + e.EndPoint + ", " + e.FailureType +(e.Exception == null ? "" : (", " + e.Exception.Message)));
  
263         }
  
264
  
265         /// <summary>
  
266         /// 更改集群
  
267         /// </summary>
  
268         /// <param name="sender"></param>
  
269         /// <param name="e"></param>
  
270         private static void MuxerHashSlotMoved(object sender, HashSlotMovedEventArgs e)
  
271         {
  
272             //LogHelper.SafeLogMessage("HashSlotMoved:NewEndPoint" + e.NewEndPoint + ", OldEndPoint" + e.OldEndPoint);
  
273         }
  
274
  
275         /// <summary>
  
276         /// redis类库错误
  
277         /// </summary>
  
278         /// <param name="sender"></param>
  
279         /// <param name="e"></param>
  
280         private static void MuxerInternalError(object sender, InternalErrorEventArgs e)
  
281         {
  
282             //LogHelper.SafeLogMessage("InternalError:Message" + e.Exception.Message);
  
283         }
  
284
  
285         //场景不一样,选择的模式便会不一样,大家可以按照自己系统架构情况合理选择长连接还是Lazy。
  
286         //建立连接后,通过调用ConnectionMultiplexer.GetDatabase 方法返回对 Redis Cache 数据库的引用。从 GetDatabase 方法返回的对象是一个轻量级直通对象,不需要进行存储。
  
287
  
288         /// <summary>
  
289         /// 使用的是Lazy,在真正需要连接时创建连接。
  
290         /// 延迟加载技术
  
291         /// 微软azure中的配置 连接模板
  
292         /// </summary>
  
293         //private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
  
294         //{
  
295         //    //var options = ConfigurationOptions.Parse(constr);
  
296         //    ////options.ClientName = GetAppName(); // only known at runtime
  
297         //    //options.AllowAdmin = true;
  
298         //    //return ConnectionMultiplexer.Connect(options);
  
299         //    ConnectionMultiplexer muxer = ConnectionMultiplexer.Connect(Coonstr);
  
300         //    muxer.ConnectionFailed += MuxerConnectionFailed;
  
301         //    muxer.ConnectionRestored += MuxerConnectionRestored;
  
302         //    muxer.ErrorMessage += MuxerErrorMessage;
  
303         //    muxer.ConfigurationChanged += MuxerConfigurationChanged;
  
304         //    muxer.HashSlotMoved += MuxerHashSlotMoved;
  
305         //    muxer.InternalError += MuxerInternalError;
  
306         //    return muxer;
  
307         //});
  
308
  
309
  
310         #region当作消息代理中间件使用 一般使用更专业的消息队列来处理这种业务场景
  
311
  
312         /// <summary>
  
313         /// 当作消息代理中间件使用
  
314         /// 消息组建中,重要的概念便是生产者,消费者,消息中间件。
  
315         /// </summary>
  
316         /// <param name="channel"></param>
  
317         /// <param name="message"></param>
  
318         /// <returns></returns>
  
319         public static long Publish(string channel, string message)
  
320         {
  
321             ISubscriber sub = Instance.GetSubscriber();
  
322             //return sub.Publish("messages", "hello");
  
323             return sub.Publish(channel, message);
  
324         }
  
325
  
326         /// <summary>
  
327         /// 在消费者端得到该消息并输出
  
328         /// </summary>
  
329         /// <param name="channelFrom"></param>
  
330         /// <returns></returns>
  
331         public static void Subscribe(string channelFrom)
  
332         {
  
333             ISubscriber sub = Instance.GetSubscriber();
  
334             sub.Subscribe(channelFrom, (channel, message) =>
  
335             {
  
336               Console.WriteLine((string) message);
  
337             });
  
338         }
  
339
  
340         #endregion
  
341
  
342         /// <summary>
  
343         /// GetServer方法会接收一个EndPoint类或者一个唯一标识一台服务器的键值对
  
344         /// 有时候需要为单个服务器指定特定的命令
  
345         /// 使用IServer可以使用所有的shell命令,比如:
  
346         /// DateTime lastSave = server.LastSave();
  
347         /// ClientInfo[] clients = server.ClientList();
  
348         /// 如果报错在连接字符串后加 ,allowAdmin=true;
  
349         /// </summary>
  
350         /// <returns></returns>
  
351         public static IServer GetServer(string host, int port)
  
352         {
  
353             IServer server = Instance.GetServer(host, port);
  
354             return server;
  
355         }
  
356
  
357         /// <summary>
  
358         /// 获取全部终结点
  
359         /// </summary>
  
360         /// <returns></returns>
  
361         public static EndPoint[] GetEndPoints()
  
362         {
  
363             EndPoint[] endpoints = Instance.GetEndPoints();
  
364             return endpoints;
  
365         }
  
366   }
页: [1]
查看完整版本: redis的安装、启动、主从配置,以及.Net下StackExchange.Redis的使用