Redis緩存服務器是一款key/value數據庫,讀110000次/s,寫81000次/s,由於是內存操做因此速度飛快,常見用法是存用戶token、短信驗證碼等git
官網顯示Redis自己並無Windows版本的,微軟官方開發了基於Windows的Redis服務器:MSOpenTech/redis github
首先下載Redis服務器,點擊前往下載.msi版本,雙擊安裝Redis服務端就有了,並以服務的形式隨系統一塊兒啓動: redis
安裝好Redis服務器以後第一件事就是設置密碼,進入安裝目錄:C:\Program Files\Redis - 找到配置文件:redis.windows-service.conf - 找到:# requirepass foobared - 回車換行加上:requirepass 這裏寫本身的新密碼(頂行寫,前面不要留空格) - 到服務裏重啓Redis服務,或者重啓電腦數據庫
不設置密碼的壞處,看看攜程這哥們的遭遇就知道了:記一次Redis被攻擊的事件 windows
命令行方式演示:啓動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) post
keys *:查看全部鍵值對(若是Redis服務器設置了密碼,這條命令會報錯,須要先輸入密碼,執行此命令:auth 你的密碼) ui
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系統
以上都是命令行和可視化工具操做Redis服務器,C#程序操做Redis須要藉助StackExchange.Redis(https://github.com/StackExchange/StackExchange.Redis),爲了統一調用,封裝了一個RedisHelper幫助類:
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);
刪除這條記錄:
bool result = RedisHelper.StringRemove(CacheFolderEnum.Folder1, "name"); if (result) { Console.WriteLine("鍵爲name的記錄刪除成功"); } else { Console.WriteLine("鍵爲name的記錄刪除失敗"); }
查詢這條記錄是否存在:
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);
獲取這個對象:
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的記錄"); }
4、其餘
MSOpenTech開發Redis緩存服務器自帶持久化,寫入以後重啓電腦鍵值對還存在,通常寫入鍵值對要設置過時時間,不然一直佔用內存不會被釋放。Redis存儲方式不光有鍵對應字符串,還有對應List,HashTable等,固然Redis更多高階的用法仍是在Linux下。