1.简介
Redis 的 Set 是 string 类型的无序集合。
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。
集合中最大的成员数为 232- 1(4294967295, 每个集合可存储40多亿个成员)。
Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。
2.使用场景
集合主要应用在一些需要求交集、并集、补集这样的场景,比如我们需要求共同好友、共同兴趣爱好、共同关注的微博,限制同一个账号多处登录系统等场景。
3.set数据结构示意图
set类型在存储数据时,是以key-List<value>格式存储的,如下图所示:
例如,一个用户tom,他的兴趣有编程,音乐,运动,就可以用set表示:
如下是对set封装后的api方法,RedisSetService.cs,代码如下:
using MyRedis.Redis.Interface; using System.Collections.Generic; namespace MyRedis.Redis.Service { public class RedisSetService : RedisBase { #region 添加 /// <summary> /// key集合中添加value /// </summary> /// <param name="key"></param> /// <param name="value"></param> public void AddItemToSet(string key, string value) { base.iClient.AddItemToSet(key, value); } /// <summary> /// key集合中添加list集合 /// </summary> /// <param name="key"></param> /// <param name="list"></param> public void AddRangeToSet(string key, List<string> list) { base.iClient.AddRangeToSet(key, list); } #endregion #region 获取 /// <summary> /// 随机获取key集合中的一个值 /// </summary> /// <param name="key"></param> /// <returns></returns> public string GetRandomItemFromSet(string key) { return base.iClient.GetRandomItemFromSet(key); } /// <summary> /// 获取key集合值的数量 /// </summary> /// <param name="key"></param> /// <returns></returns> public long GetSetCount(string key) { return base.iClient.GetSetCount(key); } /// <summary> /// 获取所有key集合的值 /// </summary> /// <param name="key"></param> /// <returns></returns> public HashSet<string> GetAllItemsFromSet(string key) { return base.iClient.GetAllItemsFromSet(key); } #endregion #region 删除 /// <summary> /// 随机删除key集合中的一个值 /// </summary> /// <param name="key"></param> /// <returns></returns> public string PopItemFromSet(string key) { return base.iClient.PopItemFromSet(key); } /// <summary> /// 删除key集合中的value /// </summary> /// <param name="key"></param> /// <returns></returns> public void RemoveItemFromSet(string key, string value) { base.iClient.RemoveItemFromSet(key, value); } #endregion #region 其它 /// <summary> /// 从fromkey集合中移除值为value的值,并把value添加到tokey集合中 /// </summary> /// <param name="fromkey"></param> /// <param name="tokey"></param> /// <param name="value"></param> public void MoveBetweenSets(string fromkey, string tokey, string value) { base.iClient.MoveBetweenSets(fromkey, tokey, value); } /// <summary> /// 返回keys多个集合中的并集 /// </summary> /// <param name="keys"></param> /// <returns></returns> public HashSet<string> GetUnionFromSets(params string[] keys) { return base.iClient.GetUnionFromSets(keys); } /// <summary> /// 返回keys多个集合中的交集 /// </summary> /// <param name="keys"></param> /// <returns></returns> public HashSet<string> GetIntersectFromSets(params string[] keys) { return base.iClient.GetIntersectFromSets(keys); } /// <summary> /// 返回keys多个集合中的差集 /// </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> /// <param name="newkey"></param> /// <param name="keys"></param> public void StoreUnionFromSets(string newkey, string[] keys) { base.iClient.StoreUnionFromSets(newkey, keys); } /// <summary> /// 把fromkey集合中的数据与keys集合中的数据进行比对,fromkey集合中不存在keys集合中,则把这些不存在的数据放入newkey /// </summary> /// <param name="newkey"></param> /// <param name="fromkey"></param> /// <param name="keys"></param> public void StoreDifferencesFromSet(string newkey, string fromkey, string[] keys) { base.iClient.StoreDifferencesFromSet(newkey, fromkey, keys); } #endregion } }
上面的代码创建完成后,项目的基础就构建完成了,下面开始学习set数据类型常用api的使用。
在控制台应用程序中的ServiceStackTest.cs类中,调用Redis的api方法。代码如下:
using MyRedis.Redis.Service; using System; using System.Collections.Generic; using System.Threading; namespace MyRedis { /// <summary> /// ServiceStackTest api 封装测试 /// </summary> public class ServiceStackTest { public class Student { public int Id { get; set; } public string Name { get; set; } public string Remark { get; set; } public int Age { get; set; } } public static void Show() { #region RedisSetService using (RedisSetService setService = new RedisSetService()) { setService.FlushAll(); //模拟zhangsan和lisi的好友列表 setService.AddItemToSet("zhangsan", "lisi"); setService.AddItemToSet("zhangsan", "jack"); setService.AddItemToSet("zhangsan", "jam"); setService.AddItemToSet("zhangsan", "alis"); setService.AddItemToSet("zhangsan", "wangwu"); setService.AddItemToSet("lisi", "zhangsan"); setService.AddItemToSet("lisi", "lucy"); setService.AddItemToSet("lisi", "wangwu"); var res1 = setService.GetIntersectFromSets("zhangsan", "lisi");//交集 var res2 = setService.GetDifferencesFromSet("zhangsan", "lisi");//差集 前者有,后者没有的 var res3 = setService.GetUnionFromSets("zhangsan", "lisi");//并集 两者所有的合起来 Console.WriteLine("************** 交集 ******************"); foreach (var item in res1) { Console.WriteLine(item); } Console.WriteLine("************** 差集 ******************"); foreach (var item in res2) { Console.WriteLine(item); } Console.WriteLine("************** 并集 ******************"); foreach (var item in res3) { Console.WriteLine(item); } } #endregion } } }
执行结果:
执行后可以从可视化工具看到Redis中存储的数据信息:
通过上文,我们可以知道集合的主要几个特性,无序、不可重复、支持并交差等操作。因此集合类型比较适合用来数据去重和保障数据的唯一性,还可以用来统计多个集合的交集、错集和并集等,当我们存储的数据是无序并且需要去重的情况下,比较适合使用集合类型进行存储。
更多hash的用法,参考文章:https://www.cnblogs.com/hunternet/p/12695738.html