NoSQL初探之人人都愛Redis:(2)Redis API與經常使用數據類型簡介

1、Redis API For .Net

  首先,不得不說Redis官方提供了衆多的API開發包,可是目前Redis官方版本不支持.Net直接進行鏈接,須要使用一些第三方的開源類庫。目前最流行的就是ServiceStack.Redis這個開源項目,其在GitHub上的下載地址爲:https://github.com/ServiceStack/ServiceStack.Redishtml

  進入下載頁面,點擊「Download Zip」按鈕,便可下載該API包。解壓該Zip包後,其實咱們所用到的只是其中的幾個DLL而已,打開build/release/MonoDevelop文件夾,看到裏邊還有一個zip包,這裏邊就是咱們所需的DLL了。git

  再次解壓這個Zip包,能夠看到其中包含以下圖所示的DLL文件,這幾個也是咱們今天所要引入VS的DLL庫,有了它們,咱們就能夠在程序端和Redis服務端進行對話了,是否是很贊?github

  這時,咱們就能夠在VS中新建一個控制檯項目,命名爲RedisDemo,而後新建一個Lib文件夾用來存放咱們的DLL文件,而後添加對這些DLL引用。至此,就是萬事俱備只欠東風了,咱們接下來會在程序中調用Redis客戶端和Redis服務端進行通訊,瞭解Redis API爲咱們提供的豐富的數據類型。redis

2、Redis中經常使用數據類型

  由上一篇博客可知,Redis目前提供五種數據類型:string(字符串)、list(鏈表)、Hash(哈希)、set(集合)及zset(sorted set)  (有序集合)。如今,咱們一一來看看這五種數據類型的基本使用方法。在開始介紹以前,咱們先使用剛剛引入的Redis API創建一個Redis客戶端對象,有了這個客戶端對象,咱們才能和Redis服務端進行通訊,且看下面的一行代碼。咱們須要事先指定好Redis服務端的IP地址和端口號,而後根據這兩個信息創建一個RedisClient的對象實例,經過這個實例所帶的方法和服務端通訊。安全

using System;
using System.Collections.Generic;
using ServiceStack.Redis;

namespace RedisDemo.FirstStart
{
    class Program
    {
        //Redis服務器IP地址
        static string localHostIP = "127.0.0.1";
        //Redis服務端口號
        static int redisServicePort = 6379;           

        static void Main(string[] args)
        {
            var redisClient = new RedisClient(localHostIP, redisServicePort);

            Console.ReadKey();
        }
    }
}

  2.1 String 字符串

  String是最經常使用的一種數據類型,普通的key/value存儲均可以歸爲此類 。一個Key對應一個Value,string類型是二進制安全的。Redis的string能夠包含任何數據,好比jpg圖片(生成二進制)或者序列化的對象。服務器

  在Redis中的基本操做以下所示:數據結構

     static void StringTypeDemo(RedisClient redisClient)
        {
            //向Redis中添加一個Key/Value對
            redisClient.Set<string>("username", "edisonchou");
            //從Redis中讀取一個Value值
            string userName = redisClient.Get<string>("username");

            Console.WriteLine("The value from Redis is {0}", userName);
        }

  運行效果以下:併發

  2.2 Hash 哈希

  Hash是一個string 類型的field和value的 映射表。Hash 特別適合存儲對象,相對於將對象的每一個字段存成單個string 類型。一個對象存儲在Hash類型中會佔用更少的內存,而且能夠更方便的存取整個對象。
  這裏借用 羣叔的描述,咱們簡單舉個實例來描述下Hash的應用場景,好比咱們要存儲一個用戶信息對象數據,包含如下信息:用戶ID爲查找的key,存儲的value用戶對象包含姓名,年齡,生日等信息,若是用普通的key/value結構來存儲,主要有如下2種存儲方式:
  第一種方式將用戶ID做爲查找key,把其餘信息封裝成一個對象以序列化的方式存儲,這種方式的缺點是, 增長了序列化/反序列化的開銷,而且在須要修改其中一項信息時,須要把整個對象取回,而且修改操做須要對併發進行保護,引入CAS等複雜問題。
  第二種方法是這個用戶信息對象有多少成員就存成多少個key-value對兒,用用戶ID+對應屬性的名稱做爲惟一標識來取得對應屬性的值,雖然省去了序列化開銷和併發問題,可是用戶ID爲重複存儲,若是存在大量這樣的數據, 內存浪費仍是很是可觀的
  所以,基於以上兩種方式的缺陷,Redis提供的Hash很好的解決了這個問題, Redis的Hash實際是內部存儲的Value爲一個HashMap,並提供了直接存取這個Map成員的接口,以下圖:
  也就是說,Key仍然是用戶ID, value是一個Map,這個Map的key是成員的屬性名,value是屬性值,這樣對數據的修改和存取均可以直接經過其內部Map的Key(Redis裏稱內部Map的key爲field), 也就是經過 key(用戶ID) + field(屬性標籤) 就能夠操做對應屬性數據了,既不須要重複存儲數據,也不會帶來序列化和併發修改控制的問題,也就很好的解決了問題。
  下面咱們在VS中來看看Hash類型如何Code:
        static void HashTypeDemo(RedisClient redisClient)
        {
            redisClient.SetEntryInHash("user", "userinfo", "cool boy");
            redisClient.SetEntryInHash("user", "useraccount", "5000");

            List<string> keyList = redisClient.GetHashKeys("user");

            foreach (string key in keyList)
            {
                Console.WriteLine(key);
                string value = redisClient.GetValueFromHash("user", key);
                Console.WriteLine("user:{0}:{1}", key, value);
            }
        }
  運行結果以下圖:

  2.3 List 鏈表

  Lst是一個鏈表結構,主要功能是push與pop,獲取一個範圍的全部的值等,操做中key理解爲鏈表名字。 Redis的List類型其實就是一個每一個子元素都是string類型的雙向鏈表,咱們能夠經過push或pop操做從鏈表的頭部或者尾部添加刪除元素,這樣List既能夠做爲棧,又能夠做爲隊列。它便可以支持反向查找和遍歷,更方便操做,不過帶來了部分額外的內存開銷。Redis內部的不少實現,包括髮送緩衝隊列等也都是用的這個數據結構。ssh

  (1)如今咱們首先來看看List做爲(Stack)棧類型的使用: ui

  那麼在VS中如何來Code呢?經過Push與Pop操做Stack

        static void StackTypeDemo(RedisClient redisClient)
        {
            redisClient.PushItemToList("userenname", "edisonchou");
            redisClient.PushItemToList("userenname", "wncudchou");
            redisClient.PushItemToList("userenname", "milkye");
            redisClient.PushItemToList("userenname", "dickgu");

            int length = redisClient.GetListCount("userenname");
            for (int i = 0; i < length; i++)
            {
                Console.WriteLine(redisClient.PopItemFromList("userenname"));
            }
        }

  運行效果以下:

  (2)下面咱們來看看List做爲(Queue)隊列的使用:

  那麼在VS中如何Code呢?經過DeQueue和EnQueue操做Queue

        static void QueueTypeDemo(RedisClient redisClient)
        {
            redisClient.EnqueueItemOnList("account", "馬雲");
            redisClient.EnqueueItemOnList("account", "馬化騰");
            redisClient.EnqueueItemOnList("account", "李彥宏");

            int length = redisClient.GetListCount("account");
            for (int i = 0; i < length; i++)
            {
                Console.WriteLine(redisClient.DequeueItemFromList("account"));
            }
        }

  運行效果以下:

  2.4 Set 集合

  Set是string類型的無序集合。set是經過hash table實現的,添加,刪除和查找,對集合咱們能夠取並集,交集,差集,能夠很是方便的實現如共同關注、共同喜愛、二度好友等功能,對上面的全部集合操做,你還可使用不一樣的命令選擇將結果返回給客戶端仍是存集到一個新的集合中。

  與List比較而言,set對外提供的功能與list相似是一個列表的功能,特殊之處在於set是能夠自動排重的,當你須要存儲一個列表數據,又不但願出現重複數據時,set是一個很好的選擇,而且set提供了判斷某個成員是否在一個set集合內的重要接口,這個也是list所不能提供的。

  那麼在VS中咱們使用Set來Code一下,先增長兩個Set集合,而後對其進行交集、並集與差集運算:

    static void SetTypeDemo(RedisClient redisClient)
        {
            redisClient.AddItemToSet("a3", "ddd");
            redisClient.AddItemToSet("a3", "ccc");
            redisClient.AddItemToSet("a3", "tttt");
            redisClient.AddItemToSet("a3", "sssh");
            redisClient.AddItemToSet("a3", "hhhh");
            redisClient.AddItemToSet("a4", "hhhh");
            redisClient.AddItemToSet("a4", "h777");

            Console.WriteLine("-------------求a3集合------------");

            HashSet<string> hashSet = redisClient.GetAllItemsFromSet("a3");
            foreach (string value in hashSet)
            {
                Console.WriteLine(value);
            }

            Console.WriteLine("-------------求並集------------");

            hashSet.Clear();
            hashSet = redisClient.GetUnionFromSets(new string[] { "a3", "a4" });
            foreach (string value in hashSet)
            {
                Console.WriteLine(value);
            }

            Console.WriteLine("-------------求交集------------");

            hashSet.Clear();
            hashSet = redisClient.GetIntersectFromSets(new string[] { "a3", "a4" });
            foreach (string value in hashSet)
            {
                Console.WriteLine(value);
            }

            Console.WriteLine("-------------求差集------------");

            hashSet.Clear();
            hashSet = redisClient.GetDifferencesFromSet("a3", new string[] { "a4" });
            foreach (string value in hashSet)
            {
                Console.WriteLine(value);
            }
        }

  運行效果以下:

  2.5 Sorted Set 有序集合

  Sorted Set 是set的一個升級版本,又被稱爲ZSet,它在set的基礎上增長了一個順序的屬性,這一屬性在添加修改。元素的時候能夠指定,每次指定後,zset(表示有序集合)會自動從新按新的值調整順序。 能夠理解爲有列的表,一列存 value,一列存順序。操做中key理解爲zset的名字。
  sorted set的使用場景與set相似,區別是 set不是自動有序的,而sorted set能夠經過用戶額外提供一個優先級(score)的參數來爲成員排序,而且是插入有序的,即自動排序。 當你須要一個有序的而且不重複的集合列表,那麼能夠選擇sorted set數據結構此外,還能夠用Sorted Sets來作帶權重的隊列,好比普通消息的score爲1,重要消息的score爲2,而後工做線程能夠選擇按score的倒序來獲取工做任務。讓重要的任務優先執行。
  下面,咱們在VS中編寫對Sorted Set的操做代碼,輸出時會按字母的有序順序輸出:
        static void SortedSetTypeDemo(RedisClient redisClient)
        {
            redisClient.AddItemToSortedSet("a5", "ffff");
            redisClient.AddItemToSortedSet("a5", "bbbb");
            redisClient.AddItemToSortedSet("a5", "gggg");
            redisClient.AddItemToSortedSet("a5", "cccc");
            redisClient.AddItemToSortedSet("a5", "waaa");

            List<string> list = redisClient.GetAllItemsFromSortedSet("a5");
            foreach (string str in list)
            {
                Console.WriteLine(str);
            }
        }

  運行效果以下:

3、小結

  Redis爲咱們提供了相比Memcached更爲豐富多樣的數據類型,使得Redis能夠用在多種多樣的應用場合,這也說明了爲何Redis在國內外各大互聯網名企中這麼受歡迎的緣由。本篇簡單地介紹和使用了各類數據類型,下一篇,咱們會針對1-2個具體應用場景來使用這些數據類型進行具體案例的Code。最後,仍是謝謝參考資料的原做者,站在大家的肩膀上,咱們才能看的更遠!

參考文獻

(1)傳智播客公開課,王承偉主講,http://bbs.itcast.cn/thread-26525-1-1.html

(2)羣叔,《Redis數據類型詳解及Redis適用場景》,http://www.cnblogs.com/qunshu/p/3196972.html

附件下載

(1)ServiceStack.Redis:http://pan.baidu.com/s/1sjtxe5v

 

相關文章
相關標籤/搜索