1、新建一個WinForm窗體,命名為Main: 2、在NuGet中安裝StackExchange.Redis。 3、添加一個類,命名為RedisHelper。 public static class RedisHelper { private static string Constr = ""; ...
1、新建一個WinForm窗體,命名為Main:
2、在NuGet中安裝StackExchange.Redis。
3、添加一個類,命名為RedisHelper。
public static class RedisHelper { private static string Constr = ""; private static readonly object _locker = new object(); private static ConnectionMultiplexer _instance = null; /// <summary> /// 使用一個靜態屬性來返回已連接的實例,如下列中所示。這樣,一旦 ConnectionMultiplexer 斷開連接,便可以初始化新的連接實例。 /// </summary> public static ConnectionMultiplexer Instance { get { if (Constr.Length == 0) { throw new Exception("連接字元串未設置!"); } if (_instance == null) { lock (_locker) { if (_instance == null || !_instance.IsConnected) { _instance = ConnectionMultiplexer.Connect(Constr); } } } //註冊如下事件 _instance.ConnectionFailed += MuxerConnectionFailed; _instance.ConnectionRestored += MuxerConnectionRestored; _instance.ErrorMessage += MuxerErrorMessage; _instance.ConfigurationChanged += MuxerConfigurationChanged; _instance.HashSlotMoved += MuxerHashSlotMoved; _instance.InternalError += MuxerInternalError; return _instance; } } static RedisHelper() { } public static void SetCon(string config) { Constr = config; } public static IDatabase GetDatabase() { return Instance.GetDatabase(); } /// <summary> /// 這裡的 MergeKey 用來拼接 Key 的首碼,具體不同的業務模塊使用不同的首碼。 /// </summary> /// <param name="key"></param> /// <returns></returns> private static string MergeKey(string key) { return key; //return BaseSystemInfo.SystemCode + key; } /// <summary> /// 根據key獲取緩存對象 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <returns></returns> public static T Get<T>(string key) { key = MergeKey(key); return Deserialize<T>(GetDatabase().StringGet(key)); } /// <summary> /// 根據key獲取緩存對象 /// </summary> /// <param name="key"></param> /// <returns></returns> public static object Get(string key) { key = MergeKey(key); return Deserialize<object>(GetDatabase().StringGet(key)); } /// <summary> /// 設置緩存 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <param name="expireMinutes"></param> public static void Set(string key, object value, int expireMinutes = 0) { key = MergeKey(key); if (expireMinutes > 0) { GetDatabase().StringSet(key, Serialize(value), TimeSpan.FromMinutes(expireMinutes)); } else { GetDatabase().StringSet(key, Serialize(value)); } } /// <summary> /// 判斷在緩存中是否存在該key的緩存數據 /// </summary> /// <param name="key"></param> /// <returns></returns> public static bool Exists(string key) { key = MergeKey(key); return GetDatabase().KeyExists(key); //可直接調用 } /// <summary> /// 移除指定key的緩存 /// </summary> /// <param name="key"></param> /// <returns></returns> public static bool Remove(string key) { key = MergeKey(key); return GetDatabase().KeyDelete(key); } /// <summary> /// 非同步設置 /// </summary> /// <param name="key"></param> /// <param name="value"></param> public static async Task SetAsync(string key, object value) { key = MergeKey(key); await GetDatabase().StringSetAsync(key, Serialize(value)); } /// <summary> /// 根據key獲取緩存對象 /// </summary> /// <param name="key"></param> /// <returns></returns> public static async Task<object> GetAsync(string key) { key = MergeKey(key); object value = await GetDatabase().StringGetAsync(key); return value; } /// <summary> /// 實現遞增 /// </summary> /// <param name="key"></param> /// <returns></returns> public static long Increment(string key) { key = MergeKey(key); //三種命令模式 //Sync,同步模式會直接阻塞調用者,但是顯然不會阻塞其他線程。 //Async,非同步模式直接走的是Task模型。 //Fire - and - Forget,就是發送命令,然後完全不關心最終什麼時候完成命令操作。 //即發即棄:通過配置 CommandFlags 來實現即發即棄功能,在該實例中該方法會立即返回,如果是string則返回null 如果是int則返回0.這個操作將會繼續在後臺運行,一個典型的用法頁面計數器的實現: return GetDatabase().StringIncrement(key, flags: CommandFlags.FireAndForget); } /// <summary> /// 實現遞減 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <returns></returns> public static long Decrement(string key, string value) { key = MergeKey(key); return GetDatabase().HashDecrement(key, value, flags: CommandFlags.FireAndForget); } /// <summary> /// 序列化對象 /// </summary> /// <param name="o"></param> /// <returns></returns> private static byte[] Serialize(object o) { if (o == null) { return null; } BinaryFormatter binaryFormatter = new BinaryFormatter(); using (MemoryStream memoryStream = new MemoryStream()) { binaryFormatter.Serialize(memoryStream, o); byte[] objectDataAsStream = memoryStream.ToArray(); return objectDataAsStream; } } /// <summary> /// 反序列化對象 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="stream"></param> /// <returns></returns> private static T Deserialize<T>(byte[] stream) { if (stream == null) { return default(T); } BinaryFormatter binaryFormatter = new BinaryFormatter(); using (MemoryStream memoryStream = new MemoryStream(stream)) { T result = (T)binaryFormatter.Deserialize(memoryStream); return result; } } /// <summary> /// 配置更改時 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void MuxerConfigurationChanged(object sender, EndPointEventArgs e) { //LogHelper.SafeLogMessage("Configuration changed: " + e.EndPoint); } /// <summary> /// 發生錯誤時 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void MuxerErrorMessage(object sender, RedisErrorEventArgs e) { //LogHelper.SafeLogMessage("ErrorMessage: " + e.Message); } /// <summary> /// 重新建立連接之前的錯誤 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void MuxerConnectionRestored(object sender, ConnectionFailedEventArgs e) { //LogHelper.SafeLogMessage("ConnectionRestored: " + e.EndPoint); } /// <summary> /// 連接失敗,如果重新連接成功你將不會收到這個通知。 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void MuxerConnectionFailed(object sender, ConnectionFailedEventArgs e) { //LogHelper.SafeLogMessage("重新連接:Endpoint failed: " + e.EndPoint + ", " + e.FailureType +(e.Exception == null ? "" : (", " + e.Exception.Message))); } /// <summary> /// 更改集群 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void MuxerHashSlotMoved(object sender, HashSlotMovedEventArgs e) { //LogHelper.SafeLogMessage("HashSlotMoved:NewEndPoint" + e.NewEndPoint + ", OldEndPoint" + e.OldEndPoint); } /// <summary> /// redis類庫錯誤 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void MuxerInternalError(object sender, InternalErrorEventArgs e) { //LogHelper.SafeLogMessage("InternalError:Message" + e.Exception.Message); } //場景不一樣,選擇的模式便會不一樣,大家可以按照自己系統架構情況合理選擇長連接還是Lazy。 //建立連接後,通過調用ConnectionMultiplexer.GetDatabase 方法返回對 Redis Cache 資料庫的引用。從 GetDatabase 方法返回的對象是一個輕量級直通對象,不需要進行存儲。 /// <summary> /// 使用的是Lazy,在真正需要連接時創建連接。 /// 延遲載入技術 /// 微軟azure中的配置 連接模板 /// </summary> //private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() => //{ // //var options = ConfigurationOptions.Parse(constr); // ////options.ClientName = GetAppName(); // only known at runtime // //options.AllowAdmin = true; // //return ConnectionMultiplexer.Connect(options); // ConnectionMultiplexer muxer = ConnectionMultiplexer.Connect(Coonstr); // muxer.ConnectionFailed += MuxerConnectionFailed; // muxer.ConnectionRestored += MuxerConnectionRestored; // muxer.ErrorMessage += MuxerErrorMessage; // muxer.ConfigurationChanged += MuxerConfigurationChanged; // muxer.HashSlotMoved += MuxerHashSlotMoved; // muxer.InternalError += MuxerInternalError; // return muxer; //}); #region 當作消息代理中間件使用 一般使用更專業的消息隊列來處理這種業務場景 /// <summary> /// 當作消息代理中間件使用 /// 消息組建中,重要的概念便是生產者、消費者、消息中間件。 /// </summary> /// <param name="channel"></param> /// <param name="message"></param> /// <returns></returns> public static long Publish(string channel, string message) { ISubscriber sub = Instance.GetSubscriber(); //return sub.Publish("messages", "hello"); return sub.Publish(channel, message); } /// <summary> /// 在消費者端得到該消息並輸出 /// </summary> /// <param name="channelFrom"></param> /// <returns></returns> public static void Subscribe(string channelFrom) { ISubscriber sub = Instance.GetSubscriber(); sub.Subscribe(channelFrom, (channel, message) => { Console.WriteLine(message); }); } #endregion /// <summary> /// GetServer方法會接收一個EndPoint類或者一個唯一標識一臺伺服器的鍵值對 /// 有時候需要為單個伺服器指定特定的命令 /// 使用IServer可以使用所有的shell命令,比如: /// DateTime lastSave = server.LastSave(); /// ClientInfo[] clients = server.ClientList(); /// 如果報錯在連接字元串後加 ,allowAdmin=true; /// </summary> /// <returns></returns> public static IServer GetServer(string host, int port) { IServer server = Instance.GetServer(host, port); return server; } /// <summary> /// 獲取全部終結點 /// </summary> /// <returns></returns> public static EndPoint[] GetEndPoints() { EndPoint[] endpoints = Instance.GetEndPoints(); return endpoints; } }View Code
4、Main窗體代碼:
public partial class Main : Form { public Main() { InitializeComponent(); try { string redisconf = "127.0.0.1:6379,password=12345,DefaultDatabase=0"; RedisHelper.SetCon(redisconf); } catch (Exception ex) { MessageBox.Show(ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } } /// <summary> /// 設置 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button1_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(textBox1.Text)) { textBox4.Text = "請填寫鍵"; return; } if (string.IsNullOrEmpty(textBox2.Text)) { textBox4.Text = "請填寫值"; return; } if (string.IsNullOrEmpty(textBox3.Text)) { textBox4.Text = "請填寫過期時間"; return; } //鍵、值、過期時間 RedisHelper.Set(textBox1.Text, textBox2.Text, int.Parse(textBox3.Text)); textBox4.Text = "添加成功"; } /// <summary> /// 刪除 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button2_Click(object sender, EventArgs e) { if (!string.IsNullOrEmpty(textBox1.Text)) { if (RedisHelper.Exists(textBox1.Text)) { RedisHelper.Remove(textBox1.Text).ToString(); textBox4.Text = "刪除成功"; } else { textBox4.Text = "已過期或不存在"; } } else { textBox4.Text = "請填寫鍵"; } } /// <summary> /// 獲取 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button3_Click(object sender, EventArgs e) { if (!string.IsNullOrEmpty(textBox1.Text)) { if (RedisHelper.Exists(textBox1.Text)) { textBox4.Text = RedisHelper.Get(textBox1.Text).ToString(); } else { textBox4.Text = "已過期或不存在"; } } else { textBox4.Text = "請填寫鍵"; } } /// <summary> /// 分鐘數--非Backspace鍵或數字時處理 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void TextBox3_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar != 8 && !char.IsDigit(e.KeyChar)) { e.Handled = true; } } }View Code
5、運行結果:
參考自:
https://blog.csdn.net/wu_zongwen/article/details/80318916