Redis 4.x系列(四):Redis 数据类型之Set、Sorted Set
Set集合类型,是一个无序的,不可重复的字符串集合,可以快速测试成员在集合中是否存在,重复项删除和集合运算(求并、交、差集) 。Set 集合中最大成员数量为 2 的 32 次方减 1(4294967295)
Set 集合
Set 集合的不可重复特性,常用来跟踪具有唯一性的事物。例如要统计访问网站的用户数,可以根据用户 IP 地址来统计,只需要在有访问时就把 IP 加入到 Set 集合,集合中不会出现重复的 IP;计算水果种类,只需把水果命称加入到集合中而不需要判断是否重复, 还可用于存储中奖用户的 ID,因为有去重功能,可以保证同一用户不会中奖两次。
内部编码
Redis 内部使用两种编码方式来存储对集合对象:
- intset:元素都是整数,且元素个数小于配置中 set-max-intset-entries 选项设置的值(默认 512)的集合,采用此编码,对于较小的集合可以节省占用空间。
- hashtable:intset 不适用时的默认编码。
常用命令
- sadd:添加元素到集合。在添加时,如果键不存在,Redis 则创建一个空键集合;也会自动删除空集合对应的键。
- srem:从集合中删除元素。
- sismember:查看元素是否在集合中,存在返回 1,不存在返回 0。
- smembers:列出所有成员。该命令在大集合中使用可能会阻塞服务器,因此推荐使用
sscan
命令。 - scard:获取集合中成员数量。
- sscan:基于指针的增量迭代遍历元素,不会造成服务器阻塞;在使用时需要指定一个游标(从 0 开始), 返回一个列表以及一个新游标,新游标可用于下一次迭代。
- srandmember key [count]:随机返回指定个数无素。count可选,如果不写默认为1。
- spop key [count]:从集合中随机弹出指定个数元素。可用于生成随机数,比如抽奖。
Set常用的使用场景:标签系统,用户有多个爱好标签,一个标签有多个用户,在社交应用,推荐系统中常用。
sadd:添加
添加元素到有序集合
语法:sadd key value [value.....]
示例:
1 | 添加元素 |
srm:删除
删除元素
语法:srm key value
示例:
1 | 删除 |
scard:查个数
查看集合元素个数
语法:scard key
示例:
1 | 统计元素 |
sismember:是否存在
查看元素在集合中是否存在,存在返回 1, 不存在返回 0
语法:sismember key value
示例:
1 | 存在 |
smembers:列出所有成员
列出有序集合里的所有成员
语法:smembers key
示例:
1 | 列出所有成员 |
sscan:根据游标查询
根据游标和匹配规则获取集合元素
语法:sscan key cursor [MATCH pattern] [COUNT number]
示例:
1 | sscan |
集合运算:交/并/差
Set 集合运算有求并集的sunion 和 sunionstore命令,求交集的sinter 和 sinterstore命令,求差集的sdiff 和 sdiffstore命令。其中不带store后缀的命令只返回相应操作的集合;带store后缀的命令则会将结果存储到指定的键中。
1 | 添加两个集合 |
求并集
命令:sunion/sunionstore
1 | 127.0.0.1:6379> sunion shop1 shop2 |
求交集
命令:sinter/sinterstore
1 | 127.0.0.1:6379> sinter "shop1" "shop2" |
求差集
命令:sdiff / sdiffstore
1 | 127.0.0.1:6379> sdiff shop1 shop2 |
Sorted Set
Sorted set 是一个有序集合,不可重复集合,与 Set 集合非常类似。有序集合的每个元素都有一个用于排序的权重,权重分可重复。
使用有序集合,可以快速地对集合中的元素执行添加、删除、更新操作,可以按顺序从集合中获取元素。有序集合在某些需要一直保持数据有序的场景中非常有用,例如排行榜类场景。
内部编码
Redi 内部使用两种编码方式存储有序集合对象:
- **ziplist(压缩列表)**:对于元素个数小于配置中 zset-max-ziplist-entries 选项配置的值(默认 128 ),且每个元素的大小都小于配置中 zset-max-ziplist-value 选项配置的值(默认为 64 字节)的有序集合,采用此编码。 ziplist 用于节省较小集合所占用的空间。
- **skiplist(跳跃表)**:当 ziplist 不适用时使用的默认编码。
常用命令
- zadd key member:添加元素。
- zrem key member:删除元素。
- zremrangebyrank key start end:删除指定排名内的升序元素。
- zremrangebyscore key min max:删除指定分数范围的元素。
- zcard:计算成员个数。
- zrange:根据索引范围获取集合元素,按权重分从小到大排序。
- zrevrange:根据索引范围获取集合元素,按权重分从大到小排序。
- zrangebyscore key min max [withscores] [limit offset count]:按照分数从低到高返回指定范围的成员。
- zrevrangebyscore key min max [withscores] [limit offset count]:按照分数从高到低返回指定范围的成员。
- zincr:对 score 做增加。
- zincrby:修改元素权重分。
- zrank:是从分数从低到高返回排名。
- zrevrank:获取元素排名所在索引位置,第一位索位 0 。
- zscore:获取元素的权重分(投票数),不存在返回 nil。
- zinterstore:获取有序集合的交集,并存到到新的有集集合中,并可以指定元素权重分,默认情况下,元素的结果分数是其存在的有序集合中的分数之和。
- zunionstore:将两个有序集合的并集保存到指定键中(创建一个新的有序集合保存并集),且可以指定各个有序集合的不同权重分。
- zcount key min max:获取指定分数范围的元素个数。
zadd:添加
语法:zadd key [NX|XX] [CH] [INCR] score member [score member ...]
- NX在成员不存在时添加成员;
- XX 表示更新已存在的的成员,而不是添加新成员;
- CH 返回此次操作后,有序集合元素和分数发生变化的个数。
zadd
添加新的成员,允许成员具有相同的权重,Redis 将按照字典顺序进行排序。
示例:
1 | 127.0.0.1:6379> zadd ranking:film 1431 gold_brother 690 fantanfengbao 516 diezhongdie3 293 jianghuernv |
zrange:根据索引范围获取
语法:zrange key start stop [WITHSCORES]
, 根据索引范围获取集合元素,按权重分从小到大排序。
示例:
1 | 127.0.0.1:6379> zrange ranking:film 0 -1 withscores |
ZRANGEBYSCORE
语法:ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
,返回有序集合中指定分数区间内的成员,权重分由小到大排序, 支持分页。
示例:
1 | 127.0.0.1:6379> ZRANGEBYSCORE ranking:film 516 690 withscores |
ZRANGEBYSCORE还可用于实现延时队列,使用时间戳作为 score,消息内容作为 member 调用 zadd 生产消息,消费者使用ZRANGEBYSCORE指令获取** N **秒之前的数据轮询进行处理。
zrevrange
语法:zrevrange key start stop [WITHSCORES]
, 获取索引范围内的元素,权重分由大到小排序。
示例:
1 | 127.0.0.1:6379> zrevrange ranking:film 0 -1 withscores |
zrevrangebyscore
语法:zrevrangebyscore key max min [WITHSCORES] [LIMIT offset count]
,返回有序集合中指定分数区间内的成员,权重分由大到小排序, 支持分页。min 和 max 还支持开区间(小括号)和闭区间(中括号),**-inf** 和 +inf分别代表无限小和无限大。
示例:
1 | 127.0.0.1:6379> zrevrangebyscore ranking:film 690 293 withscores |
zcard:查个数
语法:zcard key
, 获取有序集合中元素个数。
示例:
1 | 127.0.0.1:6379> zcard ranking:film |
zincrby:改权重分
语法:zincrby key increment member
, 修改元素权重(投票数)
示例:
1 | 127.0.0.1:6379> zincrby ranking:film 300 jianghuernv |
zrevrank:获取元素排名
语法:zrevrank key member
, 获取元素在集合中的排名(索引),起始位是 0。
示例:
1 | 127.0.0.1:6379> zrevrank ranking:film fantanfengbao |
zscore:获取权重分
语法:zscore key member
, 获取元素的权重分(投票数)
示例:
1 | 127.0.0.1:6379> zscore ranking:film fantanfengbao |
zrem:删除元素
语法:zrem key member [member ...]
,删除集合中的元素成员
示例:
1 | 127.0.0.1:6379> zcard ranking:film |
集合运算:交/并
示例:新增两个集合以备运算
1 | 添加一个新集合 |
zunionstore:并集
合并两个集合的元素到一个新的有序集合。
语法:zunionstore destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]
- destination:计算结果保存到这个键
- numkeys:需要计算的键的个数
- key [key …]:需要做计算的键
- weights weight [weight …]:每个键的权重,在计算时,每个成员的分数乘以这个键权重,每个键权重默认
- aggregate sum|min|max:计算成员后,分值可根据此设置项进行统计,默认是 sum。
示例:
1 | 合并 |
zinterstore:交集
求两个集合的交集,存储到一个新的有序集合中。
语法:zinterstore destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]
示例:
1 | 127.0.0.1:6379> ZADD zset1 1 "one" |
相关参考
Redis 4.x系列(四):Redis 数据类型之Set、Sorted Set
http://blog.gxitsky.com/2018/09/25/Redis-4-datatype-2-set-sorted_set/