Redis學習筆記:Redis在C#中的使用

来源:https://www.cnblogs.com/atomy/archive/2020/03/01/12383803.html
-Advertisement-
Play Games

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


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • MySQL 的基本架構示意圖 MySQL 可以分為 Server 層和存儲引擎層兩部分。 server 存儲引擎 連接器 連接器負責跟客戶端建立連接、獲取許可權、維持和管理連接 註意: 長鏈接: 查詢緩存 執行步驟1:查詢緩存 緩存中沒有 是否使用緩存 按需使用 分析器 詞法分析 語法分析 優化器 優 ...
  • 1、連接mysql 連接本機 mysql -u root -p 連接遠程主機 mysql -h 192.168.1.% -u root -p 退出 exit; 2、修改密碼 格式:alter user 用戶名@主機地址 identified by '新密碼'; 將root密碼改為newroot al ...
  • select * from testTable1; 查詢表中的全部數據 INSERT INTO testTable1(username,password) VALUES('admin','admin'); 在testTable1表中 添加兩個欄位 分別為username和password 數值adm ...
  • 基本數據類型: 整數(int),小數(double),固定長度字元(char),可變長度字元(varchar),文本(text),二進位大對象(blog) ...
  • CREATE DATABASE testdb CHARSET=UTF8 創建一個資料庫 名字叫做testdb USE testdb; 選擇資料庫 CREATE TABLE testTable1( -> id int(11) not null primary key auto_increment, - ...
  • 什麼是Redis ? 簡單描述一下Redis的特點有哪些? Redis支持的數據類型 為什麼Redis需要把所有數據放到記憶體中? Redis是單線程的嗎? Redis持久化機制有哪些?區別是什麼?優缺點是什麼? Redis的緩存失效策略有哪幾種? 什麼是緩存命中率?提高緩存命中率的方法有哪些? Re ...
  • 1、jvm怎麼判斷哪些對象應該回收呢回答:引用計數演算法和可達性分析演算法 因為引用計數法的演算法是這樣的:在對象中添加一個引用計數器,每當一個地方引用它時,計數器就加一;當引用失效時,計數器值就減一;任何時刻計數器為零的對象就是不可能再被使用的。 但是這樣的演算法有個問題,是什麼呢? Object 1和O ...
  • 基礎篇 什麼是Redis及快速理解Redis的使用 Redis解決的問題及Redis的特性 Redis的應用場景及正確安裝與啟動 Redis配置、啟動、操作、關閉及版本選擇 字元串使用與內部實現原理 字典使用與內部實現原理 列表使用與內部實現原理 集合使用與內部實現原理 有序集合使用與內部實現原理 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...