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


本系列將和大家分享Redis分布式緩存,本章主要簡單介紹下Redis中的Hash類型。

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

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

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

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

方案2:多個key-value。

/// <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雖然修改起來方便了,但是缺點就是浪費空間,效率也不高。

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

首先先給大家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 其它
    }
}

使用如下:

/// <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/1B_XUM4Eqc81CJdjufOWS9A 
提取碼:a78n

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

版權聲明:如有雷同純屬巧合,如有侵權請及時聯系本人修改,謝謝!!!


免責聲明!

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



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