前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >StackExchange.Redis学习笔记(一) Redis的使用初探

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

作者头像
蓝夏
发布2022-03-10 16:37:37
1.1K0
发布2022-03-10 16:37:37
举报
文章被收录于专栏:bluesummer

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 命令来开启服务,以下是服务启动成功界面

Redis的使用

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

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

代码语言:javascript
复制
  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         /// <summary>
  7         /// 使用一个静态属性来返回已连接的实例,如下列中所示。这样,一旦 ConnectionMultiplexer 断开连接,便可以初始化新的连接实例。
  8         /// </summary>
  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         /// <summary>
 40         /// 
 41         /// </summary>
 42         /// <returns></returns>
 43         public static IDatabase GetDatabase()
 44         {
 45             return Instance.GetDatabase();
 46         }
 47 
 48         /// <summary>
 49         /// 这里的 MergeKey 用来拼接 Key 的前缀,具体不同的业务模块使用不同的前缀。
 50         /// </summary>
 51         /// <param name="key"></param>
 52         /// <returns></returns>
 53         private static string MergeKey(string key)
 54         {
 55             return BaseSystemInfo.SystemCode + key;
 56         }
 57         /// <summary>
 58         /// 根据key获取缓存对象
 59         /// </summary>
 60         /// <typeparam name="T"></typeparam>
 61         /// <param name="key"></param>
 62         /// <returns></returns>
 63         public static T Get<T>(string key)
 64         {
 65             key = MergeKey(key);
 66             return Deserialize<T>(GetDatabase().StringGet(key));
 67         }
 68         /// <summary>
 69         /// 根据key获取缓存对象
 70         /// </summary>
 71         /// <param name="key"></param>
 72         /// <returns></returns>
 73         public static object Get(string key)
 74         {
 75             key = MergeKey(key);
 76             return Deserialize<object>(GetDatabase().StringGet(key));
 77         }
 78 
 79         /// <summary>
 80         /// 设置缓存
 81         /// </summary>
 82         /// <param name="key"></param>
 83         /// <param name="value"></param>
 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         /// <summary>
 91         /// 判断在缓存中是否存在该key的缓存数据
 92         /// </summary>
 93         /// <param name="key"></param>
 94         /// <returns></returns>
 95         public static bool Exists(string key)
 96         {
 97             key = MergeKey(key);
 98             return GetDatabase().KeyExists(key);  //可直接调用
 99         }
100 
101         /// <summary>
102         /// 移除指定key的缓存
103         /// </summary>
104         /// <param name="key"></param>
105         /// <returns></returns>
106         public static bool Remove(string key)
107         {
108             key = MergeKey(key);
109             return GetDatabase().KeyDelete(key);
110         }
111 
112         /// <summary>
113         /// 异步设置
114         /// </summary>
115         /// <param name="key"></param>
116         /// <param name="value"></param>
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         /// <summary>
124         /// 根据key获取缓存对象
125         /// </summary>
126         /// <param name="key"></param>
127         /// <returns></returns>
128         public static async Task<object> GetAsync(string key)
129         {
130             key = MergeKey(key);
131             object value = await GetDatabase().StringGetAsync(key);
132             return value;
133         }
134 
135         /// <summary>
136         /// 实现递增
137         /// </summary>
138         /// <param name="key"></param>
139         /// <returns></returns>
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         /// <summary>
152         /// 实现递减
153         /// </summary>
154         /// <param name="key"></param>
155         /// <param name="value"></param>
156         /// <returns></returns>
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         /// <summary>
164         /// 序列化对象
165         /// </summary>
166         /// <param name="o"></param>
167         /// <returns></returns>
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         /// <summary>
184         /// 反序列化对象
185         /// </summary>
186         /// <typeparam name="T"></typeparam>
187         /// <param name="stream"></param>
188         /// <returns></returns>
189         static T Deserialize<T>(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         /// <summary>
203         /// 配置更改时
204         /// </summary>
205         /// <param name="sender"></param>
206         /// <param name="e"></param>
207         private static void MuxerConfigurationChanged(object sender, EndPointEventArgs e)
208         {
209             LogHelper.WriteInfoLog("Configuration changed: " + e.EndPoint);
210         }
211         /// <summary>
212         /// 发生错误时
213         /// </summary>
214         /// <param name="sender"></param>
215         /// <param name="e"></param>
216         private static void MuxerErrorMessage(object sender, RedisErrorEventArgs e)
217         {
218             LogHelper.WriteInfoLog("ErrorMessage: " + e.Message);
219         }
220         /// <summary>
221         /// 重新建立连接之前的错误
222         /// </summary>
223         /// <param name="sender"></param>
224         /// <param name="e"></param>
225         private static void MuxerConnectionRestored(object sender, ConnectionFailedEventArgs e)
226         {
227             LogHelper.WriteInfoLog("ConnectionRestored: " + e.EndPoint);
228         }
229         /// <summary>
230         /// 连接失败 , 如果重新连接成功你将不会收到这个通知
231         /// </summary>
232         /// <param name="sender"></param>
233         /// <param name="e"></param>
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         /// <summary>
239         /// 更改集群
240         /// </summary>
241         /// <param name="sender"></param>
242         /// <param name="e"></param>
243         private static void MuxerHashSlotMoved(object sender, HashSlotMovedEventArgs e)
244         {
245             LogHelper.WriteInfoLog("HashSlotMoved:NewEndPoint" + e.NewEndPoint + ", OldEndPoint" + e.OldEndPoint);
246         }
247         /// <summary>
248         /// redis类库错误
249         /// </summary>
250         /// <param name="sender"></param>
251         /// <param name="e"></param>
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         /// <summary>
261         /// 使用的是Lazy,在真正需要连接时创建连接。
262         /// 延迟加载技术
263         /// 微软azure中的配置 连接模板
264         /// </summary>
265         //private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
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         /// <summary>
284         /// 当作消息代理中间件使用
285         /// 消息组建中,重要的概念便是生产者,消费者,消息中间件。
286         /// </summary>
287         /// <param name="channel"></param>
288         /// <param name="message"></param>
289         /// <returns></returns>
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         /// <summary>
298         /// 在消费者端得到该消息并输出
299         /// </summary>
300         /// <param name="channelFrom"></param>
301         /// <returns></returns>
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         /// <summary>
313         /// GetServer方法会接收一个EndPoint类或者一个唯一标识一台服务器的键值对
314         /// 有时候需要为单个服务器指定特定的命令
315         /// 使用IServer可以使用所有的shell命令,比如:
316         /// DateTime lastSave = server.LastSave();
317         /// ClientInfo[] clients = server.ClientList();
318         /// 如果报错在连接字符串后加 ,allowAdmin=true;
319         /// </summary>
320         /// <returns></returns>
321         public static IServer GetServer(string host, int port)
322         {
323             IServer server = Instance.GetServer(host, port);
324             return server;
325         }
326 
327         /// <summary>
328         /// 获取全部终结点
329         /// </summary>
330         /// <returns></returns>
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     }

测试代码

代码语言:javascript
复制
 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命令

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服务启动成功

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-10-16 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Redis
  • Redis的安装
  • Redis的使用
  • Redis加入Windows服务
相关产品与服务
云数据库 Redis®
腾讯云数据库 Redis®(TencentDB for Redis®)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档