zoukankan      html  css  js  c++  java
  • c# redis系列二

    Hash

    Hash:key--Dictionary,

    1 节约空间(zipmap的紧密摆放的存储模式)

    2 更新/访问方便(hashid+key) Hash数据很像关系型数据库的表的一行数据, 但是字段是可以随意定制的,没有严格约束的,非常灵活

    如果说我们要存储一个模型,如果还是存储string类型的话就得将其序列化,使用的时候取出来之后还是要再次反序列化,这样太麻烦了。

    Hash:类似dictionary,通过索引快速定位到指定元素的,耗时均等,跟string的区别在于不用反序列化,直接修改某个字段;string的话要么是 001:序列化整个实体,要么是 001_name: 001_pwd: 多个key-value,Hash的话,一个hashid-{key:value;key:value;key:value;}可以一次性查找实体,也可以单个,还可以单个修改

    如果是存string类型的话,后面做更改的话就需要全部取出来,然后更改,更改完之后再重新存储,这样的话就会存在问题,万一更改过程中出现其他问题,比如多线程之类的导致其他数据出现问题。如果使用hash的话可以直接更改指定元素,不必取出,保证了原子性,性能还高。

    模型类:

        public class UserInfo
        {
            public int Id { get; set; }
            public string Name { get; set; }
            public string Account { get; set; }
            public string Password { get; set; }
            public string Email { get; set; }
            public string Address { get; set; }
            public long QQ { get; set; }
        }

    string类型示例:

    {
                        //service.FlushAll();//删除所有的Redis缓存
                        string key = $"userInfo_{user.Id}";
                        //这是redis内部自动对UserInfo做了序列化
                        service.Set<UserInfo>(key, user);
                        //取出来也是redis内部做的反序列化
                        List<UserInfo> userList = service.Get<UserInfo>(new List<string>() { key });
                        UserInfo updateUser = userList.FirstOrDefault();
                        updateUser.Account = "Admin";
                        service.Set<UserInfo>(key, updateUser);
                    }

    hash:

       using (RedisHashService service = new RedisHashService())
                {
                    service.FlushAll();
                    service.SetEntryInHash($"UserInfo_{user.Id}", "Name", user.Name);
                    service.SetEntryInHash($"UserInfo_{user.Id}", "Account", user.Account);
                    //如果在这个hashid中已经存在一个key,再次执行SetEntryInHash方法就会覆盖上一个值,也可以当做修改方法使用
                    service.SetEntryInHash($"UserInfo_{user.Id}", "Name", user.Address);
                    service.SetEntryInHash($"UserInfo_{user.Id}", "Name", user.Email);
                    service.GetValueFromHash($"UserInfo_{user.Id}", "Name");
                    //目标是最好是一个Api 去定位到某一个数据,直接在Redis 层面就给改掉!
                    //Hash存储是有Api 直接修改某一个;
                }

     hash存储是这种结构:

     Set存储

     

    Set存储value值自动去重,使用场景: IP统计去重; 添加好友申请; 投票限制; 点赞;

    封装的一些常用的api:

      /// <summary>
        /// Set:用哈希表来保持字符串的唯一性,没有先后顺序,存储一些集合性的数据
        /// 1.共同好友、二度好友
        /// 2.利用唯一性,可以统计访问网站的所有独立 IP
        /// </summary>
        public class RedisSetService : RedisBase
        {
            #region 添加
            /// <summary>
            /// key集合中添加value值
            /// </summary>
            public void Add(string key, string value)
            {
                base.iClient.AddItemToSet(key, value);
            }
            /// <summary>
            /// key集合中添加list集合
            /// </summary>
            public void Add(string key, List<string> list)
            {
                base.iClient.AddRangeToSet(key, list);
    
            }
            #endregion
    
            #region 获取
            /// <summary>
            /// 随机获取key集合中的一个值
            /// </summary>
            public string GetRandomItemFromSet(string key)
            {
                return base.iClient.GetRandomItemFromSet(key);
            }
            /// <summary>
            /// 获取key集合值的数量
            /// </summary>
            public long GetCount(string key)
            {
                return base.iClient.GetSetCount(key);
            }
            /// <summary>
            /// 获取所有key集合的值
            /// </summary>
            public HashSet<string> GetAllItemsFromSet(string key)
            {
                return base.iClient.GetAllItemsFromSet(key);
            }
            #endregion
    
            #region 删除
            /// <summary>
            /// 随机删除key集合中的一个值
            /// </summary>
            public string RandomRemoveItemFromSet(string key)
            {
                return base.iClient.PopItemFromSet(key);
            }
            /// <summary>
            /// 删除key集合中的value
            /// </summary>
            public void RemoveItemFromSet(string key, string value)
            {
                base.iClient.RemoveItemFromSet(key, value);
            }
            #endregion
    
            #region 其它
            /// <summary>
            /// 从fromkey集合中移除值为value的值,并把value添加到tokey集合中
            /// </summary>
            public void MoveBetweenSets(string fromkey, string tokey, string value)
            {
                base.iClient.MoveBetweenSets(fromkey, tokey, value);
            }
            /// <summary>
            /// 返回keys多个集合中的并集,返还hashset
            /// </summary>
            public HashSet<string> GetUnionFromSets(params string[] keys)
            {
                return base.iClient.GetUnionFromSets(keys);
            }
            /// <summary>
            /// 返回keys多个集合中的交集,返还hashset
            /// </summary>
            public HashSet<string> GetIntersectFromSets(params string[] keys)
            {
                return base.iClient.GetIntersectFromSets(keys);
            }
            /// <summary>
            /// 返回keys多个集合中的差集,返还hashset
            /// </summary>
            /// <param name="fromKey">原集合</param>
            /// <param name="keys">其他集合</param>
            /// <returns>出现在原集合,但不包含在其他集合</returns>
            public HashSet<string> GetDifferencesFromSet(string fromKey, params string[] keys)
            {
                return base.iClient.GetDifferencesFromSet(fromKey,keys);
            }
            /// <summary>
            /// keys多个集合中的并集,放入newkey集合中
            /// </summary>
            public void StoreUnionFromSets(string newkey, string[] keys)
            {
                base.iClient.StoreUnionFromSets(newkey, keys);
            }
            /// <summary>
            /// 把fromkey集合中的数据与keys集合中的数据对比,fromkey集合中不存在keys集合中,则把这些不存在的数据放入newkey集合中
            /// </summary>
            public void StoreDifferencesFromSet(string newkey, string fromkey, string[] keys)
            {
                base.iClient.StoreDifferencesFromSet(newkey, fromkey, keys);
            }
            #endregion
        }

     一些简单的api方法:

          using (RedisSetService service = new RedisSetService())
                    {
                        service.FlushAll();//清理全部数据
    
                        service.Add("advanced", "111");
                        service.Add("advanced", "112");
                        service.Add("advanced", "114");
                        service.Add("advanced", "114");
                        service.Add("advanced", "115");
                        service.Add("advanced", "115");
                        service.Add("advanced", "113");
    
                        var result = service.GetAllItemsFromSet("advanced");
                        //随机获取key其中一个value
                        var random = service.GetRandomItemFromSet("advanced");
                        service.GetCount("advanced");//独立的ip数
                        //删除指定数据
                        service.RemoveItemFromSet("advanced", "114");
    
                        {
                            service.Add("begin", "111");
                            service.Add("begin", "112");
                            service.Add("begin", "115");
    
                            service.Add("end", "111");
                            service.Add("end", "114");
                            service.Add("end", "113");
                            //获取begin和end中的 交集
                            var result1 = service.GetIntersectFromSets("begin", "end");
                            //获取begin和end中的 差集
                            var result2 = service.GetDifferencesFromSet("begin", "end");
                            //获取begin和end中的 并集,就是2者
                            var result3 = service.GetUnionFromSets("begin", "end");
                            //共同好友   共同关注
                        }
                    }

      set存储的格式:

     下面列举了一个添加好友的一个例子:

         public static void Show()
            {
                using (RedisSetService service = new RedisSetService())
                {
                    service.FlushAll();
                    service.Add("Richard", "云怀");
                    service.Add("Richard", "fresh");
                    service.Add("Richard", "腾坤");
                    service.Add("Richard", "心有所属");
                    service.Add("Richard", "莎士比亚");
    
                    service.Add("fresh", "奥利给");
                    service.Add("fresh", "明日梦");
                    service.Add("fresh", "棒棒糖");
                    service.Add("fresh", "放下");
                    service.Add("fresh", "阳光下的微信");
                    service.Add("fresh", "腾坤");
                    //1.查询共同好友; 求交集
                    var resut1 = service.GetIntersectFromSets("Richard", "fresh");//
                    //2.好友推荐/可能认识人,这是给Richard推荐的  返回keys多个集合中的差集,返还hashset 出现在fresh集合中,但不包含在Richard集合中
                    var resut2 = service.GetDifferencesFromSet("fresh", "Richard");
                    //同上
                    var resut3 = service.GetDifferencesFromSet("Richard", "fresh");//
                    //汇总所有的  并集
                    var result4 = service.GetUnionFromSets("Richard", "fresh");
    
                }
    
            }

     ZSet存储

     

    可以去重复还可以排序。比如排行榜的时候可以使用!

    封装的一些常用的api类:

     /// <summary>
        /// Sorted Sets是将 Set 中的元素增加了一个权重参数 score,使得集合中的元素能够按 score 进行有序排列
        /// 1.带有权重的元素,比如一个游戏的用户得分排行榜
        /// 2.比较复杂的数据结构,一般用到的场景不算太多
        /// </summary>
        public class RedisZSetService : RedisBase
        {
            #region 添加
            /// <summary>
            /// 添加key/value,默认分数是从1.多*10的9次方以此递增的,自带自增效果
            /// </summary>
            public bool Add(string key, string value)
            {
                return base.iClient.AddItemToSortedSet(key, value);
            }
            /// <summary>
            /// 添加key/value,并设置value的分数
            /// </summary>
            public bool AddItemToSortedSet(string key, string value, double score)
            {
                return base.iClient.AddItemToSortedSet(key, value, score);
            }
            /// <summary>
            /// 为key添加values集合,values集合中每个value的分数设置为score
            /// </summary>
            public bool AddRangeToSortedSet(string key, List<string> values, double score)
            {
                return base.iClient.AddRangeToSortedSet(key, values, score);
            }
            /// <summary>
            /// 为key添加values集合,values集合中每个value的分数设置为score
            /// </summary>
            public bool AddRangeToSortedSet(string key, List<string> values, long score)
            {
                return base.iClient.AddRangeToSortedSet(key, values, score);
            }
            #endregion
    
            #region 获取
            /// <summary>
            /// 获取key的所有集合
            /// </summary>
            public List<string> GetAll(string key)
            {
                return base.iClient.GetAllItemsFromSortedSet(key);
            }
            /// <summary>
            /// 获取key的所有集合,倒叙输出
            /// </summary>
            public List<string> GetAllDesc(string key)
            {
                return base.iClient.GetAllItemsFromSortedSetDesc(key);
            }
            /// <summary>
            /// 获取集合,带分数
            /// </summary>
            public IDictionary<string, double> GetAllWithScoresFromSortedSet(string key)
            {
                return base.iClient.GetAllWithScoresFromSortedSet(key);
            }
            /// <summary>
            /// 获取key为value的下标值
            /// </summary>
            public long GetItemIndexInSortedSet(string key, string value)
            {
                return base.iClient.GetItemIndexInSortedSet(key, value);
            }
            /// <summary>
            /// 倒叙排列获取key为value的下标值
            /// </summary>
            public long GetItemIndexInSortedSetDesc(string key, string value)
            {
                return base.iClient.GetItemIndexInSortedSetDesc(key, value);
            }
            /// <summary>
            /// 获取key为value的分数
            /// </summary>
            public double GetItemScoreInSortedSet(string key, string value)
            {
                return base.iClient.GetItemScoreInSortedSet(key, value);
            }
            /// <summary>
            /// 获取key所有集合的数据总数
            /// </summary>
            public long GetSortedSetCount(string key)
            {
                return base.iClient.GetSortedSetCount(key);
            }
            /// <summary>
            /// key集合数据从分数为fromscore到分数为toscore的数据总数
            /// </summary>
            public long GetSortedSetCount(string key, double fromScore, double toScore)
            {
                return base.iClient.GetSortedSetCount(key, fromScore, toScore);
            }
            /// <summary>
            /// 获取key集合从高分到低分排序数据,分数从fromscore到分数为toscore的数据
            /// </summary>
            public List<string> GetRangeFromSortedSetByHighestScore(string key, double fromscore, double toscore)
            {
                return base.iClient.GetRangeFromSortedSetByHighestScore(key, fromscore, toscore);
            }
            /// <summary>
            /// 获取key集合从低分到高分排序数据,分数从fromscore到分数为toscore的数据
            /// </summary>
            public List<string> GetRangeFromSortedSetByLowestScore(string key, double fromscore, double toscore)
            {
                return base.iClient.GetRangeFromSortedSetByLowestScore(key, fromscore, toscore);
            }
            /// <summary>
            /// 获取key集合从高分到低分排序数据,分数从fromscore到分数为toscore的数据,带分数
            /// </summary>
            public IDictionary<string, double> GetRangeWithScoresFromSortedSetByHighestScore(string key, double fromscore, double toscore)
            {
                return base.iClient.GetRangeWithScoresFromSortedSetByHighestScore(key, fromscore, toscore);
            }
            /// <summary>
            ///  获取key集合从低分到高分排序数据,分数从fromscore到分数为toscore的数据,带分数
            /// </summary>
            public IDictionary<string, double> GetRangeWithScoresFromSortedSetByLowestScore(string key, double fromscore, double toscore)
            {
                return base.iClient.GetRangeWithScoresFromSortedSetByLowestScore(key, fromscore, toscore);
            }
            /// <summary>
            ///  获取key集合数据,下标从fromRank到分数为toRank的数据
            /// </summary>
            public List<string> GetRangeFromSortedSet(string key, int fromRank, int toRank)
            {
                return base.iClient.GetRangeFromSortedSet(key, fromRank, toRank);
            }
            /// <summary>
            /// 获取key集合倒叙排列数据,下标从fromRank到分数为toRank的数据
            /// </summary>
            public List<string> GetRangeFromSortedSetDesc(string key, int fromRank, int toRank)
            {
                return base.iClient.GetRangeFromSortedSetDesc(key, fromRank, toRank);
            }
            /// <summary>
            /// 获取key集合数据,下标从fromRank到分数为toRank的数据,带分数
            /// </summary>
            public IDictionary<string, double> GetRangeWithScoresFromSortedSet(string key, int fromRank, int toRank)
            {
                return base.iClient.GetRangeWithScoresFromSortedSet(key, fromRank, toRank);
            }
            /// <summary>
            ///  获取key集合倒叙排列数据,下标从fromRank到分数为toRank的数据,带分数
            /// </summary>
            public IDictionary<string, double> GetRangeWithScoresFromSortedSetDesc(string key, int fromRank, int toRank)
            {
                return base.iClient.GetRangeWithScoresFromSortedSetDesc(key, fromRank, toRank);
            }
            #endregion
    
            #region 删除
            /// <summary>
            /// 删除key为value的数据
            /// </summary>
            public bool RemoveItemFromSortedSet(string key, string value)
            {
                return base.iClient.RemoveItemFromSortedSet(key, value);
            }
            /// <summary>
            /// 删除下标从minRank到maxRank的key集合数据
            /// </summary>
            public long RemoveRangeFromSortedSet(string key, int minRank, int maxRank)
            {
                return base.iClient.RemoveRangeFromSortedSet(key, minRank, maxRank);
            }
            /// <summary>
            /// 删除分数从fromscore到toscore的key集合数据
            /// </summary>
            public long RemoveRangeFromSortedSetByScore(string key, double fromscore, double toscore)
            {
                return base.iClient.RemoveRangeFromSortedSetByScore(key, fromscore, toscore);
            }
            /// <summary>
            /// 删除key集合中分数最大的数据
            /// </summary>
            public string PopItemWithHighestScoreFromSortedSet(string key)
            {
                return base.iClient.PopItemWithHighestScoreFromSortedSet(key);
            }
            /// <summary>
            /// 删除key集合中分数最小的数据
            /// </summary>
            public string PopItemWithLowestScoreFromSortedSet(string key)
            {
                return base.iClient.PopItemWithLowestScoreFromSortedSet(key);
            }
            #endregion
    
            #region 其它
            /// <summary>
            /// 判断key集合中是否存在value数据
            /// </summary>
            public bool SortedSetContainsItem(string key, string value)
            {
                return base.iClient.SortedSetContainsItem(key, value);
            }
            /// <summary>
            /// 为key集合值为value的数据,分数加scoreby,返回相加后的分数
            /// </summary>
            public double IncrementItemInSortedSet(string key, string value, double scoreBy)
            {
                return base.iClient.IncrementItemInSortedSet(key, value, scoreBy);
            }
            /// <summary>
            /// 获取keys多个集合的交集,并把交集添加的newkey集合中,返回交集数据的总数
            /// </summary>
            public long StoreIntersectFromSortedSets(string newkey, string[] keys)
            {
                return base.iClient.StoreIntersectFromSortedSets(newkey, keys);
            }
            /// <summary>
            /// 获取keys多个集合的并集,并把并集数据添加到newkey集合中,返回并集数据的总数
            /// </summary>
            public long StoreUnionFromSortedSets(string newkey, string[] keys)
            {
                return base.iClient.StoreUnionFromSortedSets(newkey, keys);
            }
            #endregion
        }

    简单调用对应的一些常用api:

                    using (RedisZSetService service = new RedisZSetService())
                    {
                        service.FlushAll();//清理全部数据
                        //添加之后会默认一个score,默认递增
                        service.Add("advanced", "1");
                        service.Add("advanced", "2");
                        service.Add("advanced", "5");
                        service.Add("advanced", "4");
                        service.Add("advanced", "7");
                        service.Add("advanced", "5");
                        service.Add("advanced", "9");
    
                        var result1 = service.GetAll("advanced");
                        //获取key为advanced的集合信息,倒序输出
                        var result2 = service.GetAllDesc("advanced");
                        //也可以手动指定score值,默认按照score值递增
                        service.AddItemToSortedSet("Sort", "BY", 123234);
                        service.AddItemToSortedSet("Sort", "走自己的路", 123);
                        service.AddItemToSortedSet("Sort", "redboy", 45);
                        service.AddItemToSortedSet("Sort", "大蛤蟆", 7567);
                        service.AddItemToSortedSet("Sort", "路人甲", 9879);
                        var result3 = service.GetAllWithScoresFromSortedSet("Sort");
    
                        //交叉并
                    }

      redis可视化工具中查看到的数据:

     

    接下来模拟一个排行榜的场景,比如一个直播间中的观众的礼物排行榜,这东西是实时的刷新的,不能一直来刷新数据库,所以可以用redis,并且使用zset来存储:

        /// <summary>
        /// 直播平台:很多频道---不同的房间/主播
        ///           刷小礼物!
        ///            
        /// 排行榜:频道排行!平台的排行!房间排行榜!  需要实时展示数据!
        /// Redis--Zset;排序
        /// 
        /// </summary>
        public class RankManager
        {
    
            //模拟的房间的听众
            private static List<string> userList = new List<string>()
            {
                "棒棒糖","苏洋","思索","奥利给","Alex","君临天下"
            };
    
            public static void Show()
            {
                using (RedisZSetService service = new RedisZSetService())
                {
                    service.FlushAll();
                    Task.Run(() => //刷礼物---每隔2秒钟就刷一个礼物
                    {
                        while (true)
                        {
                            foreach (var user in userList)
                            {
                                Thread.Sleep(20);
                                //设置 刷礼物的人,每次刷的礼物是1到100之间的一个随机数
                                service.IncrementItemInSortedSet("主播1", user, new Random().Next(1, 100));
                            }
                            Thread.Sleep(20 * 100);
                        }
                    });
                    //实时展示排行榜 每5秒展示一次最新数据
                    Task.Run(() =>
                    {
                        while (true)
                        {
                            Console.WriteLine("**************Eleven房间排行榜******************");
                            Thread.Sleep(5 * 1000);
                            //获取主播1中所有刷礼物的人的信息
                            var dic = service.GetAllWithScoresFromSortedSet("主播1");
                            int i = 1;
                            foreach (var item in dic)
                            {
                                Console.WriteLine($"第{i++}名   {item.Key} 分数{item.Value}");
                            }
                        }
                    });
                    Console.Read();
    
                    //现在大家开始提问,22:20  开始答疑! 期间老师就不说话了!
                }
    
            }
        }

    a

  • 相关阅读:
    sql: table,view,function, procedure created MS_Description in sql server
    sql: sq_helptext
    sql:Oracle11g 表,视图,存储过程结构查询
    sql:MySQL 6.7 表,视图,存储过程结构查询
    csharp: MongoDB
    10个出色的NoSQL数据库
    算法习题---3.01猜数字游戏提示(UVa340)
    03--STL算法(常用算法)
    STL函数适配器
    02--STL算法(函数对象和谓词)
  • 原文地址:https://www.cnblogs.com/anjingdian/p/15380530.html
Copyright © 2011-2022 走看看