本系列將和大家分享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/1C10DIILkSgV90lTXJOizLw 提取碼:ucoe
此文由博主精心撰寫轉載請保留此原文鏈接:https://www.cnblogs.com/xyh9039/p/13987454.html
著作權宣告:如有雷同純屬巧合,如有侵權請及時聯系本人修改,謝謝!!!
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/220836.html
標籤:.NET技术
