分享

Redis分布式缓存系列(三)- Redis中的Hash类型

 头号码甲 2021-03-13

本系列将和大家分享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类型高。


版权声明:如有雷同纯属巧合,如有侵权请及时联系本人修改,谢谢!!!

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多