-
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
栏目列表
最新更新
nodejs爬虫
Python正则表达式完全指南
爬取豆瓣Top250图书数据
shp 地图文件批量添加字段
爬虫小试牛刀(爬取学校通知公告)
【python基础】函数-初识函数
【python基础】函数-返回值
HTTP请求:requests模块基础使用必知必会
Python初学者友好丨详解参数传递类型
如何有效管理爬虫流量?
SQL SERVER中递归
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
这是目前我见过最好的跨域解决方案!
减少回流与重绘
减少回流与重绘
如何使用KrpanoToolJS在浏览器切图
performance.now() 与 Date.now() 对比
一款纯 JS 实现的轻量化图片编辑器
关于开发 VS Code 插件遇到的 workbench.scm.
前端设计模式——观察者模式
前端设计模式——中介者模式
创建型-原型模式