命令不区分大小写,而key是区分大小写的。永远的帮助命令,help @类型
1.字符串:
1.1设置值:set key value [ex seconds] [px milliseconds] [nx|xx]
- ex seconds:为键设置秒级过期时间。
- px milliseconds:为键设置毫秒级过期时间。
- nx:键必须不存在,才可以设置成功,用于添加。
- xx:与nx相反,键必须存在,才可以设置成功,用于更新。
127.0.0.1:6380> set hello world ex 1000 nx
OK
除了set选项,Redis还提供了setex和setnx两个命令:setex key seconds value
setnx key value 它们的作用和ex和nx选项是一样的。
setnx命令的应用场景:由于Redis的单线程命令处理机制,如果有多个客户端同时执行setnx key value,根据setnx的特性只有一个客户端能设置成功,setnx可以作为分布式锁的一种实现方案。
1.2获取值:get key //如果要获取的键不存在,则返回nil(空)
1.3批量设置值:mset key value [key value …]
1.4批量获取值:mget key [key …] //如果有些键不存在,那么它的值为nil(空),结果是按照传入键的顺序返回:
假如没有mget这样的命令,要执行n次get命令具体耗时如下:n次get时间 = n次网络时间 + n次命令时间
使用mget命令后,具体耗时如下:n次get时间 = 1次网络时间 + n次命令时间
批量操作命令可以有效提高开发效率,对于开发人员来说,网络可能会成为性能的瓶颈。但是要注意的是每次批量操作所发送的命令数不是无节制的,如果数量过多可能造成Redis阻塞或者网络拥塞。
1.5计数:incr key
incr命令用于对值做自增操作,返回结果分为三种情况:
- 值不是整数,返回错误。
- 值是整数,返回自增后的结果。
- 键不存在,按照值为0自增,返回结果为1。
除了incr命令,Redis提供了decr(自减)、incrby(自增指定数字)、decrby(自减指定数字)、incrbyfloat(自增浮点数)。
1.6追加值:append key value//append可以向字符串尾部追加值
1.7字符串长度:strlen key
1.8设置并返回原值:getset key value//getset和set一样会设置值,但同时会返回键原来的值
1.9设置指定位置的字符:setrange key offeset value
1.10获取部分字符串:getrange key start end
下表是字符串类型命令时间复杂度:
2.哈希:
2.1设置值:hset key field value//设置成功会返回1,反之会返回0。
hsetnx key field value
2.2获取值:hget key field //如果键或field不存在,会返回nil
2.3删除field:hdel key field [field …]//hdel会删除一个或多个field,返回结果为成功删除field的个数
2.4计算field个数:hlen key
2.5批量设置或获取field-value:hmset key field value [field value …]
hmget key field [field …]
2.6判断field是否存在:hexists key field//返回1包含,0不包含
2.7获取所有field:hkeys key
2.8获取所有value:hvals key
2.9获取所有的field-value:hgetall key
在使用hgetall时,如果哈希元素个数比较多,会存在阻塞Redis的可能。如果开发人员只需要获取部分field,可以使用hmget,如果一定要获取全部field-value,可以使用hscan命令,该命令会渐进式遍历哈希类型。
2.10计数:hincrby hincrbyfloat
hincrby key field
hincrbyfloat key field
hincrby和hincrbyfloat,就像incrby和incrbyfloat命令一样,但是它们的作用域是filed。
2.11计算value的字符串长度(需要Redis3.2以上):hstrlen key field
下表是哈希类型命令的时间复杂度
3.列表
列表(list)类型是用来存储多个有序的字符串,a、b、c、d、e五个元素从左到右组成了一个有序的列表,列表中的每个字符串称为元素(element),一个列表最多可以存储2^32-1个元素。在Redis中,可以对列表两端插入(push)和弹出(pop),还可以获取指定范围的元素列表、获取指定索引下标的元素等。列表是一种比较灵活的数据结构,它可以充当栈和队列的角色,在实际开发上有很多应用场景。
列表类型有两个特点:第一、列表中的元素是有序的,这就意味着可以通过索引下标获取某个元素或者某个范围内的元素列表。第二、列表中的元素可以是重复的。
3.1添加操作
从右边插入元素:rpush key value [value …]
将值 value 插入到列表 key 的表尾,当且仅当 key 存在并且是一个列表。和 RPUSH 命令相反,当 key 不存在时, RPUSHX 命令什么也不做。RPUSHX key value [value …]
从左边插入元素:lpush key value [value …]
将值 value 插入到列表 key 的表头,当且仅当 key 存在并且是一个列表。当 key 不存在时, LPUSHX 命令什么也不做。 LPUSHX key value [value …]
向某个元素前或者后插入元素:linsert key before|after pivot value //当插入成功时返回列表的长度,当列表为空没找到某个元素时返回0,当列表不为空时没找到某个元素时返回-1
3.2查找
获取指定范围内的元素列表:lrange key start end
lrange操作会获取列表指定索引范围所有的元素。索引下标有两个特点:第一,索引下标从左到右分别是0到N-1,但是从右到左分别是-1到-N。第二,lrange中的end选项包含了自身,这个和很多编程语言不包含end不太相同。
获取列表指定索引下标的元素:lindex key index
获取列表长度:llen key
3.3删除
从列表左侧弹出元素:lpop key
从列表右侧弹出:rpop key
删除指定元素:lrem key count value
lrem命令会从列表中找到等于value的元素进行删除,根据count的不同分为三种情况:
-
count>0,从左到右,删除最多count个元素。
-
count<0,从右到左,删除最多count绝对值个元素。
-
count=0,删除所有。
按照索引范围修剪列表:ltrim key start end
3.4修改
修改指定索引下标的元素:lset key index newValue
3.5阻塞操作
blpop key [key …] timeout
brpop key [key …] timeout -
key[key…]:多个列表的键。
-
timeout:阻塞时间(单位:秒)。
1)列表为空:如果timeout=3,那么客户端要等到3秒后返回,如果timeout=0,那么客户端一直阻塞等下去:如果此期间添加了数据element1,客户端立即返回。
2)列表不为空:客户端会立即返回。
在使用brpop时,有两点需要注意。第一点,如果是多个键,那么brpop会从左至右遍历键,一旦有一个键能弹出元素,客户端立即返回:第二点,如果多个客户端对同一个键执行brpop,那么最先执行brpop命令的客户端可以获取到弹出的值。
下表是列表命令时间复杂度
3.6 RPOPLPUSH :RPOPLPUSH source destination
命令 RPOPLPUSH 在一个原子时间内,执行以下两个动作: -
将列表 source 中的最后一个元素(尾元素)弹出,并返回给客户端。
-
将 source 弹出的元素插入到列表 destination ,作为 destination 列表的的头元素。
举个例子,你有两个列表 source 和 destination , source 列表有元素 a, b, c , destination 列表有元素 x, y, z ,执行RPOPLPUSH source destination 之后, source 列表包含元素 a, b , destination 列表包含元素 c, x, y, z ,并且元素 c 会被返回给客户端。
如果 source 不存在,值 nil 被返回,并且不执行其他动作。
如果 source 和 destination 相同,则列表中的表尾元素被移动到表头,并返回该元素,可以把这种特殊情况视作列表的旋转(rotation)操作。
时间复杂度:O(1)
返回值:被弹出的元素。
# source 和 destination 不同
redis> LRANGE alpha 0 -1 # 查看所有元素
1) "a"
2) "b"
3) "c"
4) "d"
redis> RPOPLPUSH alpha reciver # 执行一次 RPOPLPUSH 看看
"d"
redis> LRANGE alpha 0 -1
1) "a"
2) "b"
3) "c"
redis> LRANGE reciver 0 -1
1) "d"
redis> RPOPLPUSH alpha reciver # 再执行一次,证实 RPOP 和 LPUSH 的位置正确
"c"
redis> LRANGE alpha 0 -1
1) "a"
2) "b"
redis> LRANGE reciver 0 -1
1) "c"
2) "d"
# source 和 destination 相同
redis> LRANGE number 0 -1
1) "1"
2) "2"
3) "3"
4) "4"
redis> RPOPLPUSH number number
"4"
redis> LRANGE number 0 -1 # 4 被旋转到了表头
1) "4"
2) "1"
3) "2"
4) "3"
redis> RPOPLPUSH number number
"3"
redis> LRANGE number 0 -1 # 这次是 3 被旋转到了表头
1) "3"
2) "4"
3) "1"
4) "2"
模式: 安全的队列
Redis的列表经常被用作队列(queue),用于在不同程序之间有序地交换消息(message)。一个客户端通过 LPUSH 命令将消息放入队列中,而另一个客户端通过 RPOP 或者 BRPOP 命令取出队列中等待时间最长的消息。
不幸的是,上面的队列方法是『不安全』的,因为在这个过程中,一个客户端可能在取出一个消息之后崩溃,而未处理完的消息也就因此丢失。
使用 RPOPLPUSH 命令(或者它的阻塞版本 BRPOPLPUSH )可以解决这个问题:因为它不仅返回一个消息,同时还将这个消息添加到另一个备份列表当中,如果一切正常的话,当一个客户端完成某个消息的处理之后,可以用 LREM 命令将这个消息从备份表删除。
最后,还可以添加一个客户端专门用于监视备份表,它自动地将超过一定处理时限的消息重新放入队列中去(负责处理该消息的客户端可能已经崩溃),这样就不会丢失任何消息了。
模式:循环列表
通过使用相同的 key 作为 RPOPLPUSH 命令的两个参数,客户端可以用一个接一个地获取列表元素的方式,取得列表的所有元素,而不必像 LRANGE 命令那样一下子将所有列表元素都从服务器传送到客户端中(两种方式的总复杂度都是 O(N))。
以上的模式甚至在以下的两个情况下也能正常工作:
- 有多个客户端同时对同一个列表进行旋转(rotating),它们获取不同的元素,直到所有元素都被读取完,之后又从头开始。
- 有客户端在向列表尾部(右边)添加新元素。
这个模式使得我们可以很容易实现这样一类系统:有 N 个客户端,需要连续不断地对一些元素进行处理,而且处理的过程必须尽可能地快。一个典型的例子就是服务器的监控程序:它们需要在尽可能短的时间内,并行地检查一组网站,确保它们的可访问性。
注意,使用这个模式的客户端是易于扩展(scala)且安全(reliable)的,因为就算接收到元素的客户端失败,元素还是保存在列表里面,不会丢失,等到下个迭代来临的时候,别的客户端又可以继续处理这些元素了。
BRPOPLPUSH:BRPOPLPUSH source destination timeout
BRPOPLPUSH 是 RPOPLPUSH 的阻塞版本,当给定列表 source 不为空时, BRPOPLPUSH 的表现和 RPOPLPUSH 一样。
当列表 source 为空时, BRPOPLPUSH 命令将阻塞连接,直到等待超时,或有另一个客户端对 source 执行 LPUSH 或 RPUSH 命令为止。
超时参数 timeout 接受一个以秒为单位的数字作为值。超时参数设为 0 表示阻塞时间可以无限期延长(block indefinitely) 。
时间复杂度:O(1)
返回值:假如在指定时间内没有任何元素被弹出,则返回一个 nil 和等待时长。反之,返回一个含有两个元素的列表,第一个元素是被弹出元素的值,第二个元素是等待时长。
# 非空列表
redis> BRPOPLPUSH msg reciver 500
"hello moto" # 弹出元素的值
(3.38s) # 等待时长
redis> LLEN reciver
(integer) 1
redis> LRANGE reciver 0 0
1) "hello moto"
# 空列表
redis> BRPOPLPUSH msg reciver 1
(nil)
(1.34s)
4.集合
4.1集合内操作
4.1.1添加元素:sadd key element [element …]//返回结果为添加成功的元素个数
4.1.2删除元素:srem key element [element …]//返回结果为成功删除元素个数
4.1.3计算元素个数:scard key
scard的时间复杂度为O(1),它不会遍历集合所有元素,而是直接用Redis内部的变量
4.1.4判断元素是否在集合中:sismember key element//如果给定元素element在集合内返回1,反之返回0。
4.1.5随机从集合返回指定个数元素:srandmember key [count] //[count]是可选参数,如果不写默认为1
4.1.6从集合随机弹出元素:spop key
需要注意的是Redis从3.2版本开始,spop也支持[count]参数。srandmember和spop都是随机从集合选出元素,两者不同的是spop命令执行后,元素会从集合中删除,而srandmember不会。
4.1.7获取所有元素:smembers key//返回结果是无序的
smembers和lrange、hgetall都属于比较重的命令,如果元素过多存在阻塞Redis的可能性,这时候可以使用sscan来完成。
4.2集合间操作
4.2.1求多个集合的交集:sinter key [key …]
4.2.2求多个集合的并集:suinon key [key …]
4.2.3求多个集合的差集:sdiff key [key …]
4.2.4将交集、并集、差集的结果保存
sinterstore destination key [key …]
suionstore destination key [key …]
sdiffstore destination key [key …]
集合间的运算在元素较多的情况下会比较耗时,所以Redis提供了上面三个命令(原命令+store)将集合间交集、并集、差集的结果保存在destination key中。
4.2.6将 member 元素从 source 集合移动到 destination 集合:SMOVE
SMOVE source destination member//将 member 元素从 source 集合移动到 destination 集合。
SMOVE 是原子性操作。
如果 source 集合不存在或不包含指定的 member 元素,则 SMOVE 命令不执行任何操作,仅返回 0 。否则, member 元素从 source 集合中被移除,并添加到 destination 集合中去。
当 destination 集合已经包含 member 元素时, SMOVE 命令只是简单地将 source 集合中的 member 元素删除。当 source 或 destination 不是集合类型时,返回一个错误。
时间复杂度 :O(1)
返回值:如果 member 元素被成功移除,返回 1 。如果 member 元素不是 source 集合的成员,并且没有任何操作对 destination 集合执行,那么返回 0 。
下表是集合常用命令时间复杂度
5.有序集合
有序集合中的元素不能重复,但是score可以重复,有序集合中的元素可以根据分数(score)排序。有序集合提供了获取指定分数和元素范围查询、计算成员排名等功能,合理的利用有序集合,能帮助我们在实际开发中解决很多问题。
列表、集合、有序集合三者的异同点:
5.1集合内
5.1.1添加成员:zadd key [NX|XX] [GT|LT] [CH] [INCR] score member [score member …]//返回结果代表成功添加成员的个数
- XX:只更新已经存在的元素,不添加新元素 NX:只添加新元素,不更新已有元素
- LT:新元素会添加;对于已存在元素,当新score值小于当前score值时才会更新
- GT:新元素会添加;对于已存在元素,当新score值大于当前score值时才会更新
- CH:改变返回值的计算逻辑。默认返回的是新添加的元素个数,提供该参数后返回被改变的元素个数:即新增的元素个数和score值被更新的元素个数之和。如果元素已经存在,且新的score值与当前score值一样,不会被计数
- INCR:提供该参数后的命令类似ZINCRBY,将score加上一个值,只允许提供一个member和score
注意:GT、LT 和 NX 选项是互斥的。
有序集合相比集合提供了排序字段,但是也产生了代价,zadd的时间复杂度为O(log(n)),sadd的时间复杂度为O(1)。
127.0.0.1:6379> zadd user:ranking nx 1 kris 91 mike 200 frank 220 tim 250 martin
(integer) 5
5.1.2计算成员个数:zcard key
5.1.3计算某个成员的分数:zscore key member
5.1.4计算成员的排名:zrank key member
zrevrank key member//zrank是从分数从低到高返回排名,zrevrank反之(排名从0开始计算)。
5.1.5删除成员:zrem key member [member …]//返回结果为成功删除的个数。
5.1.6增加成员的分数:zincrby key increment member
5.1.7返回指定排名范围的成员:zrange key start end [withscores]
zrevrange key start end [withscores]
有序集合是按照分值排名的,zrange是从低到高返回,zrevrange反之。下面代码返回排名最低的是三个成员,如果加上withscores选项,同时会返回成员的分数。
5.1.8返回指定分数范围的成员:zrangebyscore key min max [withscores] [limit offset count]
zrevrangebyscore key max min [withscores] [limit offset count]
其中zrangebyscore按照分数从低到高返回,zrevrangebyscore反之。withscores选项会同时返回每个成员的分数。[limit offset count]选项可以限制输出的起始位置和个数:同时min和max还支持开区间(小括号)和闭区间(中括号),-inf和+inf分别代表无限小和无限大:
127.0.0.1:6379> zrangebyscore user:ranking (200 +inf withscores
1) "tim"
2) "220"
3) "martin"
4) "250"
5) "tom"
6) "260"
5.1.9返回指定分数范围成员个数:zcount key min max
5.1.10删除指定排名内的升序元素:zremrangebyrank key start end
5.1.11删除指定分数范围的成员:zremrangebyscore key min max
5.2集合间的操作
127.0.0.1:6379> zadd user:ranking:1 1 kris 91 mike 200 frank 220 tim 250 martin 251 tom
(integer) 6
127.0.0.1:6379> zadd user:ranking:2 8 james 77 mike 625 martin 888 tom
(integer) 4
5.2.2交集:
zinterstore destination numkeys key [key …] [weights weight [weight …]][aggregate sum|min|max]
- destination:交集计算结果保存到这个键。
- numkeys:需要做交集计算键的个数。
- key[key…]:需要做交集计算的键。
- weights weight[weight…]:每个键的权重,在做交集计算时,每个键中的每个member会将自己分数乘以这个权重,每个键的权重默认是1。
- aggregate sum|min|max:计算成员交集后,分值可以按照sum(和)、min(最小值)、max(最大值)做汇总,默认值是sum。
127.0.0.1:6379> zinterstore user:ranking:1_inter_2 2 user:ranking:1 user:ranking:2 weights 1 0.5 aggregate max
(integer) 2
127.0.0.1:6379> zrange user:ranking:1_inter_2 0 -1 withscores
1) "mike"
2) "91"
3) "martin"
4) "312.5"
5.2.3并集
zunionstore destination numkeys key [key …] [weights weight [weight …]][aggregate sum|min|max]
该命令的所有参数和zinterstore是一致的
127.0.0.1:6379> zunionstore user:ranking:1_inter_2 2 user:ranking:1 user:ranking:2 weights 1 0.5 aggregate max
(integer) 7
127.0.0.1:6379> zrange user:ranking:1_inter_2 0 -1 withscores
1) "kris"
2) "1"
3) "james"
4) "4"
5) "mike"
6) "91"
7) "frank"
8) "200"
9) "tim"
10) "220"
11) "martin"
12) "312.5"
13) "tom"
14) "444"
下表是有序集合命令的时间复杂度