[你必須知道的NOSQL系列]專題二:Redis快速入門


一、前言

   在前一篇博文介紹了MongoDB基本操作,本來打算這篇博文繼續介紹MongoDB的相關內容的,例如索引,主從備份等內容的,但是發現這些內容都可以通過官方文檔都可以看到,並且都非常詳細,所以這里就不想繼續介紹了,需要用到的朋友到官方文檔進行查閱:http://docs.mongodb.org/manual/tutorial/remove-indexes/。本專題將介紹另一個NoSQL——Redis的相關內容。

二、Redis介紹

  關於Redis大家肯定多多少少都有所了解,Redis一般都用來做緩存的,當然也可以作為消息隊列。這里就直接網上一段比較好的介紹:

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

  Redis支持主從同步。數據可以從主服務器向任意數量的從服務器上同步,從服務器可以是關聯其他從服務器的主服務器。這使得Redis可執行單層樹復制。存盤可以有意無意的對數據進行寫操作。

Redis支持兩種持久化方式:

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

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

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

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

三、Windows下Redis的安裝

  Redis官方下載(官方地址:http://redis.io/download)只能用於Linux環境下,所以要在Windows環境下安裝Redis就不能從官方進行下載了。為了能夠在Windows平台安裝Redis,微軟的Microsoft Open Tech團隊為我們開發了Windows版本下Redis。下載地址為:https://github.com/MSOpenTech/redis,但是Microsoft Open Tech團隊開發的最新版本只能應用於64位操作系統,但是我使用的還是32位操作系統,那是不是我就不能安裝Redis了呢?幸好微軟之前開發的Redis之前版本還是支持32位系統的,所以我本機只能安裝之前的版本了。這里我選擇的是2.6版本,下載地址:https://github.com/MSOpenTech/redis/tree/2.6/bin/release。下載redisbin.zip文件之后直接解壓到指定目錄就完成了Redis的安裝了,解壓成功后,你將看到如下幾個Dll:

  • redis-server.exe:服務程序  
  • redis-check-dump.exe:本地數據庫檢查 
  • redis-check-aof.exe:更新日志檢查 
  • redis-benchmark.exe:性能測試,用以模擬同時由N個客戶端發送M個 SETs/GETs 查詢.
  • redis-cli.exe: 服務端開啟后,我們的客戶端就可以輸入各種命令測試了 

  接下來,只需要雙擊redis-server.exe程序就可以啟動Redis服務,在2.6版本中可以不指定config路徑,不像網上的Redis介紹文章都需要指定config文件,因為它們下載一般都是更早的版本,如2.4等版本。在2.6版本不需要特別指定config文件就可以啟動成功,啟動成功的界面如下圖所示:

  服務啟動成功后,我們就可以像MongoDB一樣,開啟redis-cli.exe客戶端程序要操作Redis服務器,關於使用redis-cli.exe客戶端命令的方式這里就不介紹了,更多可以參考官方文檔,因為對我們來說,更常用的是使用C#、Java來操作Redis服務。在第四部分我將介紹使用C#來操作Redis。

  一般服務我們都是用Windows Service來啟動的,對於最新版本的Redis安裝為Windows Service官方有詳細的介紹,由於這里我不是用的最新版本,並且還是32位的,所以這里我安裝Windows Service是通過sc(http://www.cnblogs.com/jankie/archive/2011/08/03/2126249.html)命令來安裝的,具體的安裝腳本如下所示:

sc create Redis start= auto DisplayName= Redis binpath= "F:\Study\No-Sql\Redis\redis-windows\RedisService.exe"

  其中RedisService是Redis注冊Windows服務的啟動程序,具體下載地址為:http://files.cnblogs.com/files/zhili/RedisService.zip

   通過上面的腳本就可以成功安裝Redis為Windows Service了,然后每次系統啟動的時候,就會自動開啟Redis服務,而不需要我們每次去手動運行redis-server.exe命令了。

四、C#如何操作Redis

   前面我們已經准備成功開啟Redis服務,其端口號為6379,接下來我們就看看如何使用C#語言來操作Redis。就如MongoDB一樣,要操作Redis服務,自然就需要下載C#的客戶端,這里通過Nuget下載了“ServiceStack.Redis”客戶端,引入成功之后,就可以使用C#來對Redis服務進行操作了。

  由於Redis一般是用來作為緩存的,也就是一般我們把一些不經常改變的數據通過Redis緩存起來,之后用戶的請求就不需要再訪問數據庫,而可以直接從Redis緩存中直接獲取,這樣就可以減輕數據庫服務器的壓力以及加快響應速度。既然是用來做緩存的,也就是通過指定key值來把對應Value保存起來,之后再根據key值來獲得之前緩存的值。具體的操作代碼如下所示,這里就不過多介紹了。

class Program
    {
        static void Main(string[] args)
        {
            //在Redis中存儲常用的5種數據類型:String,Hash,List,SetSorted set
            var client = new RedisClient("127.0.0.1", 6379);
            //AddString(client);
            //AddHash(client);
            //AddList(client);
            //AddSet(client);
            AddSetSorted(client);

            Console.ReadLine();
        }

        private static void AddString(RedisClient client)
        {
            var timeOut = new TimeSpan(0,0,0,30);
            client.Add("Test", "Learninghard", timeOut);
            while (true)
            {
                if (client.ContainsKey("Test"))
                {
                    Console.WriteLine("String Key: Test -Value: {0}, 當前時間: {1}", client.Get<string>("Test"), DateTime.Now);
                    Thread.Sleep(10000);
                }
                else
                {
                    Console.WriteLine("Value 已經過期了,當前時間:{0}", DateTime.Now);
                    break;
                }
            }

            var person = new Person() {Name = "Learninghard", Age = 26};
            client.Add("lh", person);
            var cachePerson = client.Get<Person>("lh");
            Console.WriteLine("Person's Name is : {0}, Age: {1}", cachePerson.Name, cachePerson.Age);
        }

        private static void AddHash(RedisClient client)
        {
            if (client == null) throw new ArgumentNullException("client");

            client.SetEntryInHash("HashId", "Name", "Learninghard");
            client.SetEntryInHash("HashId", "Age", "26");
            client.SetEntryInHash("HashId", "Sex", "");

            var hashKeys = client.GetHashKeys("HashId");
            foreach (var key in hashKeys)
            {
                Console.WriteLine("HashId--Key:{0}", key);
            }

            var haskValues = client.GetHashValues("HashId");
            foreach (var value in haskValues)
            {
                Console.WriteLine("HashId--Value:{0}", value);
            }

            var allKeys = client.GetAllKeys(); //獲取所有的key。
            foreach (var key in allKeys)
            {
                Console.WriteLine("AllKey--Key:{0}", key);
            }
        }

        private static void AddList(RedisClient client)
        {
            if (client == null) throw new ArgumentNullException("client");

            client.EnqueueItemOnList("QueueListId", "1.Learnghard");  //入隊
            client.EnqueueItemOnList("QueueListId", "2.張三");
            client.EnqueueItemOnList("QueueListId", "3.李四");
            client.EnqueueItemOnList("QueueListId", "4.王五");
            var queueCount = client.GetListCount("QueueListId");

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

            client.PushItemToList("StackListId", "1.Learninghard");  //入棧
            client.PushItemToList("StackListId", "2.張三");
            client.PushItemToList("StackListId", "3.李四");
            client.PushItemToList("StackListId", "4.王五");

            var stackCount = client.GetListCount("StackListId");
            for (var i = 0; i < stackCount; i++)
            {
                Console.WriteLine("StackListId出棧值:{0}", client.PopItemFromList("StackListId"));   //出棧(棧先進后出)
            }
        }

      
        //它是string類型的無序集合。set是通過hash table實現的,添加,刪除和查找,對集合我們可以取並集,交集,差集
        private static void AddSet(RedisClient client)
        {
            if (client == null) throw new ArgumentNullException("client");

            client.AddItemToSet("Set1001", "A");
            client.AddItemToSet("Set1001", "B");
            client.AddItemToSet("Set1001", "C");
            client.AddItemToSet("Set1001", "D");
            var hastset1 = client.GetAllItemsFromSet("Set1001");
            foreach (var item in hastset1)
            {
                Console.WriteLine("Set無序集合Value:{0}", item); //出來的結果是無須的
            }

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

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

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

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

        }

        /*
        sorted set 是set的一個升級版本,它在set的基礎上增加了一個順序的屬性,這一屬性在添加修改.元素的時候可以指定,
        * 每次指定后,zset(表示有序集合)會自動重新按新的值調整順序。可以理解為有列的表,一列存 value,一列存順序。操作中key理解為zset的名字.
        */
        private static void AddSetSorted(RedisClient client)
        {
            if (client == null) throw new ArgumentNullException("client");

            client.AddItemToSortedSet("SetSorted1001", "A");
            client.AddItemToSortedSet("SetSorted1001", "B");
            client.AddItemToSortedSet("SetSorted1001", "C");
            var listSetSorted = client.GetAllItemsFromSortedSet("SetSorted1001");
            foreach (var item in listSetSorted)
            {
                Console.WriteLine("SetSorted有序集合{0}", item);
            }

            client.AddItemToSortedSet("SetSorted1002", "A", 400);
            client.AddItemToSortedSet("SetSorted1002", "D", 200);
            client.AddItemToSortedSet("SetSorted1002", "B", 300);

            // 升序獲取第一個值:"D"
            var list = client.GetRangeFromSortedSet("SetSorted1002", 0, 0);

            foreach (var item in list)
            {
                Console.WriteLine(item);
            }

            //降序獲取第一個值:"A"
            list = client.GetRangeFromSortedSetDesc("SetSorted1002", 0, 0);

            foreach (var item in list)
            {
                Console.WriteLine(item);
            }
        }
    }

    class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }

  如何要想查看自己操作是否成功,也可以像MongoDB那樣下載一個客戶端工具,這里推薦一款Redis Desktop Manager。這個工具就相當於SQL Server的客戶端工具一樣。通過這款工具可以查看Redis服務器中保存的數據和對應格式。其使用也非常簡單,只需要添加一個Redis服務連接即可。該工具的下載地址為:http://pan.baidu.com/s/1sjp55Ul

五、小結

   到此,本專題的內容就介紹結束了。關於Redis更深入的內容我覺得大家可以在項目中用到了可以自己深入研究,這里只是作為一個快速入門的教程。所以該NoSQL系列可能會先告一段落,接下來將計划一個全新的系列:Web API和Windows Azure系列。

  本文所有源碼下載地址:http://files.cnblogs.com/files/zhili/RedisQuickStart.zip


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM