一 set类型
set 是集合,和我们数学中的集合概念相似,对集合的操作有添加删除元素,有对多个集合求交并差等操作,操作中key 理解为集合的名字。
Redis的set是 string类型的无序集合。set元素最大可以包含(2的 32次方)个元素。
set的是通过hash table 实现的,所以添加、删除和查找的复杂度都是 O(1)。hash table 会随着添加或者删除自动的调整大小。需要注意的是调整 hash table大小时候需要同步(获取写锁)会阻塞其他读写操作,可能不久后就会改用跳表(skip list)来实现,跳表已经在 sorted set 中使用了。关于 set 集合类型除了基本的添加删除操作,其他有用的操作还包含集合的取并集(union),交集(intersection),差集(difference)。通过这些操作可以很容易的实现 sns中的好友推荐和 blog的tag功能。下面详细介绍 set相关命令:
1.1 sadd
向名称为key 的set中添加元素
127.0.0.1:6379> sadd myset "hello"
(integer) 1
redis 127.0.0.1:6379> sadd myset "world"
(integer) 1
127.0.0.1:6379> sadd myset "world"
(integer) 0
127.0.0.1:6379> smembers myset
1) "world"
2) "hello"
本例中,我们向myset中添加了三个元素,但由于第三个元素跟第二个元素是相同的,所以第三个元素没有添加成功,最后我们用smembers来查看myset中的所有元素。
1.2 srem
删除名称为key的 set中的元素member
127.0.0.1:6379> sadd myset2 "one"
(integer) 1
127.0.0.1:6379> sadd myset2 "two"
(integer) 1
redis 127.0.0.1:6379> sadd myset2 "three"
(integer) 1
127.0.0.1:6379> srem myset2 "one"
(integer) 1
127.0.0.1:6379> srem myset2 "four"
(integer) 0
127.0.0.1:6379> smembers myset2
1) "three"
2) "two"
本例中,我们向myset2中添加了三个元素后,再调用 srem来删除 one 和four,但由于元素中没有four所以,此条 srem命令执行失败。
随机返回并删除名称为 key 的set中一个元素
127.0.0.1:6379> sadd myset3 "one"
(integer) 1
127.0.0.1:6379> sadd myset3 "two"
(integer) 1
127.0.0.1:6379> sadd myset3 "three"
(integer) 1
127.0.0.1:6379> spop myset3
"three"
127.0.0.1:6379> smembers myset3
1) "two"
2) "one"
本例中,我们向myset3中添加了三个元素后,再调用spop来随机删除一个元素,可以看到three元素被删除了。
1.4 sdiff
返回所有给定key 与第一个key的差集
127.0.0.1:6379> smembers myset2
1) "three"
2) "two"
127.0.0.1:6379> smembers myset3
1) "two"
2) "one"
127.0.0.1:6379> sdiff myset2 myset3
1) "three"
127.0.0.1:6379>
本例中,我们可以看到 myset2中的元素与 myset3中不同的只是three,所以只有three被查出来了,而不是 three和one,因为one 是 myset3的元素。
1.5 sdiffstore
返回所有给定key 与第一个key的差集,并将结果存为另一个 key
127.0.0.1:6379> smembers myset2
1) "three"
2) "two"
127.0.0.1:6379> smembers myset3
1) "two"
2) "one"
127.0.0.1:6379> sdiffstore myset4 myset2 myset3
(integer) 1
127.0.0.1:6379> smembers myset4
1) "three"
返回所有给定key 的交集
127.0.0.1:6379> smembers myset2
1) "three"
2) "two"
127.0.0.1:6379> smembers myset3
1) "two"
2) "one"
127.0.0.1:6379> sinter myset2 myset3
1) "two"
通过本例的结果可以看出, myset2和myset3 的交集two被查出来了
1.7 sinterstore
返回所有给定key 的交集,并将结果存为另一个 key
127.0.0.1:6379> smembers myset2
1) "three"
2) "two"
127.0.0.1:6379> smembers myset3
1) "two"
2) "one"
127.0.0.1:6379> sinterstore myset5 myset2 myset3
(integer) 1
127.0.0.1:6379> smembers myset5
1) "two"
通过本例的结果可以看出, myset2和myset3 的交集被保存到myset5 中了
返回所有给定key 的并集
127.0.0.1:6379> smembers myset2
1) "three"
2) "two"
127.0.0.1:6379> smembers myset3
1) "two"
2) "one"
127.0.0.1:6379> sunion myset2 myset3
1) "three"
2) "one"
3) "two"
通过本例的结果可以看出, myset2和myset3 的并集被查出来了
1.9 sunionstore
返回所有给定key 的并集,并将结果存为另一个 key
127.0.0.1:6379> smembers myset2
1) "three"
2) "two"
127.0.0.1:6379> smembers myset3
1) "two"
2) "one"
127.0.0.1:6379> sunionstore myset6 myset2 myset3
(integer) 3
127.0.0.1:6379> smembers myset6
1) "three"
2) "one"
3) "two"
通过本例的结果可以看出, myset2和myset3 的并集被保存到myset6 中了
1.10 smove
从第一个key 对应的set中移除member 并添加到第二个对应set中
127.0.0.1:6379> smembers myset2
1) "three"
2) "two"
127.0.0.1:6379> smembers myset3
1) "two"
2) "one"
127.0.0.1:6379> smove myset2 myset7 three
(integer) 1
127.0.0.1:6379> smembers myset7
1) "three"
通过本例可以看到,myset2 的three 被移到 myset7中了
1.11 scard
返回名称为key的 set的元素个数
127.0.0.1:6379> scard myset2
(integer) 1
通过本例可以看到,myset2 的成员数量为1
1.12 sismember
测试member 是否是名称为 key的 set的元素
127.0.0.1:6379> smembers myset2
1) "two"
127.0.0.1:6379> sismember myset2 two
(integer) 1
127.0.0.1:6379> sismember myset2 one
(integer) 0
通过本例可以看到,two是myset2 的成员,而 one不是。
1.13 srandmember
随机返回名称为 key的set的一个元素,但是不删除元素
127.0.0.1:6379> smembers myset3
1) "two"
2) "one"
127.0.0.1:6379> srandmember myset3
"two"
127.0.0.1:6379> srandmember myset3
"one"
sorted set是set的一个升级版本,它在 set的基础上增加了一个顺序属性,这一属性在添加修改元素的时候可以指定,每次指定后,zset会自动重新按新的值调整顺序。可以理解为有两列的mysql表,一列存value,一列存顺序。操作中 key理解为 zset的名字。
和 set 一样 sorted set 也是 string 类型元素的集合,不同的是每个元素都会关联一个 double类型的score。sorted set的实现是skip list和hash table 的混合体。当元素被添加到集合中时,一个元素到score 的映射被添加到hash table中,所以给定一个元素获取score 的开销是 O(1),另一个score 到元素的映射被添加到 skip list,并按照score 排序,所以就可以有序的获取集合中的元素。添加,删除操作开销都是 O(log(N))和 skip list的开销一致,redis的 skip list实现用的是双向链表,这样就可以逆序从尾部取元素。sorted set最经常的使用方式应该是作为索引来使用.我们可以把要排序的字段作为 score 存储,对象的 id当元素存储。下面是 sorted set相关命令
2.1 zadd
向名称为 key 的 zset 中添加元素 member,score 用于排序。如果该元素已经存在,则根据score 更新该元素的顺序
127.0.0.1:6379> zadd myzset 1 "one"
(integer) 1
127.0.0.1:6379> zadd myzset 2 "two"
(integer) 1
127.0.0.1:6379> zadd myzset 3 "two"
(integer) 0
127.0.0.1:6379> zrange myzset 0 -1 withscores
1) "one"
2) "1"
3) "two"
4) "3"
本例中我们向 myzset 中添加了 one 和 two,并且 two 被设置了 2 次,那么将以最后一次的设置为准,最后我们将所有元素都显示出来并显示出了元素的score。
2.2 zrem
删除名称为key的 zset中的元素member
127.0.0.1:6379> zrange myzset 0 -1 withscores
1) "one"
2) "1"
3) "two"
4) "3"
127.0.0.1:6379> zrem myzset two
(integer) 1
127.0.0.1:6379> zrange myzset 0 -1 withscores
1) "one"
2) "1"
可以看到two被删除了
2.3 zincrby
如果在名称为key 的zset中已经存在元素 member,则该元素的score增加 increment;否则向集合中添加该元素,其 score 的值为increment
127.0.0.1:6379> zadd myzset2 1 "one"
(integer) 1
127.0.0.1:6379> zadd myzset2 2 "two"
(integer) 1
127.0.0.1:6379> zincrby myzset2 2 "one"
"3"
127.0.0.1:6379> zrange myzset2 0 -1 withscores
1) "two"
2) "2"
3) "one"
4) "3"
本例中将one 的 score 从1 增加了2,增加到了 3
2.4 zrank
返回名称为key的 zset中member 元素的排名(按 score从小到大排序)即下标
127.0.0.1:6379> zrange myzset3 0 -1 withscores
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
7) "five"
8) "5"
127.0.0.1:6379> zrank myzset3 two
(integer) 1
本例中将two的下标是1,我这里取的是下标,而不是 score
2.5 zrangebyscore
返回集合中score在给定区间的元素
127.0.0.1:6379> zrange myzset3 0 -1 withscores
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
7) "five"
8) "5"
127.0.0.1:6379> zrangebyscore myzset3 2 3 withscores
1) "two"
2) "2"
3) "three"
4) "3"
本例中,返回了 score在2~3区间的元素
2.6 zcount
返回集合中score在给定区间的数量
127.0.0.1:6379> zrange myzset3 0 -1 withscores
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
7) "five"
8) "5"
127.0.0.1:6379> zcount myzset3 2 3
(integer) 2
127.0.0.1:6379>
本例中,计算了 score在2~3之间的元素数目
2.7 zcard
返回集合中元素个数
127.0.0.1:6379> zrange myzset3 0 -1 withscores
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
7) "five"
8) "5"
127.0.0.1:6379> zcard myzset3
(integer) 4
从本例看出myzset3 这个集全的元素数量是4
返回给定元素对应的 score
127.0.0.1:6379> zrange myzset3 0 -1 withscores
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
7) "five"
8) "5"
127.0.0.1:6379> zscore myzset3 two
"2"
此例中我们成功的将 two的score取出来了。
删除集合中排名在给定区间的元素
127.0.0.1:6379> zrange myzset3 0 -1 withscores
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
7) "five"
8) "5"
127.0.0.1:6379> zremrangebyrank myzset3 3 3
(integer) 1
127.0.0.1:6379> zrange myzset3 0 -1 withscores
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
在本例中我们将 myzset3中按从小到大排序结果的下标为3的元素删除了。
2.10 zremrangebyscore
删除集合中score在给定区间的元素
127.0.0.1:6379> zrange myzset3 0 -1 withscores
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
127.0.0.1:6379> zremrangebyscore myzset3 1 2
(integer) 2
127.0.0.1:6379> zrange myzset3 0 -1 withscores
1) "three"
2) "3"
在本例中我们将 myzset3中按从小到大排序结果的 score 在1~2之间的元素删除了。
.