一.SET概念集合类型也是保存多个字符串类型的元素的但和列表类型不同的是集合中1元素之间是无序的2元素不可重复。一个集合中最多可以存储无数个元素。Redis除了支持集合内的增删查改操作同时还支持多个集合取交集、并集、差集合理地使用好集合类型能在实际开发中解决很多问题。谈到一个术语这个术语很可能有多种含义。Set集合。设置和 get 相对应。集合就是把一些有关联的数据放到一起。集合中的元素是无序的集合中的元素是不能重复的唯一的。此处说的无序和前面 list 这里的有序是对应的。有序顺序很重要。变换一下顺序就是不同的 list 了。无序顺序不重要。变化一下顺序集合还是那个集合。示例list[1, 2, 3]和[2, 1, 3]是两个不同的 list。set[1, 2, 3]和[2, 1, 3]是同一个集合。和 list 类似集合中的每个元素也都是 string 类型。可以使用 json 这样的格式让 string 也能存储结构化数据。二.SET核心命令SADD 命令将⼀个或者多个元素添加到 set 中。注意重复的元素⽆法添加到 set 中。SADD key member [member ...]时间复杂度O(1)返回值本次添加成功的元素个数2.1SADD2.2SMEMBERSSMEMBERS命令获取⼀个 set 中的所有元素注意元素间的顺序是无序的。SMEMBERS key时间复杂度O(N)返回值所有元素的列表2.3SISMEMBERSISMEMBER命令判断⼀个元素在不在 set 中。SISMEMBER key member时间复杂度O(1)返回值1 表⽰元素在 set 中。0 表⽰元素不在 set 中或者 key 不存在2.4SPOPSPOP 命令从 set 中删除并返回⼀个或者多个元素。spop 删除元素的时候其实是随机删除。不写 count 的时候随机删除一个写 count 的时候就写几个就删几个。该操作类似于SRANDMEMBERSRANDMEMBER从集合中返回一个或多个随机元素但不删除它。其实是在源码中针对 spop 实现的时候采取了 “生成随机数” 的方式。SPOP key [count]时间复杂度O(N), n 是 count返回值取出的元素。存储元素是无序的删除随机删2.5SMOVESMOVE 命令将⼀个元素从源 set 取出并放⼊目标 set 中。把 member 从 source 上删除再插入到 destination 中。再次操作时smove 不会视为出错也会按照删除 - 插入进行执行。如果要移动的元素在 source 中不存在返回 (integer) 0 表示移动失败了。SMOVE source destination member时间复杂度O(1)返回值1 表示移动成功0 表示失败2.6SREMSREM 命令将指定的元素从 set 中删除。可以一次删除一个 member也可以一次删除多个 member。SREM key member [member ...]时间复杂度O(N), N 是要删除的元素个数.返回值本次操作删除的元素个数2.7SCARDSCARD 命令获取⼀个 set 的基数cardinality即 set 中的元素个数。SCARD key时间复杂度O(1)返回值set 内的元素个数。2.8 SRANDMEMBERSRANDMEMBER命令随机返回集合中的某个元素相关概念1.交集inter最终结果同时出现在两个集合中。示例A 为 {1, 2, 3, 4}B 为 {3, 4, 5, 6}A 和 B 的交集为 {3, 4}。2.并集union把多个集合中的数据都集中放在一起如果元素有重复也最终只保留一份。示例A 为 {1, 2, 3, 4}B 为 {3, 4, 5, 6}A 和 B 的并集为 {1, 2, 3, 4, 5, 6}。3.差集diffA 和 B 做差集就是找出哪些元素在 A 中存在同时在 B 中不存在。示例A 为 {1, 2, 3, 4}B 为 {3, 4, 5, 6}A 和 B 做差集为 {1, 2}B 和 A 的差集为 {5, 6}。2.9SINTER SINTERSTSTORESINTER命令获取给定 set 的交集中的元素。SINTER key [key ...]时间复杂度O(N * M), N 是最⼩的集合元素个数. M 是最大的集合元素个数.返回值交集的元素。SINTERSTORE命令获取给定 set 的交集中的元素并保存到⽬标 set 中。SINTERSTORE destination key [key ...]时间复杂度O(N * M), N 是最小的集合元素个数. M 是最大的集合元素个数.返回值交集的元素个数2.10SUNION SUNIONSTORESUNION命令获取给定 set 的并集中的元素。SUNION key [key ...]时间复杂度O(N), N 给定的所有集合的总的元素个数.返回值并集的元素SUNIONSTORE命令获取给定 set 的并集中的元素并保存到目标 set 中。SUNIONSTORE destination key [key ...]命令有效版本1.0.0 之后时间复杂度O(N), N 给定的所有集合的总的元素个数.返回值并集的元素个数。2.11SDIFFSDIFFSTORESDIFF命令获取给定 set 的差集中的元素。SDIFF key [key ...]时间复杂度O(N), N 给定的所有集合的总的元素个数.返回值差集的元素。SDIFFSTORE 命令获取给定 set 的差集中的元素并保存到⽬标 set 中。SDIFFSTORE destination key [key ...]时间复杂度O(N), N 给定的所有集合的总的元素个数.返回值差集的元素个数三.SET内部编码intset整数集合当集合中的元素都是整数并且元素的个数小于 set-max-intset-entries 配置默认 512 个时Redis 会选用 intset 来作为集合的内部实现从而减少内存的使用。hashtable哈希表当集合类型无法满足 intset 的条件时Redis 会使用 hashtable 作为集合的内部实现。1.当元素个数较少并且都为整数时内部编码为 intset127.0.0.1:6379 sadd setkey 1 2 3 4 (integer) 4 127.0.0.1:6379 object encoding setkey intset2.当元素个数超过 512 个内部编码为 hashtable127.0.0.1:6379 sadd setkey 1 2 3 4 (integer) 513 127.0.0.1:6379 object encoding setkey hashtable3.当存在元素不是整数时内部编码为 hashtable127.0.0.1:6379 sadd setkey a (integer) 1 127.0.0.1:6379 object encoding setkey hashtable四.SET的应用场景集合类型比较典型的使用场景是标签tag。例如 A 用户对娱乐、体育板块比较感兴趣B 用户对历史、新闻比较感兴趣这些兴趣点可以被抽象为标签。有了这些数据就可以得到喜欢同一个标签的人以及用户的共同喜好的标签这些数据对于增强用户体验和用户黏度都非常有帮助。 例如一个电子商务网站会对不同标签的用户做不同的产品推荐。使用 Set 来保存用户的 “标签”用户画像分析出个人的一些特征分析清楚特征之后再投其所好实现 “千人千面”例如可以分析出性别、年龄、居住地、爱好等特征。可以根据用户的一些历史行为得出相关特征。比如对于两个程序、两个账号判断是否为同一个人现在的程序登录主要是通过手机号和微信等入口来判断。通过上述过程搜集到的用户特征会转换成 “标签”标签是简短的字符串此时就可以把标签保存到 redis 的 set 中了。使用 Set 来计算用户之间的共同好友基于 “集合求交集” 操作。例如在 QQ 中我加了很多好友你也加了很多好友基于此还可以做一些好友推荐。如 A 和 B 是好友A 和 C 是好友B 和 C、D 都是好友系统就会把 D 推荐给 A。使用 Set 统计 UV去重一个互联网产品衡量用户量、用户规模主要有两方面指标PVpage view用户每次访问该服务器每次访问都会产生一个 pv。UVuser view每个用户访问服务器都会产生一个 uv但同一个用户多次访问不会使 uv 增加uv 需要按照用户进行去重上述的去重过程可以使用 set 来实现。Set 方便计算交集很容易找到两个用户之间的公共标签。基于这样的标签衍生出一些 “用户关系”。