Redis分佈式緩存系列(三)- Redis中的Hash類型

本系列將和你們分享Redis分佈式緩存,本章主要簡單介紹下Redis中的Hash類型。html

散列Hash:相似dictionary,經過索引快速定位到指定元素的,耗時均等,跟string的區別在於不用反序列化,直接修改某個字段。redis

存儲形式: hashId-{key:value;key:value;key:value;}緩存

在正式開始介紹Hash類型以前,咱們先來思考一個問題,如何使用咱們上一篇介紹的String類型來緩存和修改一個學生對象信息。你們能想到的可能有如下兩種方案:分佈式

方案1:查詢-反序列化-修改-序列化-存儲。性能

方案2:多個key-value。spa

/// <summary>
/// 學生類
/// </summary>
public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Remark { get; set; }
    public string Description { get; set; }
}
/// <summary>
/// 散列Hash:相似dictionary,經過索引快速定位到指定元素的,耗時均等,跟string的區別在於不用反序列化,直接修改某個字段
/// 存儲形式: hashId-{key:value;key:value;key:value;}
/// 能夠一次性查找實體,也能夠單個查找,還能夠單個修改
/// </summary>
public static void ShowHash()
{
    var student = new Student()
    {
        Id = 10000,
        Name = "TianYa",
        Description = "一年級",
        Remark = "優秀"
    };

    //使用String類型緩存學生對象信息
    using (RedisStringService service = new RedisStringService())
    {
        //方案1
        //查詢-反序列化-修改-序列化-存儲
        //該方案修改很不方便
        service.Set("student", student);
        var stu = service.Get<Student>("student");
        stu.Remark = "很優秀";
        service.Set("student", stu);

        //方案2
        //多個key-value
        //string類型的value最小值是512byte,即便只保存一個1,也是要佔用512byte空間的
        //該方案修改方便,可是數據項會不少,浪費空間
        service.Set($"student_{student.Id}_Name", student.Name);
        service.Set($"student_{student.Id}_Description", student.Description);
        service.Set($"student_{student.Id}_Remark", student.Remark);

        service.Set($"student_{student.Id}_Remark", "很優秀"); //修改方便
    }
}

從上面的代碼中你會發現這2種方案都不是很合適,方案1修改起來很不方便,而方案2雖然修改起來方便了,可是缺點就是浪費空間,效率也不高。code

那有沒有更好的解決方案呢?答案:確定是有的,那就是接下來咱們要講的Hash類型。htm

首先先給你們Show一波Redis中與Hash類型相關的API:對象

using System.Collections.Generic;

namespace TianYa.Redis.Service
{
    /// <summary>
    /// 散列Hash:相似dictionary,經過索引快速定位到指定元素的,耗時均等,跟string的區別在於不用反序列化,直接修改某個字段
    /// 存儲形式: hashId-{key:value;key:value;key:value;}
    /// 能夠一次性查找實體,也能夠單個查找,還能夠單個修改
    /// </summary>
    public class RedisHashService : RedisBase
    {
        #region 添加

        /// <summary>
        /// 向hashId集合中添加key/value
        /// </summary>       
        public bool SetEntryInHash(string hashId, string key, string value)
        {
            return base._redisClient.SetEntryInHash(hashId, key, value);
        }

        /// <summary>
        /// 若是hashId集合中存在key則不添加,返回false,
        /// 若是不存在則添加key/value,返回true
        /// </summary>
        public bool SetEntryInHashIfNotExists(string hashId, string key, string value)
        {
            return base._redisClient.SetEntryInHashIfNotExists(hashId, key, value);
        }

        /// <summary>
        /// 存儲對象T t到hash集合中
        /// 須要包含Id,而後用Id獲取
        /// </summary>
        public void StoreAsHash<T>(T t)
        {
            base._redisClient.StoreAsHash<T>(t);
        }

        #endregion 添加

        #region 獲取

        /// <summary>
        /// 獲取對象T中Id爲id的數據
        /// </summary>
        public T GetFromHash<T>(object id)
        {
            return base._redisClient.GetFromHash<T>(id);
        }

        /// <summary>
        /// 獲取全部hashId數據集的key/value數據集合
        /// </summary>
        public Dictionary<string, string> GetAllEntriesFromHash(string hashId)
        {
            return base._redisClient.GetAllEntriesFromHash(hashId);
        }

        /// <summary>
        /// 獲取hashId數據集中的數據總數
        /// </summary>
        public long GetHashCount(string hashId)
        {
            return base._redisClient.GetHashCount(hashId);
        }

        /// <summary>
        /// 獲取hashId數據集中全部key的集合
        /// </summary>
        public List<string> GetHashKeys(string hashId)
        {
            return base._redisClient.GetHashKeys(hashId);
        }

        /// <summary>
        /// 獲取hashId數據集中的全部value集合
        /// </summary>
        public List<string> GetHashValues(string hashId)
        {
            return base._redisClient.GetHashValues(hashId);
        }

        /// <summary>
        /// 獲取hashId數據集中指定key的value數據
        /// </summary>
        public string GetValueFromHash(string hashId, string key)
        {
            return base._redisClient.GetValueFromHash(hashId, key);
        }

        /// <summary>
        /// 獲取hashId數據集中多個key的value集合
        /// </summary>
        public List<string> GetValuesFromHash(string hashId, string[] keys)
        {
            return base._redisClient.GetValuesFromHash(hashId, keys);
        }

        #endregion 獲取

        #region 刪除

        /// <summary>
        /// 刪除hashId數據集中的key數據
        /// </summary>
        public bool RemoveEntryFromHash(string hashId, string key)
        {
            return base._redisClient.RemoveEntryFromHash(hashId, key);
        }

        #endregion 刪除

        #region 其它

        /// <summary>
        /// 判斷hashId數據集中是否存在key的數據
        /// </summary>
        public bool HashContainsEntry(string hashId, string key)
        {
            return base._redisClient.HashContainsEntry(hashId, key);
        }

        /// <summary>
        /// 給hashId數據集key的value加incrementBy,返回相加後的數據
        /// </summary>
        public double IncrementValueInHash(string hashId, string key, double incrementBy)
        {
            return base._redisClient.IncrementValueInHash(hashId, key, incrementBy);
        }

        #endregion 其它
    }
}

使用以下:blog

/// <summary>
/// 散列Hash:相似dictionary,經過索引快速定位到指定元素的,耗時均等,跟string的區別在於不用反序列化,直接修改某個字段
/// 存儲形式: hashId-{key:value;key:value;key:value;}
/// 能夠一次性查找實體,也能夠單個查找,還能夠單個修改
/// </summary>
public static void ShowHash()
{
    var student = new Student()
    {
        Id = 10000,
        Name = "TianYa",
        Description = "一年級",
        Remark = "優秀"
    };

    //使用String類型緩存學生對象信息
    using (RedisStringService service = new RedisStringService())
    {
        //方案1
        //查詢-反序列化-修改-序列化-存儲
        //該方案修改很不方便
        service.Set("student", student);
        var stu = service.Get<Student>("student");
        stu.Remark = "很優秀";
        service.Set("student", stu);

        //方案2
        //多個key-value
        //string類型的value最小值是512byte,即便只保存一個1,也是要佔用512byte空間的
        //該方案修改方便,可是數據項會不少,浪費空間
        service.Set($"student_{student.Id}_Name", student.Name);
        service.Set($"student_{student.Id}_Description", student.Description);
        service.Set($"student_{student.Id}_Remark", student.Remark);

        service.Set($"student_{student.Id}_Remark", "很優秀"); //修改方便
    }

    //使用Hash類型緩存學生對象信息
    //hash是一種zipmap存儲,數據緊密排列,能夠節約空間
    //1 節約空間  2 更新方便
    //若是實體類型是帶Id,能夠直接實體存儲和讀取
    using (RedisHashService service = new RedisHashService())
    {
        service.FlushAll();
        //能夠反射遍歷作一下
        service.SetEntryInHash($"student_{student.Id}", "Name", student.Name);
        service.SetEntryInHash($"student_{student.Id}", "Description", student.Description);
        service.SetEntryInHash($"student_{student.Id}", "Remark", student.Remark);

        var keys = service.GetHashKeys($"student_{student.Id}");
        var values = service.GetHashValues($"student_{student.Id}");
        var keyValues = service.GetAllEntriesFromHash($"student_{student.Id}");

        Console.WriteLine(service.GetValueFromHash($"student_{student.Id}", "Name"));
        Console.WriteLine(service.GetValueFromHash($"student_{student.Id}", "Description"));
        service.RemoveEntryFromHash($"student_{student.Id}", "Description");
        Console.WriteLine(service.GetValueFromHash($"student_{student.Id}", "Description"));

        //下面必須是實體含ID屬性的才能夠怎麼使用
        service.StoreAsHash<Student>(student);
        var result = service.GetFromHash<Student>(student.Id);
    }
}

運行結果以下:

Hash是一種zipmap存儲,數據緊密排列,能夠節約空間,更新也方便,並且性能會比string類型高。

至此本文就所有介紹完了,若是以爲對您有所啓發請記得點個贊哦!!!

 

Demo源碼:

連接:https://pan.baidu.com/s/1C10DIILkSgV90lTXJOizLw 
提取碼:ucoe

此文由博主精心撰寫轉載請保留此原文連接:https://www.cnblogs.com/xyh9039/p/13987454.html

相關文章
相關標籤/搜索