Redis常用命令详解(中)

2.7 type

返回key所存储的value的数据结构类型

返回值

返回当前key的数据类型,如果key不存在时返回none

rename

将key重命名为newkey,如果key与newkey相同,将返回一个错误

如果newkey已经存在,则值将被覆盖


返回值

simple-string-reply

renamenx

当且仅当 newkey 不存在时,将 key 改名为 newkey

当 key 不存在时,返回一个错误

返回值

integer-reply:OK

  • 修改成功时,返回 1 。
  • 如果 newkey 已经存在,返回 0

randomkey

从当前数据库返回一个随机的key

3 string命令

setex

设置key对应字符串value,并且设置key在给定的seconds时间之后超时过期。这个命令等效于执行下面的命令

SET mykey value
EXPIRE mykey seconds

SETEX是原子的,也可以通过把上面两个命令放到MULTI/EXEC块中执行的方式重现。相比连续执行上面两个命令,它更快,因为当Redis当做缓存使用时,这个操作更加常用。

返回值

simple-string-replyOK

psetex

PSETEXSETEX一样,唯一的区别是到期时间以毫秒为单位,而不是秒

getset(具有原子性)

自动将key对应到value并且返回原来key对应的value

如果key存在但是对应的value不是字符串,就返回错误


GETSET可以和INCR一起使用实现支持重置的计数功能。

举个例子:每当有事件发生的时候,一段程序都会调用INCR给key mycounter加1,但是有时我们需要获取计数器的值,并且自动将其重置为0。这可以通过GETSET mycounter “0”来实现:

INCR mycounter
GETSET mycounter "0"
GET mycounter

返回值

bulk-string-reply: 返回之前的旧值,如果之前Key不存在将返回nil

mset

对应给定的keys到他们相应的values上。

MSET会用新的value替换已经存在的value,就像普通的SET命令一样

MSET是原子的,所以所有给定的keys是一次性set的。客户端不可能看到这种一部分keys被更新而另外的没有改变的情况

返回值

simple-string-reply:总是OK,因为MSET不会失败

##mget

返回所有指定的key的value。对于每个不对应string或者不存在的key,都返回特殊值nil。正因为此,这个操作从来不会失败。

返回值

array-reply: 指定的key对应的values的list

setnx(防止set覆盖问题,具有原子性)

key设置值为value

如果key不存在,这种情况下等同set

key存在时,什么也不做

SETNX是”SET if Not eXists”的简写

返回值

Integer reply, 特定值

  • 1 如果key被设置了
  • 0 如果key没有被设置

msetnx

对应给定的keys到他们相应的values上

只要有一个key已存在,MSETNX一个操作都不会执行

由于这种特性,MSETNX可以实现要么所有的操作都成功,要么一个都不执行,这样可以用来设置不同的key,来表示一个唯一的对象的不同字段


MSETNX是原子的,所以所有给定的keys是一次性set的

客户端不可能看到这种一部分keys被更新而另外的没有改变的情况

返回值

integer-reply,只有以下两种值:

  • 1 如果所有的key被set
  • 0 如果没有key被set(至少其中有一个key是存在的)

incr

对存储在指定key的数值执行原子的加1操作

如果指定的key不存在,那么在执行incr操作之前,会先将它的值设定为0

返回值

integer-reply:执行递增操作后key对应的值

##incrby

将key对应的数字加decrement

如果key不存在,操作之前,key就会被置为0。

###返回值

integer-reply: 增加之后的value值

decr

对key对应的数字做减1操作

如果key不存在,那么在操作之前,这个key对应的值会被置为0

返回值

数字:减小之后的value

decrby

将key对应的数字减decrement

如果key不存在,操作之前,key就会被置为0

返回值

数字:减少之后的value值

apend

如果 key 已经存在,并且值为字符串,那么这个命令会把 value 追加到原来值(value)的结尾

如果 key 不存在,那么它将首先创建一个空字符串的key,再执行追加操作,这种情况 APPEND 将类似于 SET 操作。


返回值

Integer reply:返回append后字符串值(value)的长度

4 hashes

3.1 hset key field value [field value …]

2.0.0提供。

时间复杂度:O(1)对每个字段/值对添加,因此 O(N) 在调用具有多个字段/值对的命令时添加 N 个字段/值对。

设置存储在键到值的哈希中的字段。如果key不存在,则创建一个持有哈希的新key。如果哈希中已存在字段,则覆盖该字段。

Redis 4.0.0 起,HSET 是万数值,允许多个字段/值对。

设置 key 指定的哈希集中指定字段的值

如果 key 指定的哈希集不存在,会创建一个新的哈希集并与 key 关联

如果字段在哈希集中存在,它将被重写

返回值

添加的字段数。

  • 1:如果field是一个新的字段
  • 0:如果filed原来在hash里已存在
  • Redis常用命令详解(中)

3.2 hexists key field

返回hash里面field是否存在

返回值

integer-reply, 含义如下

  • 1 hash里面包含该field
  • 0 hash里面不包含该field或者key不存在

3. hget key field

返回 key 指定的哈希集中该字段所关联的值

返回值

bulk-string-reply:该字段所关联的值

当字段不存在或者 key 不存在时返回nil

4. hgetall key

返回 key 指定的哈希集中所有的字段和值

返回值中,每个字段名的下一个是它的值,所以返回值的长度是哈希集大小的两倍

返回值

array-reply:哈希集中字段和值的列表。当 key 指定的哈希集不存在时返回空列表。

hkeys key

返回 key 指定的哈希集中所有字段的名字

返回值

array-reply:哈希集中的字段列表,当 key 指定的哈希集不存在时返回空列表

hvals key

返回 key 指定的哈希集中所有字段的值

返回值

array-reply:哈希集中的值的列表,当 key 指定的哈希集不存在时返回空列表。

7. hlen

返回 key 指定的哈希集包含的字段的数量

返回值

integer-reply: 哈希集中字段的数量,当 key 指定的哈希集不存在时返回 0

8. hmget

返回 key 指定的哈希集中指定字段的值。

对于哈希集中不存在的每个字段,返回 nil 值。因为不存在的keys被认为是一个空的哈希集,对一个不存在的 key 执行 HMGET 将返回一个只含有 nil 值的列表

返回值

array-reply:含有给定字段及其值的列表,并保持与请求相同的顺序。

##9. hmset key field value [field value …]

设置 key 指定的哈希集中指定字段的值。该命令将重写所有在哈希集中存在的字段。如果 key 指定的哈希集不存在,会创建一个新的哈希集并与 key 关联


10. hsetnx key field value

只在 key 指定的哈希集中不存在指定的字段时,设置字段的值

如果 key 指定的哈希集不存在,会创建一个新的哈希集并与 key 关联

如果字段已存在,该操作无效果

4 list

双向列表,适用于最新列表,关注列表

1. lpush

将指定的值插入列表头

  • key 不存在, push 前会创建一个空列表
  • key 对应的值不是一个 list 的话,那么会返回一个错误

可以使用一个命令把多个元素 push 进入列表,只需在命令末尾加上多个指定的参数

元素是从最左端的到最右端的、一个接一个被插入到 list 的头部

lpush mylist a b c
返回的列表是 c 为第一个元素, b 为第二个元素, a 为第三个元素

返回值

push 后的 list 长

2. llen

返回存储在 key 里的list的长度

如果 key 不存在,那么就被看作是空list,并且返回长度为 0

当存储在 key 里的值不是一个list的话,会返回error

返回值

key对应的list的长

3. lrange key start stop

返回存储在 key 的列表里指定范围内的元素

start 和 end 偏移量都是基于0的下标,即list的第一个元素下标是0(list的表头),第二个元素下标是1,以此类推


偏移量也可以是负数,表示偏移量是从list尾部开始计数。 例如, -1 表示列表的最后一个元素,-2 是倒数第二个,以此类推。

求范围函数的一致性

需要注意的是,如果你有一个list,里面的元素是从0到100,那么 LRANGE list 0 10 这个命令会返回11个元素,即最右边的那个元素也会被包含在内。 在你所使用的编程语言里,这一点可能是也可能不是跟那些求范围有关的函数都是一致的。(像Ruby的 Range.new,Array#slice 或者Python的 range() 函数。)

超过范围的下标

当下标超过list范围的时候不会产生error。 如果start比list的尾部下标大的时候,会返回一个空列表。 如果stop比list的实际尾部大的时候,Redis会当它是最后一个元素的下标。

返回值

指定范围里的列表元素

##4. lset key index value

设置 index 位置的list元素的值为 value

当index超出范围时会返回一个error

##5. lindex key index

返回列表里的元素的索引 index 存储在 key 里面。

下标是从0开始,-1 表示最后一个元素

当 key 位置的值不是一个列表的时候,会返回一个error

返回值

bulk-reply:请求的对应元素,或者当 index 超过范围的时候返回 nil

##6. lpop

移除并且返回 key 对应的 list 的第一个元素

返回值

bulk-string-reply返回第一个元素的值,或者当 key 不存在时返回 nil。

7 rpop

移除并返回存于 key 的 list 的最后一个元素。

返回值

bulk-string-reply最后一个元素的值

或 key 不存在时,返回 nil

8 bl-pop key [key …] timeout

阻塞列表的弹出

是命令 l-pop的阻塞版本,当给定列表内没有元素可供弹出时, 连接将被阻塞

当给定多个 key 参数时,按参数 key 的先后顺序依次检查各个列表,弹出第一个非空列表的头元素

8.1 非阻塞行为

被调用时,如果给定 key 内至少有一个非空列表,那么弹出遇到的第一个非空列表的头元素,并和被弹出元素所属的列表的名字 key 一起,组成结果返回给调用者

设 key list1 不存在,而 list2 和 list3 都是非空列表

BLPOP list1 list2 list3 0

BLPOP 保证返回一个存在于 list2 里的元素(因为它是从 list1 –> list2 –> list3 这个顺序查起的第一个非空列表)。


8.2 阻塞行为

如果所有给定 key 都不存在或包含空列表,则BLPOP将阻塞连接, 直到有另一个客户端对给定的这些 key 的任意一个执行 LPUSH或 RPUSH。

一旦有新的数据出现在其中一个列表里,那么这个命令会解除阻塞状态,并且返回 key 和弹出的元素值。


当命令引起客户端阻塞并且设置了一个非零的超时参数 timeout 时, 若经过了指定的 timeout 仍没有出现一个针对某一特定 key 的 push 操作,则客户端会解除阻塞状态并且返回一个 nil 的多组合值(multi-bulk value)


timeout 参数表示的是一个指定阻塞的最大秒数的整型值

当 timeout 为 0 是表示阻塞时间无限制

8.3 什么 key 会先被处理?是什么客户端?什么元素?

  • 当客户端为多个 key 尝试阻塞的时候,若至少存在一个 key 拥有元素,那么返回的键值对(key/element pair)就是从左到右数第一个拥有一个或多个元素的key。
    在这种情况下客户端不会被阻塞
  • 当多个客户端为同一个 key 阻塞的时候,第一个被处理的客户端是等待最长时间的那个(即第一个因为该key而阻塞的客户端)。 一旦一个客户端解除阻塞那么它就不会保持任何优先级,当它因为下一个 BLPOP 命令而再次被阻塞的时候,会在处理完那些 被同个 key 阻塞的客户端后才处理它(即从第一个被阻塞的处理到最后一个被阻塞的)。

当一个客户端同时被多个 key 阻塞时,若多个 key 的元素同时可用(可能是因为事务或者某个Lua脚本向多个list添加元素), 那么客户端会解除阻塞,并使用第一个接收到 push 操作的 key(假设它拥有足够的元素为我们的客户端服务,因为有可能存在其他客户端同样是被这个key阻塞着)。 从根本上来说,在执行完每个命令之后,Redis 会把一个所有 key 都获得数据并且至少使一个客户端阻塞了的 list 运行一次。 这个 list 按照新数据的接收时间进行整理,即是从第一个接收数据的 key 到最后一个。在处理每个 key 的时候,只要这个 key 里有元素, Redis就会对所有等待这个key的客户端按照“先进先出”(FIFO)的顺序进行服务。若这个 key 是空的,或者没有客户端在等待这个 key, 那么将会去处理下一个从之前的命令或事务或脚本中获得新数据的 key,如此等等。

当多个元素被 push 进入一个 list 时 BLPOP

有时候一个 list 会在同一概念的命令的情况下接收到多个元素:

  • 像 LPUSH mylist a b c 这样的可变 push 操作。
  • 在对一个向同一个 list 进行多次 push 操作的 MULTI 块执行完 EXEC 语句后。

使用 Redis 2.6 或者更新的版本执行一个 Lua 脚本。

当多个元素被 push 进入一个被客户端阻塞着的 list 的时候,Redis 2.4 和 Redis 2.6 或者更新的版本所采取行为是不一样的。


对于 Redis 2.6 来说,所采取的行为是先执行多个 push 命令,然后在执行了这个命令之后再去服务被阻塞的客户端。看看下面命令顺序。

Client A:   BLPOP foo 0
Client B:   LPUSH foo a b c

如果上面的情况是发生在 Redis 2.6 或更高版本的服务器上,客户端 A 会接收到 c 元素,因为在 [LPUSH]执行后,list 包含了 c,b,a 这三个元素,所以从左边取一个元素就会返回 c。


相反,Redis 2.4 是以不同的方式工作的:客户端会在 push 操作的上下文中被服务,所以当 LPUSH foo a b c 开始往 list 中 push 第一个元素,它就被传送给客户端A,也就是客户端A会接收到 a(第一个被 push 的元素)。


Redis 2.4的这种行为会在复制或者持续把数据存入AOF文件的时候引发很多问题,所以为了防止这些问题,很多更一般性的、并且在语义上更简单的行为被引入到 Redis 2.6 中。


需要注意的是,一个Lua脚本或者一个 MULTI / EXEC 块可能会 push 一堆元素进入一个 list 后,再 删除这个 list。 在这种情况下,被阻塞的客户端完全不会被服务,并且只要在执行某个单一命令、事务或者脚本后 list 中没有出现元素,它就会被继续阻塞下去。

上一篇:阿里云RDS for SQL Server使用的一些最佳实践


下一篇:Data Lake Analytics-数据分析时代迎来新变革