redis提供了5种数据结构,理解每次数据结构的特色在开发和运维中是很重要的.使用redis版本:3.0.7javascript
本章内容以下:java
redis
列表redis
redis
集合shell
redis
有序集合数据结构
列表(list
)类型是用来存储多个字符串,以下图A,B,C,D
四个元素从左到右组成一个有序的集合.列表中的每一个字符串被称为元素(element
),一个列表最多能够存储(2的32次方)-1
个元素.在redis
中,能够对列表两端插入(push
)和弹出(pop
),还能够获取指定范围的元素列表、获取指定全部下标的元素等.app
列表类型有两个特色:负载均衡
列表中的元素是有序的,这就意味着能够经过索引下标获取某个元素或者某个范围内的元素列表.运维
列表中的元素能够是重复的.编码
(1) 从右边插入元素.spa
rpush key value [value...]
例:
向列表插入a,b,c
三个元素.
lrange key 0 -1
命令能够获取列表中全部的元素.
(2) 从左边插入元素.
使用方法与rpush
同样,从左侧插入.
lpush key value [value....]
例:
(1) 查询指定范围内的元素列表
lrange key start end
lrange
操做会获取列表指定索引范围全部的元素.索引下标有两个特色:第一,索引下标从左到右分别是0
到N-1
,可是从右到左分别是-1
到-N
.第二,lrange
中的end
选项包含了自身.
例:
(2) 获取列表指定索引下的元素
lindex key index
例:
(3) 获取列表长度
llen key
例:
(1) 从列表左侧或右侧弹出元素.
以下操做是将列表最左侧与右侧的元素弹出来.
(2) 删除指定元素
lrem key count value
lrem
命令会从列表中找到等于value
的元素进行删除,根据count
的不一样分为三种:
count>0
,从列表中删除指定数量(count
)的元素.
count<0
,从列表中删除count
绝对值数量的元素.
count=0
,删除全部.
例:
指定元素数量:
全部元素:
(3) 按照索引范围修剪列表
ltrim key start end
例如,下面操做会保留列表第二个到第六个元素:
修改指定索引下标的元素:
lset key index value
例:
修改第一个元素的值为c
.
阻塞式弹出:
blpop key [key...] timeout brpop key [key...] timeout
blpop
与brpop
命令是lpop
和rpop
命令的阻塞版本,他除了弹出方向不一样,使用方法基本相同,因此下面以brpop
命令进行说明,brpop
命令包含两个参数:
key [key...]
:多个列表的键.
timeout
:阻塞时间(单位为秒
).
1)列表为空:若是timeout
等于3
,那么客户端等到三秒后返回,若是timeout=0
,那么客户端将一直阻塞,直到弹出成功.
2)列表不为空:客户端会马上返回.
在使用阻塞弹出命令时,有两点须要注意.
第一点:若是是多个键,那么会从左到右遍历键,一旦有一个键能弹出元素客户端就会马上返回.
第二点:若是多个客户端同时对一个键进行操做,那么最早执行命令的客户端能够获取到值.
列表类型的内部编码有两种:
编码名 | 编码描述 |
---|---|
ziplist (压缩列表) |
当列表的元素个数大于list-max-ziplist-entries 配置(默认为512个),同时列表中每一个元素的长度小于list-max-ziplist-value 配置(默认为64字节). |
linkedlist (链表) |
当列表的长度或值得大小不知足ziplist 的要求,redis 会采用linkedlist 为列表的内部实现编码. |
消息队列:redis
的lpush-brpop
命令组合便可实现阻塞队列,生产者客户端使用lpush
命令向列表插入元素.消费者客户端使用brpop
命令阻塞式的"抢"列表中的尾部元素.多个客户端保证消息的负载均衡与可用性.
文章列表:每一个用户都有属于本身的文章列表.此时能够考虑使用列表,由于列表不可是有序的,同时支持使用lrange
按照索引范围获取多个元素.
伪代码:
var articles = redis.lrange('user:1:acticles',0,9); articles.forEach(function(){ // 遍历操做 });
开发提示:列表的使用场景有不少如:
lpush
+lpop
=Stack
(栈)、lpush
+rpop
=queue
(队列)、lpush
+brpop
=message queue
(消息队列)、lpush
+ltrim
=Capped Collection
(有限集合)
集合(set
)类型也是用来保存多个的字符串元素,但和列表不一样的是:它的元素是无序且不可重复的,不能经过索引获取元素.以下图,集合user:1:follows
中包含着"his"、"it"、"sports"、"music"四个元素,一个集合最多能够存储(2的32次方-1)个元素.
(1) 添加元素
sadd key value [value...]
返回结果为添加成功的元素数量.
例:
(2) 删除元素
srem key value [value...]
返回结果为删除成功的元素数量.
例:
(3) 获取元素个数
scard key
例:
(4) 判断元素是否在集合中
sismember key value
若是元素存在于集合内则返回1
,反之返回0
.
例:
(5) 随机从集合中返回指定个数元素
srandmember key [count]
[count]
是可选参数,若是不写默认为:1
.
例:
(6) 从集合中随机弹出元素
spop key
spop操做能够从集合中随机弹出一个元素.
例:
使用spop
命令后,集合元素变为"1","3".
(7) 获取集合的全部元素
smembers key
获取集合全部元素,且返回结果是无序的.
(1) 求多个集合的交集
sinter key [key...]
例:
(2) 求多个集合的并集
sunion key [key...]
例:
(3) 求多个集合的差集
sdiff key [key...]
例:
(4) 将交集、并集、差集的结果保存.
sinterstore storeKey key [key...] sunionstore storeKey key [key...] sdiffstore storeKey key [key...]
集合间的运算在元素比较多的状况下会比较耗时,因此redis
提供了上面三个命令(原命令+store
)将集合间交集、并集、差集的结果保存到storeKey
中,例如将user:1:follows
和user:2:follows
两个集合之间的交集结果保存到user:1_2:follows
中.
集合类型的内部编码有两种:
编码名 | 编码描述 |
---|---|
intset (整数集合) |
当集合中的元素全是整数,且长度不超过set-max-intset-entries (默认为512 个)时,redis 会选用intset 做为内部编码. |
hashtable (哈希表) |
当集合没法知足intset 的条件时,redis 会使用hashtable 做为内部编码. |
集合类型比较典型的使用场景是标签(tag
).例如一个用户可能对音乐感兴趣,另外一个用户对新闻感兴趣,这些想去点就是标签.有了这些数据就能够得到喜欢同一个标签的人,以及用户的共同喜爱的标签,这些数据对于用户体验来讲比较重要.
下面使用集合类型实现标签功能的若干功能.例如:
(1) 给用户添加标签:
(2) 给标签添加用户:
(3) 删除用户的标签:
(4) 删除标签的用户:3
到4
最好在同一个事务下进行处理.
(5) 计算用户共同拥有的标签:
有序集合相对于哈希、列表、集合来讲会有一点陌生,但既然叫有序集合.那么它和集合必然是有着联系,它保留了集合不能重复元素的特性.但不一样的是,有序集合是可排序的.可是他和列表使用索引下标进行排序依据不一样的是,它给每一个元素设置一个分数(score
)做为排序的依据.
列表、集合、有序结合的异同点
数据结构 | 是否容许重复元素 | 是否有序 | 有序实现方式 | 应用场景 |
---|---|---|---|---|
集合 | 否 | 否 | 无 | 标签、社交等. |
有序集合 | 否 | 是 | 分值 | 排行榜、社交等. |
列表 | 是 | 是 | 索引下标 | 时间轴、消息队列等. |
(1) 添加成员
zadd key score member [score member ...]
下面操做向有序集合user:ranking
增长用户Rico
和他的分数60
分:
有关zadd
命令有两点须要注意:
Redis 3.2
为zadd
命令添加了nx
、xx
、ch
、incr
四个选项:
nx
:member
必须不存在,才能够设置成功,用于添加.
xx
:member
必须存在,才能够设置成功,用于添加.
ch
:返回这次操做后,有序结合元素和分数发生变化的个数.
incr
: 对score
进行添加操做,至关于后面介绍的zincrby
.
有序集合相比集合提供了排序字段,可是也产生了代价,zadd
的时间复杂度是O(log(n))
,sadd
的时间复杂度为O(1)
.
(2) 获取成员个数
zcard key
例:
(3) 获取某个成员的分数
zscore key member
例:
(4) 获取成员排名
zrank key member zrevrank key member
zrank
命令是从分数从低到高返回排名,zrevrank
反之,排名从0
开始.例以下面:
(5) 删除成员
zrem key member [member...]
下面操做成员ann
从有序集合user:ranking
中删除.
(6) 增长成员分数
zincrby key score member
下面操做给Rico
成员添加9
分,分数变为69
分.
(7) 获取制定范围的元素
zrange key start end [withscores] zrevrange key start end [withscores]
有序集合是按照分值排名的,zrange
是由低到高返回,zrevrange
反之,查询所有:zrange user:ranking 0 -1
,加上withscores
参数显示分数.
例:
获取前三名.
127.0.0.1:6379> zrange user:ranking 0 2 1) "codger" 2) "hank" 3) "ann" 127.0.0.1:6379> zrevrange user:ranking 0 2 1) "tom" 2) "Rico" 3) "ann"
(8) 返回指定分数范围的成员
zrangebyscore key min max [withscores] [limit offset count] zrevrangebyscore key min max [withscores] [limit offset count]
例:
返回分数在0
到100
的成员.
127.0.0.1:6379> zrangebyscore user:ranking 0 100 1) "codger" 2) "hank" 3) "ann" 4) "Rico" 5) "tom"
返回分数在0
到无限大的成员.
127.0.0.1:6379> zrangebyscore user:ranking 0 +inf 1) "codger" 2) "hank" 3) "ann" 4) "Rico" 5) "tom"
同时min
和max
还支持开区间(小括号)和闭区间(中括号),-inf
和+inf
分别表明无限小和无限大:
127.0.0.1:6379> zrangebyscore user:ranking (10 +inf withscores 1) "hank" 2) "15" 3) "ann" 4) "30" 5) "Rico" 6) "69" 7) "tom" 8) "80"
(9) 返回指定分数范围成员个数
zcount key min max
下面返回分数为10
到15
的成员:
127.0.0.1:6379> zcount user:ranking (10 15 (integer) 1
(10) 删除指定排名内的升序元素
zremrangebyrank key start end
删除第start
到第end
名的成员:
127.0.0.1:6379> zremrangebyrank user:ranking 0 1 (integer) 2
(11) 删除指定分数范围的成员
zremrangebyscore key min max
删除分数从min
到max
的成员:
127.0.0.1:6379> zremrangebyscore user:ranking 0 30 (integer) 1
(1) 交集
zinterstore storeKey keyNum key [key ...] [weights weight [weight...]] [aggregate sum|min|max]
参数说明:
storeKey
:交集计算结果保存到这个键下.
keyNum
:须要作交集的键的个数.
key[key ...]
:须要作交集的键.
weights weight [weight...]
:每一个键的权重,在作交集计算时,每一个键中的每一个member
的分值会和这个权重相乘,每一个键的权重默认为1
.
aggregate sum|min|sum
:计算成员交集后,分值能够按照sum
(和)、min
(最小值)、max
(最大值)作汇总.默认值为sum
.
127.0.0.1:6379> zrange user:ranking:2 0 -1 withscores 1) "Rico" 2) "138" 3) "tom" 4) "160" 127.0.0.1:6379> zinterstore user:ranking:1_2 2 user:ranking user:ranking:2 aggregate min (integer) 2 127.0.0.1:6379> zrange user:ranking:1_2 0 -1 1) "Rico" 2) "tom" 127.0.0.1:6379> zrange user:ranking:1_2 0 -1 withscores 1) "Rico" 2) "69" 3) "tom" 4) "80"
(2) 并集
zunionstore storeKey keyNum key [key...] [weights weight [weight...]] [aggregate sum|min|max]
该命令的全部参数和zinterstore
是一致的,只不过作的是并集计算.
例:
127.0.0.1:6379> zunionstore user:ranking:1_2 2 user:ranking user:ranking:2 aggregate min (integer) 3 127.0.0.1:6379> zrange user:ranking:1_2 0 -1 withscores 1) "Rico" 2) "69" 3) "codger" 4) "90" 5) "tom" 6) "160"
编码名称 | 编码描述 |
---|---|
ziplist (压缩列表) |
当有序集合的元素小于zset-max-ziplist-entries 配置(默认是128个),同时每一个元素的值都小于zset-max-ziplist-value (默认是64字节)时,Redis 会用ziplist 来做为有序集合的内部编码实现,ziplist 能够有效的减小内存的使用 |
skiplist (跳跃表) |
当ziplist 的条件不知足时,有序集合将使用skiplist 做为内部编码的实现,来解决此时ziplist 形成的读写效率降低的问题. |