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

在前面介紹了三篇關於MongoDB數據庫的開發使用文章,嚴格來說這個不能歸類於MongoDB數據庫開發,不過Redis又有着和MongoDB數據庫很是密切的關係,它們二者很接近,Redis主要是內存中的NoSQL數據庫,用來提升性能的;MongoDB數據庫則是文件中的NoSQL數據庫,作數據序列號存儲使用的,它們二者關係密切又有所區別。本篇主要介紹Redis的安裝及使用,爲後面Redis和MongoDB數據庫的聯合使用先鋪下基礎。mysql

一、Redis基礎及安裝

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

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

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

   (1):snapshotting(快照)也是默認方式.(把數據作一個備份,將數據存儲到文件)sql

   (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

下載屬於本身平臺的版本便可

下載安裝後,打開運行界面,若是咱們往裏面添加鍵值的數據,那麼能夠看到裏面的數據了。

 

二、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數據庫的完美銜接,能夠整合一塊兒作的更好,爲相關的後臺提供更高效的數據處理操做,畢竟在互聯網的大環境下,性能是很是重要的。

相關文章
相關標籤/搜索