zoukankan      html  css  js  c++  java
  • 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

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

  • 相关阅读:
    学习笔录——大话设计模式——简单工厂模式
    学习笔录——大话设计模式——代理模式
    学习笔录——大话设计模式——装饰模式
    经典扫雷下载
    C# 实现敏感词过滤
    C# 时间戳的相关操作
    easyui-datetimebox 控件绑定双击事件实现自动选中当前日期时间
    OpenGL笔记(4)纹理
    LearnOpenGL笔记(3)着色器
    c# 值类型和引用类型 笔记
  • 原文地址:https://www.cnblogs.com/xyh9039/p/13987454.html
Copyright © 2011-2022 走看看