StackExchange.Redis学习笔记(一) Redis的使用初探

StackExchange.Redis学习笔记(一) Redis的使用初探

原文:StackExchange.Redis学习笔记(一) Redis的使用初探

 

Redis

  • Redis将其数据库完全保存在内存中,仅使用磁盘进行持久化。
  • 与其它键值数据存储相比,Redis有一组相对丰富的数据类型。
  • Redis可以将数据复制到任意数量的从机中

Redis的安装

  官网只提供了linux的安装包,我win10 的系统,在github上下载的windows安装包 3.0.504最新稳定版的

  github地址:https://github.com/MicrosoftArchive/redis/releases   
  官网下载地址:https://redis.io/download   

  将压缩包解压到文件夹后,双击“redis-server.exe”即可启动redis服务,也可以在环境变量中配置之后,用redis-server 命令来开启服务,以下是服务启动成功界面

  StackExchange.Redis学习笔记(一) Redis的使用初探_第1张图片

Redis的使用

  C#可选用ServiceStack.Redis或者StackExchange.Redis等客户端程序操作redis,由于ServiceStack.Redis已经收费了,我这里用的是StackExchange.Redis,通过Nuget安装到项目中

StackExchange.Redis学习笔记(一) Redis的使用初探_第2张图片

接下来我们创建一个操作redis的帮助类:

复制代码

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

复制代码

测试代码

复制代码

 1  static void Main(string[] args)
 2         {
 3             RedisTest();
 4         }
 5         public static void RedisTest()
 6         {
 7             Console.WriteLine("Redis写入缓存:Name:张三丰");
 8             StackExchangeRedisHelper.Set("Name", "张三丰", new TimeSpan(0, 0, 0, 0, 1000));
 9             Console.WriteLine("Redis获取缓存:Name:" + StackExchangeRedisHelper.Get("Name").ToString());
10             Thread.Sleep(1000);
11             Console.WriteLine("一秒后Redis获取缓存:Name:" + StackExchangeRedisHelper.Get("Name")??"");
12             Console.ReadKey();
13         }

复制代码

 

 也可以通过Execute来直接运行redis命令

StackExchange.Redis学习笔记(一) Redis的使用初探_第3张图片

 

Redis加入Windows服务

由于关闭控制台redis就自动关闭了,所以把redis加入windows服务更好一些

切换到redis目录下运行命令:redis-server --service-install redis.windows-service.conf --loglevel verbose

移除服务:--service-uninstal

开启服务:redis-server --service-start

关闭服务:redis-server --service-stop

在开启Redis服务时遇到一些坑,

  redis.windows-service.conf中配置:

  1. logfile "Logs/redis_log.txt"需要有对应的目录

  2.将bind 127.0.0.1注释去掉

  3.依然有问题,后参考一篇文章 http://blog.csdn.net/fengzhihen2007/article/details/52211048

直到出现successfully started服务启动成功

分类: 构架-负载均衡/缓存/分布式系统服务器

你可能感兴趣的:(Redis)