C#版-Redis缓存服务器在Windows下的使用

Redis缓存服务器是一款key/value数据库,读110000次/s,写81000次/s,因为是内存操作所以速度飞快,常见用法是存用户token、短信验证码等

官网显示Redis本身并没有Windows版本的,微软官方开发了基于Windows的Redis服务器:MSOpenTech/redis 

一、Redis服务端

 

首先下载Redis服务器,点击前往下载.msi版本,双击安装Redis服务端就有了,并以服务的形式随系统一起启动: 

 

安装好Redis服务器之后第一件事就是设置密码,进入安装目录:C:\Program Files\Redis - 找到配置文件:redis.windows-service.conf - 找到:# requirepass foobared - 回车换行加上:requirepass 这里写自己的新密码(顶行写,前面不要留空格) - 到服务里重启Redis服务,或者重启电脑

不设置密码的坏处,看看携程这哥们的遭遇就知道了:记一次Redis被攻击的事件 

二、Redis客户端(命令行和可视化工具RDM) 

命令行方式演示:启动Redis客户端、读写Redis服务器

 

 

上图命令解释: 

cd C:\Program Files\Redis:cd命令进入Redis安装目录,相当于Windows系统里双击进入Redis的安装目录 

redis-cli.exe:打开redis-cli客户端程序,相当于Windows系统里双击运行一个exe程序(安装了上面的Redis服务端程序,需要一个客户端程序连接这个服务端。连接本机redis服务器直接敲此命令,连接远程的需要加ip和端口,例:redis-cli.exe -h 111.11.11.111 -p 6379) 

keys *:查看所有键值对(如果Redis服务器设置了密码,这条命令会报错,需要先输入密码,执行此命令:auth 你的密码) 

set blog oppoic.cnblogs.com:设置一个键值对,键是:blog,值是:oppoic.cnblogs.com(按目录存储:set 目录名:键 值) 

get blog:获取键为blog对应的值 

keys *:查看所有键值对

 

其他常用命令: 

config get dir:获取redis安装目录 

ping:返回PONG表示redis服务器正常 

redis-cli.exe:进入第一个数据库(默认),redis一共0到15共16个库,进入第三个库 redis-cli -n 2(已经进去了,select 0~15 随意切换) 

quit:退出redis程序 

exit:退出dos窗口 

flushdb:删除当前选择数据库中的所有key 

flushall:删除所有数据库中的数据库 

更多命令:https://redis.io/commands 

至此,一个运行在本机的Redis缓存服务器已经搭建完成,并且可以读写了。但是命令行显然对小白用户不友好,可视化工具登场:Redis Desktop Manager(https://redisdesktop.com/download)

 

左侧树显示已经有一个连接了,点击底部的Connect to Redis Server再添加一个连接: 

Name:连接名称,随便起 

Host:主机地址,本机就是127.0.0.1,远程的输入对应IP 

Port:端口,Redis服务器默认端口6379 

Auth:密码,设置了就输,没设置留空 

连上Redis服务器就可以看到,默认16个库(配置文件可改),索引从0开始。常见用法是一个项目一个库,项目下不同功能模块分不同目录存在这个库下。 

有了可视化工具之后的操作就不用说了,双击,右键新建、删除。。。会用Windows系统的都会用这个工具。相比于命令行,Redis Desktop Manager这个可视化工具更友好,调试远程服务器上的数据也更方便,指哪打哪。 

注:本机可以这样,连接远程服务器需要到服务器上的Redis安装目录下,找到redis.windows-service.conf文件,找到bind 127.0.0.1 前面加"#"注释掉,然后到服务里右键重启redis服务,或者重启Windows系统 

三、C#操作Redis服务器 

以上都是命令行和可视化工具操作Redis服务器,C#程序操作Redis需要借助StackExchange.Redis(https://github.com/StackExchange/StackExchange.Redis),为了统一调用,封装了一个RedisHelper帮助类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
using Newtonsoft.Json;
using StackExchange.Redis;
using System;
using System.ComponentModel;
using System.Configuration;
using System.Reflection;
using System.Text;
 
namespace redis_Demo
{
   /// <summary>
   /// Redis 帮助类
   /// </summary>
   public static class RedisHelper
   {
       private static string _conn = ConfigurationManager.AppSettings["redis_connection_string"] ?? "127.0.0.1:6379";
       private static string _pwd = ConfigurationManager.AppSettings["redis_connection_pwd"] ?? "123456";
       static ConnectionMultiplexer _redis;
       static readonly object _locker = new object();
       #region 单例模式
       public static ConnectionMultiplexer Manager
       {
           get
           {
               if (_redis == null)
               {
                   lock (_locker)
                   {
                       if (_redis != null) return _redis;
                       _redis = GetManager();
                       return _redis;
                   }
               }
               return _redis;
           }
       }
       private static ConnectionMultiplexer GetManager(string connectionString = null)
       {
           if (string.IsNullOrEmpty(connectionString))
           {
               connectionString = _conn;
           }
           var options = ConfigurationOptions.Parse(connectionString);
           options.Password = _pwd;
           return ConnectionMultiplexer.Connect(options);
       }
       #endregion
       /// <summary>
       /// 添加
       /// </summary>
       /// <param name="folder">目录</param>
       /// <param name="key">键</param>
       /// <param name="value">值</param>
       /// <param name="expireMinutes">过期时间,单位:分钟。默认600分钟</param>
       /// <param name="db">库,默认第一个。0~15共16个库</param>
       /// <returns></returns>
       public static bool StringSet(CacheFolderEnum folder, string key, string value, int expireMinutes = 600, int db = -1)
       {
           string fd = GetDescription(folder);
           return Manager.GetDatabase(db).StringSet(string.IsNullOrEmpty(fd) ? key : fd + ":" + key, value, TimeSpan.FromMinutes(expireMinutes));
       }
       /// <summary>
       /// 获取
       /// </summary>
       /// <param name="folder">目录</param>
       /// <param name="key">键</param>
       /// <param name="db">库,默认第一个。0~15共16个库</param>
       /// <returns></returns>
       public static string StringGet(CacheFolderEnum folder, string key, int db = -1)
       {
           try
           {
               string fd = GetDescription(folder);
               return Manager.GetDatabase(db).StringGet(string.IsNullOrEmpty(fd) ? key : fd + ":" + key);
           }
           catch (Exception)
           {
               return null;
           }
       }
       /// <summary>
       /// 删除
       /// </summary>
       /// <param name="folder">目录</param>
       /// <param name="key">键</param>
       /// <param name="db">库,默认第一个。0~15共16个库</param>
       /// <returns></returns>
       public static bool StringRemove(CacheFolderEnum folder, string key, int db = -1)
       {
           try
           {
               string fd = GetDescription(folder);
               return Manager.GetDatabase(db).KeyDelete(string.IsNullOrEmpty(fd) ? key : fd + ":" + key);
           }
           catch (Exception)
           {
               return false;
           }
       }
       /// <summary>
       /// 是否存在
       /// </summary>
       /// <param name="key">键</param>
       /// <param name="db">库,默认第一个。0~15共16个库</param>
       public static bool KeyExists(CacheFolderEnum folder, string key, int db = -1)
       {
           try
           {
               string fd = GetDescription(folder);
               return Manager.GetDatabase(db).KeyExists(string.IsNullOrEmpty(fd) ? key : fd + ":" + key);
           }
           catch (Exception)
           {
               return false;
           }
       }
       /// <summary>
       /// 延期
       /// </summary>
       /// <param name="folder">目录</param>
       /// <param name="key">键</param>
       /// <param name="min">延长时间,单位:分钟,默认600分钟</param>
       /// <param name="db">库,默认第一个。0~15共16个库</param>
       public static bool AddExpire(CacheFolderEnum folder, string key, int min = 600, int db = -1)
       {
           try
           {
               string fd = GetDescription(folder);
               return Manager.GetDatabase(db).KeyExpire(string.IsNullOrEmpty(fd) ? key : fd + ":" + key, DateTime.Now.AddMinutes(min));
           }
           catch (Exception)
           {
               return false;
           }
       }
       /// <summary>
       /// 添加实体
       /// </summary>
       /// <param name="folder">目录</param>
       /// <param name="key">键</param>
       /// <param name="t">实体</param>
       /// <param name="ts">延长时间,单位:分钟,默认600分钟</param>
       /// <param name="db">库,默认第一个。0~15共16个库</param>
       public static bool Set<T>(CacheFolderEnum folder, string key, T t, int expireMinutes = 600, int db = -1)
       {
           string fd = GetDescription(folder);
           var str = JsonConvert.SerializeObject(t);
           return Manager.GetDatabase(db).StringSet(string.IsNullOrEmpty(fd) ? key : fd + ":" + key, str, TimeSpan.FromMinutes(expireMinutes));
       }
       /// <summary>
       /// 获取实体
       /// </summary>
       /// <param name="folder">目录</param>
       /// <param name="key">键</param>
       /// <param name="db">库,默认第一个。0~15共16个库</param>
       public static T Get<T>(CacheFolderEnum folder, string key, int db = -1) where T : class
       {
           string fd = GetDescription(folder);
           var strValue = Manager.GetDatabase(db).StringGet(string.IsNullOrEmpty(fd) ? key : fd + ":" + key);
           return string.IsNullOrEmpty(strValue) ? null : JsonConvert.DeserializeObject<T>(strValue);
       }
       /// <summary>
       /// 获得枚举的Description
       /// </summary>
       /// <param name="value">枚举值</param>
       /// <param name="nameInstead">当枚举值没有定义DescriptionAttribute,是否使用枚举名代替,默认是使用</param>
       /// <returns>枚举的Description</returns>
       private static string GetDescription(this Enum value, Boolean nameInstead = true)
       {
           Type type = value.GetType();
           string name = Enum.GetName(type, value);
           if (name == null)
           {
               return null;
           }
           FieldInfo field = type.GetField(name);
           DescriptionAttribute attribute = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute;
           if (attribute == null && nameInstead == true)
           {
               return name;
           }
           return attribute == null ? null : attribute.Description;
       }
   }
 
}

向redis服务器第一个库的fd1目录里,添加一个键为name,值为wangjie的记录: 

RedisHelper.StringSet(CacheFolderEnum.Folder1, "name", "wangjie");

 获取这条记录: 

string key = RedisHelper.StringGet(CacheFolderEnum.Folder1, "name");

Console.WriteLine("键为name的记录对应的值:" + key);

 删除这条记录:

1
2
3
4
5
6
7
8
9
bool result = RedisHelper.StringRemove(CacheFolderEnum.Folder1, "name");
if (result)
{
   Console.WriteLine("键为name的记录删除成功");
}
else
{
   Console.WriteLine("键为name的记录删除失败");
}

查询这条记录是否存在:

1
2
3
4
5
6
7
8
9
bool ifExist = RedisHelper.KeyExists(CacheFolderEnum.Folder1, "name");
if (ifExist)
{
   Console.WriteLine("键为name的记录存在");
}
else
{
   Console.WriteLine("键为name的记录不存在");
}

向redis服务器第二个库的fd2目录里,添加一个键为sd1,值为一个对象的记录: 

Student student = new Student() { Id = 1, Name = "张三", Class = "三年二班" };

RedisHelper.Set<Student>(CacheFolderEnum.Folder2, "sd1", student, 10, 1);

 获取这个对象:

1
2
3
4
5
6
7
8
9
10
Student sdGet = RedisHelper.Get<Student>(CacheFolderEnum.Folder2, "sd1", 1);
if (sdGet != null)
{
      Console.WriteLine("Id:" + sdGet.Id + " Name:" + sdGet.Name + " Class:" +
     sdGet.Class);
}
else
{
      Console.WriteLine("找不到键为sd1的记录");
}

 四、其他 

MSOpenTech开发Redis缓存服务器自带持久化,写入之后重启电脑键值对还存在,一般写入键值对要设置过期时间,否则一直占用内存不会被释放。Redis存储方式不光有键对应字符串,还有对应List,HashTable等,当然Redis更多高阶的用法还是在Linux下。

分类: C#
 

  

  

  

 

posted @   每天进步多一点  阅读(1083)  评论(0编辑  收藏  举报
编辑推荐:
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 2 本地部署DeepSeek模型构建本地知识库+联网搜索详细步骤
历史上的今天:
2017-05-26 SQL Server数据库SP命令祥解
2016-05-26 MVC之Ajax.BeginForm使用详解之更新列表
2016-05-26 jQuery操作checkbox
点击右上角即可分享
微信分享提示