文章目录

1. Set
集合类型也是保存多个字符串类型的元素的,但和列表类型不同的是,集合中元素之间是⽆序的,元素不允许重复,⼀个集合中最多可以存储232-1个元素。
Redis除了⽀持集合内的增删查改操作,同时还⽀持多个集合取交集、并集、差集,合理地使⽤好集合类型,能在实际开发中解决很多问题。
1.1 常用命令
sadd
:将⼀个或者多个元素添加到set中(重复的元素⽆法添加到set中)
SADD key member [member ...]
smembers
:获取⼀个set中的所有元素(元素间的顺序是⽆序的)
SMEMBERS key
sismember
:判断⼀个元素在不在set中
SISMEMBER key member
SCARD
:获取⼀个set的基数(cardinality),即set中的元素个数
SCARD key
spop
:从set中删除并返回⼀个或者多个元素(由于set内的元素是无序的,所以取出哪个元素实际是未定义行为,即可以看作随机的)
SPOP key [count]
smove
:将⼀个元素从源set取出并放⼊⽬标set中
smove source destination member
srem
:将指定的元素从set中删除
srem key member [member ...]
1.2 集合间操作
交集(inter)、并集(union)、差集(diff)的概念如图所示:
sinter
:获取给定set的交集中的元素
SINTER key [key ...]
SINTERSTORE
:获取给定set的交集中的元素并保存到⽬标set中
SINTERSTORE destination key [key ...]
SUNION
:获取给定set的并集中的元素
SUNION key [key ...]
SUNIONSTORE
:获取给定set的并集中的元素并保存到⽬标set中
SUNIONSTORE destination key [key ...]
SDIFF
:获取给定set的差集中的元素
SDIFF key [key ...]
SDIFFSTORE
:获取给定set的差集中的元素并保存到⽬标set中
SDIFFSTORE destination key [key ...]
命令小节:
1.3 内部编码
集合类型的内部编码有两种:
- intset(整数集合):当集合中的元素都是整数并且元素的个数小于set-max-intset-entries配置(默认512个)时,Redis会选⽤intset来作为集合的内部实现,从⽽减少内存的使用。
- hashtable(哈希表):当集合类型⽆法满⾜intset的条件时,Redis会使⽤hashtable作为集合的内部实现
- 当元素个数较少并且都为整数时,内部编码为intset
127.0.0.1:6379> sadd setkey 1 2 3 4
(integer) 4
127.0.0.1:6379> object encoding setkey
"intset"
- 当元素个数超过512个,内部编码为hashtable
127.0.0.1:6379> sadd setkey 1 2 3 4 ... 513
(integer) 513
127.0.0.1:6379> object encoding setkey
"hashtable"
- 当存在元素不是整数时,内部编码为hashtable
127.0.0.1:6379> sadd setkey a
(integer) 1
127.0.0.1:6379> object encoding setkey
"hashtable"
1.4 使用场景
集合类型比较典型的使⽤场景是标签(tag)
- 例如A用户对娱乐、体育板块⽐较感兴趣;B用户对历史、新闻⽐较感兴趣,这些兴趣点可以被抽象为标签。
- 有了这些数据就可以得到喜欢同⼀个标签的⼈,以及用户的共同喜好的标签,这些数据对于增强用户体验和用户黏度都⾮常有帮助。例如⼀个电⼦商务⽹站会对不同标签的用户做不同的产品推荐。
下⾯的演⽰通过集合类型来实现标签的若⼲功能
- 给用户添加标签
sadd user:1:tags tag1 tag2 tag5
sadd user:2:tags tag2 tag3 tag5
...
sadd user:k:tags tag1 tag2 tag4
- 给标签添加用户
sadd tag1:users user:1 user:3
sadd tag2:users user:1 user:2 user:3
...
sadd tagk:users user:1 user:4 user:9 user:28
- 计算用户的共同兴趣标签
sinter user:1:tags user:2:tags
2. Zset 有序集合
有序集合相对于字符串、列表、哈希、集合来说会有⼀些陌生
它保留了集合不能有重复成员的特点,但与集合不同的是,有序集合中的每个元素都有⼀个唯⼀的浮点类型的分数(score)与之关联,这使得有序集合中的元素是可以维护有序性的,但这个有序不是用下标作为排序依据而是用这个分数。
有序集合中的元素是不能重复的,但分数允许重复;分数相同,则按元素字典序排序。
有序集合提供了获取指定分数和元素范围查找、计算成员排名等功能,合理地利用有序集合,可以帮助我们在实际开发中解决很多问题。
2.1 常用命令
zadd
:添加或者更新指定的元素以及关联的分数到zset中,分数应该符合double类型,+inf/-inf作为正负极限也是合法的
ZADD key [NX | XX] [GT | LT] [CH] [INCR] score member [score member...]
默认情况下,ZADD返回的是本次添加的元素个数
相关选项:
- XX:仅仅⽤于更新已经存在的元素,不会添加新元素。
- NX:仅⽤于添加新元素,不会更新已经存在的元素。
- CH:默认情况下,ZADD返回的是本次添加的元素个数,但指定这个选项之后,就会还包含本次更新的元素的个数。
- INCR:此时命令类似ZINCRBY的效果,将元素的分数加上指定的分数。此时只能指定⼀个元素和分数。
- LT:仅当新分数小于(lesser)当前分数时,才更新现有元素。此标志不会阻止添加新元素。
- GT:仅当新分数大于(greater)当前分数时,才更新现有元素。此标志不会阻止添加新元素
- GT、LT是Redis 6.2.0 版本开始引入的
GT、LT 和 NX 选项是互斥的
ZRANGE
:返回指定区间⾥的元素,分数按照升序。带上WITHSCORES可以把分数也返回
ZRANGE key start stop [WITHSCORES]
此处的[start, stop] 为下标构成的区间从0开始,⽀持负数
zcard
:获取⼀个zset的基数(cardinality),即zset中的元素个数
ZCARD key
zcount
:返回分数在min和max之间的元素个数,默认情况下,min和max都是包含的,可以通过(
排除
ZCOUNT key min max
ZREVRANGE
:返回指定区间⾥的元素,分数按照降序。带上WITHSCORES可以把分数也返回
备注:这个命令可能在6.2.0之后废弃,并且功能合并到ZRANGE中
ZREVRANGE key start stop [WITHSCORES]
ZRANGEBYSCORE
:返回分数在min和max之间的元素,默认情况下,min和max都是包含的,可以通过(
排除。
备注:这个命令可能在6.2.0之后废弃,并且功能合并到ZRANGE中
ZRANGEBYSCORE key min max [WITHSCORES]
ZPOPMAX
:删除并返回分数最⾼的count个元素。
ZPOPMAX key [count]
BZPOPMAX
: ZPOPMAX的阻塞版本
BZPOPMAX key [key ...] timeout
ZPOPMIN
:删除并返回分数最低的count个元素
ZPOPMIN key [count]
BZPOPMIN
: ZPOPMIN的阻塞版本
BZPOPMIN key [key ...] timeout
ZRANK
:返回指定元素的排名,升序。
ZRANK key member
ZREVRANK
:返回指定元素的排名,降序
ZREVRANK key member
ZSCORE
:返回指定元素的分数
ZSCORE key member
ZREM
:删除指定的元素
ZREM key member [member ...]
ZREMRANGEBYRANK
:按照排序,升序删除指定范围的元素,左闭右闭
ZREMRANGEBYRANK key start stop
ZREMRANGEBYSCORE
:按照分数删除指定范围的元素,左闭右闭
ZREMRANGEBYSCORE key min max
ZINCRBY
:为指定的元素的关联分数添加指定的分数值
ZINCRBY key increment member
集合间操作:
ZINTERSTORE
:求出给定有序集合中元素的交集并保存进⽬标有序集合中,在合并过程中以元素为单位进⾏合并,元素对应的分数按照不同的聚合⽅式和权重得到新的分数
ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]]
[AGGREGATE <SUM | MIN | MAX>]
- numkeys:有几个key参与运算,为了与后面的选项区分
- weights:权重,表示所参与交集运算key的重要性,会乘以当前的分数
- aggregate:聚合方式
ZUNIONSTORE
:求出给定有序集合中元素的并集并保存进⽬标有序集合中,在合并过程中以元素为单位进⾏合并,元素对应的分数按照不同的聚合⽅式和权重得到新的分数
ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]]
[AGGREGATE <SUM | MIN | MAX>]
命令小节:
2.2 内部编码
有序集合类型的内部编码有两种:
ziplist
(压缩列表):当有序集合的元素个数⼩于zset-max-ziplist-entries配置(默认128个),同时每个元素的值都⼩于zset-max-ziplist-value配置(默认64字节)时,Redis会⽤ziplist来作为有序集合的内部实现,ziplist可以有效减少内存的使⽤。skiplist
(跳表):当ziplist条件不满⾜时,有序集合会使⽤skiplist作为内部实现,因为此时ziplist的操作效率会下降
2.3 应用场景
有序集合⽐较典型的使⽤场景就是排⾏榜系统。例如常⻅的⽹站上的热榜信息,榜单的维度可能是多方面的:按照时间、按照阅读量、按照点赞量。
本例中我们使⽤点赞数这个维度,维护每天的热榜:
- 添加用户赞数
例如用户james发布了⼀篇⽂章,并获得3个赞,可以使⽤有序集合的zadd和zincrby功能:
zadd user:ranking:2022-03-15 3 james
之后如果再获得赞,可以使⽤zincrby:
zincrby user:ranking:2022-03-15 1 jame
- 取消用户赞数
由于各种原因(例如⽤⼾注销、⽤⼾作弊等)需要将⽤⼾删除,此时需要将⽤⼾从榜单中删除掉,可以使⽤zrem。例如删除成员tom:
zrem user:ranking:2022-03-15 tom
- 展示获取赞数最多的10个用户
此功能使⽤zrevrange命令实现:
zrevrangebyrank user:ranking:2022-03-15 0 9
- 展示用户信息以及用户分数
此功能将用户名作为键后缀,将用户信息保存在哈希类型中,⾄于用户的分数和排名可以使⽤zscore和zrank来实现。
列表、集合、有序集合三者的异同点
3. 其它数据类型
在前面,我们已经了解了Redis的五个常用类型:String、list、hash、set、zset。
除此之外,Redis还提供了一些其它的类型
3.1 stream
Stream是一种数据结构,其作用类似于仅追加日志,但也实施了多项操作来克服典型仅追加日志的一些限制。其中包括 O(1) 时间的随机访问和复杂的消费策略。
通俗来讲就是:stream类型,可以用来模拟实现时间传播的机制,本质就是一个队列(redis作为消息队列的根本),比list、blpop、brpop功能更加强大。
3.2 geospatial
地理索引允许您存储坐标并进行搜索。 此数据结构可用于查找给定半径或边界框内的附近点
3.3 HyperLogLog
HyperLogLog 是一种概率数据结构,用于估计集合重元素的个数
HyperLogLog 以完美的准确性换取了高效的空间利用。
Redis HyperLogLog 实现最多使用 12 KB,并提供0.81% 的标准误差。
我们知道set有一个应用场景:统计服务器的用户访问次数(UV)。
当然使用set也可以很好的统计,但是当这个数据量比较大时,set会消耗很多的内存空间。
假设set存uid,每个uid按8字节算,如果有1亿的UV–> 8亿字节–>800M;但是使用hyperloglog最多使用12KB空间
Hyperloglog不存储元素的内容,但是能够记录元素的特征,从而在新增元素的时候,能够知道当前新增的元素,是新增的元素,还是已经存在的元素。 所以可以用来计数,但是无法告诉你元素是什么。
3.4 bitmap
位图
3.5 bitfield
位域
bitfield可以理解为一串二进制序列(字节数组),同时可以把这个字节数组的某几个位,赋予特定的含义,并且进行读取、修改、算术等相关操作
4. 渐进式遍历
在前面,我们学习了keys命令,它可以获取key,但是该命令有时候是非常危险的,可能会阻塞redis服务器
渐进式遍历(SCAN
)不会阻塞redis服务器,它执行一次命令,只获取其中的一小部分,要想获取所有的key,就需要执行多次渐进式遍历命令
SCAN cursor [MATCH pattern] [COUNT count] [TYPE type]
首次scan从0开始,当scan返回的下次位置为0时,遍历结束
- cursor:指向开始遍历的位置,不能理解成下标,它仅是个字符串
- count:遍历的个数(实际返回的个数不一定完全相同),默认是10
- pattern:匹配的规则,跟keys相同
- type:指明要获取key的value的类型
- 返回值
- 下次开始遍历的位置
- 此次遍历的结果
除了scan以外,Redis⾯向哈希类型、集合类型、有序集合类型分别提供了hscan、sscan、zscan命令,它们的⽤法和scan基本类似
渐进性遍历scan虽然解决了阻塞的问题,但如果在遍历期间键有所变化(增加、修改、删除),可能导致遍历时键的重复遍历或者遗漏,这点务必在实际开发中考虑。
5. 数据库管理
redis提供了16个数据库,编号位0-15,默认使用0号,用户无法创建和删除
Redis 提供了⼏个⾯向Redis数据库的操作,分别是dbsize、select、flushdb、flushall命令,本机将通过具体的使⽤常⻅介绍这些命令。
select
:切换数据库
2. dbsize
:获取当前数据库中key的个数
3. flushdb
:删除当前库中的key
4. flushall
:删除所有库中所有的key