基於C#的MongoDB資料庫開發應用(4)--Redis的安裝及使用

来源:http://www.cnblogs.com/wuhuacong/archive/2016/01/12/5123347.html
-Advertisement-
Play Games

在前面介紹了三篇關於MongoDB資料庫的開發使用文章,嚴格來講這個不能歸類於MongoDB資料庫開發,不過Redis又有著和MongoDB資料庫非常密切的關係,它們兩者很接近,Redis主要是記憶體中的NoSQL資料庫,用來提高性能的;MongoDB資料庫則是文件中的NoSQL資料庫,做數據序列號存...


在前面介紹了三篇關於MongoDB資料庫的開發使用文章,嚴格來講這個不能歸類於MongoDB資料庫開發,不過Redis又有著和MongoDB資料庫非常密切的關係,它們兩者很接近,Redis主要是記憶體中的NoSQL資料庫,用來提高性能的;MongoDB資料庫則是文件中的NoSQL資料庫,做數據序列號存儲使用的,它們兩者關係密切又有所區別。本篇主要介紹Redis的安裝及使用,為後面Redis和MongoDB資料庫的聯合使用先鋪下基礎。

1、Redis基礎及安裝

Redis是一個開源的使用ANSI C語言編寫、支持網路、可基於記憶體亦可持久化的日誌型、Key-Value資料庫,和Memcached類似,它支持存儲的value類型相對更多,包括string(字元串)、list(鏈表)、set(集合)、zset(sorted set --有序集合)和hash(哈希類型)。在此基礎上,redis支持各種不同方式的排序。與memcached一樣,為了保證效率,數據都是緩存在記憶體中。區別的是redis會周期性的把更新的數據寫入磁碟或者把修改操作寫入追加的記錄文件,並且在此基礎上實現了master-slave(主從)同步。

Redis的代碼遵循ANSI-C編寫,可以在所有POSIX系統(如Linux, *BSD, Mac OS X, Solaris等)上安裝運行。而且Redis並不依賴任何非標準庫,也沒有編譯參數必需添加。

1)Redis支持兩種持久化方式:

   (1):snapshotting(快照)也是預設方式.(把數據做一個備份,將數據存儲到文件)

   (2)Append-only file(縮寫aof)的方式 

   快照是預設的持久化方式,這種方式是將記憶體中數據以快照的方式寫到二進位文件中,預設的文件名稱為dump.rdb.可以通過配置設置自動做快照持久化的方式。我們可以配置redis在n秒內如果超過m個key鍵修改就自動做快照.

   aof方式:由於快照方式是在一定間隔時間做一次的,所以如果Redis意外down掉的話,就會丟失最後一次快照後的所有修改。aof比快照方式有更好的持久化性,是由於在使用aof時,redis會將每一個收到的寫命令都通過write函數追加到文件中,當redis重啟時會通過重新執行文件中保存的寫命令來在記憶體中重建整個資料庫的內容。 

2)Redis數據結構

Redis 的作者antirez曾稱其為一個數據結構伺服器(data structures server),這是一個非常準確的表述,Redis的所有功能就是將數據以其固有的幾種結構保存,並提供給用戶操作這幾種結構的介面。我們可以想象我們在各種語言中的那些固有數據類型及其操作。

Redis目前提供四種數據類型:string,list,setzset(sorted set)和Hash

  • string是最簡單的類型,你可以理解成與Memcached一模一個的類型,一個key對應一個value,其上支持的操作與Memcached的操作類似。但它的功能更豐富。
  • list是一個鏈表結構,主要功能是push、pop、獲取一個範圍的所有值等等。操作中key理解為鏈表的名字。
  • set是集合,和我們數學中的集合概念相似,對集合的操作有添加刪除元素,有對多個集合求交並差等操作。操作中key理解為集合的名字。
  • zset是set的一個升級版本,他在set的基礎上增加了一個順序屬性,這一屬性在添加修改元素的時候可以指定,每次指定後,zset會自動重新按新的值調整順序。可以理解了有兩列的mysql表,一列存value,一列存順序。操作中key理解為zset的名字。
  • Hash數據類型允許用戶用Redis存儲對象類型,Hash數據類型的一個重要優點是,當你存儲的數據對象只有很少幾個key值時,數據存儲的記憶體消耗會很小.更多關於Hash數據類型的說明請見: http://code.google.com/p/redis/wiki/Hashes

3)Redis數據存儲

Redis的存儲分為記憶體存儲、磁碟存儲和log文件三部分,配置文件中有三個參數對其進行配置。

save seconds updatessave配置,指出在多長時間內,有多少次更新操作,就將數據同步到數據文件。這個可以多個條件配合,比如預設配置文件中的設置,就設置了三個條件。

appendonly yes/no appendonly配置,指出是否在每次更新操作後進行日誌記錄,如果不開啟,可能會在斷電時導致一段時間內的數據丟失。因為redis本身同步數據文件是按上面的save條件來同步的,所以有的數據會在一段時間內只存在於記憶體中。

appendfsync no/always/everysec appendfsync配置,no表示等操作系統進行數據緩存同步到磁碟,always表示每次更新操作後手動調用fsync()將數據寫到磁碟,everysec表示每秒同步一次。

 

4)Redis的安裝

Redis可以在不同的平臺運行,不過我主要基於Windows進行開發工作,所以下麵主要是基於Windows平臺進行介紹。

Redis可以安裝以DOS視窗啟動的,也可以安裝為Windows服務的,一般為了方便,我們更願意把它安裝為Windows服務,這樣可以比較方便管理。下載地址:https://github.com/MSOpenTech/redis/releases下載,安裝為Windows服務即可。

當前可以下載到最新的Windows安裝版本為3.0,安裝後作為Windows服務運行,安裝後可以在系統的服務裡面看到Redis的服務在運行了,如下圖所示。

安裝好Redis後,還有一個Redis伴侶Redis Desktop Manager需要安裝,這樣可以實時查看Redis緩存裡面有哪些數據,具體地址如下:http://redisdesktop.com/download

下載屬於自己平臺的版本即可

下載安裝後,打開運行界面,如果我們往裡面添加鍵值的數據,那麼可以看到裡面的數據了。

 

2、Redis的C#使用

Redis目前提供四種數據類型:string,list,setzset(sorted set)和Hash。因此它在C#裡面也有對應的封裝處理,而且有很多人對他進行了封裝,提供了很多的響應開發包,具體可以訪問http://redis.io/clients#c 進行瞭解。一般建議用ServiceStack.Redis的封裝驅動比較好,具體的使用可以參考https://github.com/ServiceStack/ServiceStack.Redis

我們開發C#代碼的時候,可以在NuGet程式包上面進行添加對應的ServiceStack.Redis引用,如下所示。

 

在彈出的NuGet程式包裡面,輸入ServiceStack.Redis進行搜索,並添加下麵的驅動引用即可。

這樣會在項目引用裡面添加了幾個對應的程式集,如下所示。

在C#裡面使用Redis,首先需要實例化一個Redis的客戶端類,如下所示。

        //創建一個Redis的客戶端類
        RedisClient client = new RedisClient("127.0.0.1", 6379);

在使用前,我們需要清空所有的鍵值存儲,使用FushAll方法即可,如下所示

            //Redis FlushAll 命令用於清空整個 Redis 伺服器的數據(刪除所有資料庫的所有 key )。 
            client.FlushAll();

根據上面的驅動,可以為不同類型的處理編寫一些演示代碼,下麵代碼是摘錄網上的案例進行介紹。

            #region string類型的測試代碼

            client.Add<string>("StringValueTime", "帶有有效期的字元串", DateTime.Now.AddMilliseconds(10000));

            while (true)
            {
                if (client.ContainsKey("StringValueTime"))
                {
                    Console.WriteLine("String.鍵:StringValue, 值:{0} {1}", client.Get<string>("StringValueTime"), DateTime.Now);
                    Thread.Sleep(10000);
                }
                else
                {
                    Console.WriteLine("鍵:StringValue, 值:已過期 {0}", DateTime.Now);
                    break;
                }
            }

            client.Add<string>("StringValue", " String和Memcached操作方法差不多");
            Console.WriteLine("數據類型為:String.鍵:StringValue, 值:{0}", client.Get<string>("StringValue"));

            Student stud = new Student() { id = "1001", name = "李四" };
            client.Add<Student>("StringEntity", stud);
            Student Get_stud = client.Get<Student>("StringEntity");
            Console.WriteLine("數據類型為:String.鍵:StringEntity, 值:{0} {1}", Get_stud.id, Get_stud.name);
            #endregion

            #region Hash類型的測試代碼

            client.SetEntryInHash("HashID", "Name", "張三");
            client.SetEntryInHash("HashID", "Age", "24");
            client.SetEntryInHash("HashID", "Sex", "");
            client.SetEntryInHash("HashID", "Address", "上海市XX號XX室");

            List<string> HaskKey = client.GetHashKeys("HashID");
            foreach (string key in HaskKey)
            {
                Console.WriteLine("HashID--Key:{0}", key);
            }

            List<string> HaskValue = client.GetHashValues("HashID");
            foreach (string value in HaskValue)
            {
                Console.WriteLine("HashID--Value:{0}", value);
            }

            List<string> AllKey = client.GetAllKeys(); //獲取所有的key。
            foreach (string Key in AllKey)
            {
                Console.WriteLine("AllKey--Key:{0}", Key);
            }
            #endregion

            #region List類型的測試代碼
            /*
             * list是一個鏈表結構,主要功能是push,pop,獲取一個範圍的所有的值等,操作中key理解為鏈表名字。 
             * Redis的list類型其實就是一個每個子元素都是string類型的雙向鏈表。我們可以通過push,pop操作從鏈表的頭部或者尾部添加刪除元素,
             * 這樣list既可以作為棧,又可以作為隊列。Redis list的實現為一個雙向鏈表,即可以支持反向查找和遍歷,更方便操作,不過帶來了部分額外的記憶體開銷,
             * Redis內部的很多實現,包括發送緩衝隊列等也都是用的這個數據結構 
             */
            client.EnqueueItemOnList("QueueListId", "1.張三");  //入隊
            client.EnqueueItemOnList("QueueListId", "2.張四");
            client.EnqueueItemOnList("QueueListId", "3.王五");
            client.EnqueueItemOnList("QueueListId", "4.王麻子");
            long q = client.GetListCount("QueueListId");

            Console.WriteLine(client.GetItemFromList("QueueListId", 0));
            for (int i = 0; i < q; i++)
            {
                Console.WriteLine("QueueListId出隊值:{0}", client.DequeueItemFromList("QueueListId"));   //出隊(隊列先進先出)
            }

            q = client.GetListCount("QueueListId");
            Console.WriteLine(q);

            client.PushItemToList("StackListId", "1.張三");  //入棧
            client.PushItemToList("StackListId", "2.張四");
            client.PushItemToList("StackListId", "3.王五");
            client.PushItemToList("StackListId", "4.王麻子");
            long p = client.GetListCount("StackListId");
            for (int i = 0; i < p; i++)
            {
                Console.WriteLine("StackListId出棧值:{0}", client.PopItemFromList("StackListId"));   //出棧(棧先進後出)
            }
            q = client.GetListCount("StackListId");
            Console.WriteLine(q);

            #endregion

            #region Set無序集合的測試代碼
            /*
             它是string類型的無序集合。set是通過hash table實現的,添加,刪除和查找,對集合我們可以取並集,交集,差集
             */
            client.AddItemToSet("Set1001", "小A");
            client.AddItemToSet("Set1001", "小B");
            client.AddItemToSet("Set1001", "小C");
            client.AddItemToSet("Set1001", "小D");
            HashSet<string> hastsetA = client.GetAllItemsFromSet("Set1001");
            foreach (string item in hastsetA)
            {
                Console.WriteLine("Set無序集合ValueA:{0}", item); //出來的結果是無須的
            }

            client.AddItemToSet("Set1002", "小K");
            client.AddItemToSet("Set1002", "小C");
            client.AddItemToSet("Set1002", "小A");
            client.AddItemToSet("Set1002", "小J");
            HashSet<string> hastsetB = client.GetAllItemsFromSet("Set1002");
            foreach (string item in hastsetB)
            {
                Console.WriteLine("Set無序集合ValueB:{0}", item); //出來的結果是無須的
            }

            HashSet<string> hashUnion = client.GetUnionFromSets(new string[] { "Set1001", "Set1002" });
            foreach (string item in hashUnion)
            {
                Console.WriteLine("求Set1001和Set1002的並集:{0}", item); //並集
            }

            HashSet<string> hashG = client.GetIntersectFromSets(new string[] { "Set1001", "Set1002" });
            foreach (string item in hashG)
            {
                Console.WriteLine("求Set1001和Set1002的交集:{0}", item);  //交集
            }

            HashSet<string> hashD = client.GetDifferencesFromSet("Set1001", new string[] { "Set1002" });  //[返回存在於第一個集合,但是不存在於其他集合的數據。差集]
            foreach (string item in hashD)
            {
                Console.WriteLine("求Set1001和Set1002的差集:{0}", item);  //差集
            }

            #endregion

            #region  SetSorted 有序集合的測試代碼
            /*
             sorted set 是set的一個升級版本,它在set的基礎上增加了一個順序的屬性,這一屬性在添加修改.元素的時候可以指定,
             * 每次指定後,zset(表示有序集合)會自動重新按新的值調整順序。可以理解為有列的表,一列存 value,一列存順序。操作中key理解為zset的名字.
             */
            client.AddItemToSortedSet("SetSorted1001", "1.劉仔");
            client.AddItemToSortedSet("SetSorted1001", "2.星仔");
            client.AddItemToSortedSet("SetSorted1001", "3.豬仔");
            List<string> listSetSorted = client.GetAllItemsFromSortedSet("SetSorted1001");
            foreach (string item in listSetSorted)
            {
                Console.WriteLine("SetSorted有序集合{0}", item);
            }
            #endregion

對於具體類型的類對象,也可以使用As方法進行轉換為對應的處理對象進行處理,如下所示

IRedisTypedClient<Phone> phones = client.As<Phone>();

具體的測試代碼如下所示。

        /// <summary>
        /// Redis對對象類的處理例子
        /// </summary>
        private void btnTypeValue_Click(object sender, EventArgs e)
        {
            IRedisTypedClient<Phone> phones = client.As<Phone>();
            Phone phoneFive = phones.GetValue("5");
            if (phoneFive == null)
            {
                Thread.Sleep(50);
                phoneFive = new Phone
                {
                    Id = 5,
                    Manufacturer = "Apple",
                    Model = "xxxxx",
                    Owner = new Person
                    {
                        Id = 1,
                        Age = 100,
                        Name = "伍華聰",
                        Profession = "電腦",
                        Surname = "wuhuacong"
                    }
                };

                phones.SetEntry(phoneFive.Id.ToString(), phoneFive);
            }

            client.Store<Phone>(
                new Phone
                {
                    Id = 2,
                    Manufacturer = "LG",
                    Model = "test-xxx",
                    Owner = new Person
                    {
                        Id = 2,
                        Age = 40,
                        Name = "test",
                        Profession = "teacher",
                        Surname = "wuhuacong"
                    }
                });

            var message = "Phone model is " + phoneFive.Manufacturer + ",";
            message += "Phone Owner Name is: " + phoneFive.Owner.Name;
            Console.WriteLine(message);
        }

以上就是關於Redis的安裝以及簡單的例子使用說明,在具體中,我們可以利用Redis的高性能特性,來構建我們的緩存數據,並且可以利用Redis和MongoDB資料庫的完美銜接,可以整合一起做的更好,為相關的後臺提供更高效的數據處理操作,畢竟在互聯網的大環境下,性能是非常重要的。

 


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

-Advertisement-
Play Games
更多相關文章
  • 我們有時候在工作流開發中可能會遇到這樣的需求,就是已經審批結束的流程,可能我們還是仍然需要修改業務表的結果,而且我們需要一個時間期限,比如:在5天內可以進行修改,這個時候我們就需要得到我們最後一步審批的時間,我們可以通過下麵這個sql查詢到該時間SELECT MAX(COMM.TIME_) FRO....
  • Python3中int、float、str、list、dict、tuple類的內建方法
  • 本小節我們來做一個好玩的事情,就是計數器,還記得在做LED自加實驗時我們就曾經提到過關於計數器的相關議題,那麼這節我們就來討論討論。 探討一下如下的問題:請用verilog記八個數的寫法,分析這個可以更好的理解觸發器的工作原理。1. reg [3:0]cnt; always@(pose...
  • Sub Macro2()'' Macro2 Macro'' Keyboard Shortcut: Ctrl+d' ActiveCell.Select ActiveSheet.Paste Selection.ShapeRange.ScaleHeight 0.6, msoFalse, msoScaleF...
  • 理解什麼是繼承首先我們知道,面對對象有三大特征:封裝:解決了數據的安全性問題繼承:解決了代碼的重用問題多態:解決了程式的擴展問題上一篇博客中,我們瞭解了一下封裝,現在我了再來看看什麼是繼承。在現實生活中,我們可以把封裝理解成兒子對父親財產的繼承。而在面向對象程式設計中的繼承,是一個對象從另一個對象獲...
  • 在以前的博客裡面,我們介紹了在java領域中大部分的知識點,從最基礎的java最基本語法到SSH框架。這裡面應該包含了在java領域裡面的大部分內容了吧。但是,那些知識點是讓我們從一個應用的層面上瞭解了java,java程式真正底層的運行機制和一些底層虛擬機的工作我們還不瞭解,雖然這些內容在我們真正...
  • 避免使用終結方法(finalizer)終結方法(finalizer)通常是不可預測的,也是很危險的,一般情況下是不必要的。不要把finalizer當成C++中析構函數的對應物。java中,當對象不可達時(即沒有引用指向這個對象時),會由垃圾回收器來回收與該對象相關聯的記憶體資源;而其他的記憶體資源,則一...
  • 題目來源自http://acm.nyist.net/JudgeOnline/problem.php?pid=7描述一個街區有很多住戶,街區的街道只能為東西、南北兩種方向。住戶只可以沿著街道行走。各個街道之間的間隔相等。用(x,y)來表示住戶坐在的街區。例如(4,20),表示用戶在東西方向第4個街道,...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...