Redis基础命令 Generic:通用命令 1.DEL命令
命令复杂度 : 删除键的复杂度为 O(N),其中 N 是要删除的键的数量。如果要删除的键包含的不是string,那么该键的复杂度为 O(M),其中 M 是list、set、sorted set或hash中的元素数量。删除单个包含string的键的复杂度为 O(1)。
删除操作 : 指定的键会被删除。如果键不存在,则会被忽略。
返回值 : 命令执行后会返回一个整数回复,表示被删除的键的数量。
1 2 3 4 5 6 7 redis> SET key1 "Hello" "OK" redis> SET key2 "World" "OK" redis> DEL key1 key2 key3 (integer) 2 redis>
2.EXISTS命令
命令复杂度 : 该命令的复杂度为O(N),其中N是要检查的键的数量。
计数方式 :如果在参数中多次提到同一个已存在的键,它将被多次计数。例如,如果somekey
存在,那么EXISTS somekey somekey
将返回2。
返回值 : 该命令返回指定参数中存在的键的数量。
1 2 3 4 5 6 7 8 9 10 11 redis> SET key1 "Hello" "OK" redis> EXISTS key1 (integer) 1 redis> EXISTS nosuchkey (integer) 0 redis> SET key2 "World" "OK" redis> EXISTS key1 key2 nosuchkey (integer) 2 redis>
3.EXPIRE命令 1 EXPIRE key seconds [NX | XX | GT | LT]
命令复杂度 : 该命令的复杂度为O(1)。
键的超时 :在Redis中,可以为键设置超时,超时后键会自动删除。使用超时的键通常被称为易失性键。
持久化和重命名 :使用PERSIST
命令可以清除超时,将键转换为持久键。如果使用RENAME
命令重命名键,关联的生存时间也会转移到新的键名。
这个命令支持一组选项:
NX :仅当键没有到期时间时设置到期时间
XX :仅当键已经有到期时间时设置到期时间
GT :仅当新的到期时间大于当前到期时间时设置到期时间
LT :仅当新的到期时间小于当前到期时间时设置到期时间
返回值 :对于已设置过期时间的键,EXPIRE 命令会返回 0,并且不会改变其过期时间。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 redis> SET mykey "Hello" "OK" redis> EXPIRE mykey 10 (integer) 1 redis> TTL mykey (integer) 10 redis> SET mykey "Hello World" "OK" redis> TTL mykey (integer) -1 redis> EXPIRE mykey 10 XX (integer) 0 redis> TTL mykey (integer) -1 redis> EXPIRE mykey 10 NX (integer) 1 redis> TTL mykey (integer) 10 redis>
4.KEYS命令
命令复杂度 : 该命令的复杂度为O(N),其中 N 是数据库中键的数量,假设数据库中的键名和给定的模式具有有限的长度。尽管该操作的时间复杂度为 O(N),但常数时间相当低。例如,运行在入门级笔记本电脑上的 Redis 可以在 40 毫秒内扫描一个包含 100 万个键的数据库。
支持的 glob
风格模式:
h?llo
匹配 hello、hallo 和 hxllo
h*llo
匹配 hllo 和 heeeello
h[ae]llo
匹配 hello 和 hallo,但不匹配 hillo
h[^e]llo
匹配 hallo、hbllo,但不匹配 hello
h[a-b]llo
匹配 hallo 和 hbllo
返回值 :该命令返回与指定模式匹配的所有键。
[!WARNING]
警告:请谨慎使用 KEYS
命令,只在生产环境中极度小心地使用。当对大型数据库执行该命令时,可能会影响性能。此命令旨在用于调试和特殊操作,比如更改键空间布局。不要在常规应用程序代码中使用 KEYS。如果要在键空间的子集中查找键,考虑使用 SCAN
或 sets
。
1 2 3 4 5 6 7 8 9 10 11 12 redis> MSET firstname Jack lastname Stuntman age 35 "OK" redis> KEYS *name* 1) "firstname" 2) "lastname" redis> KEYS a?? 1) "age" redis> KEYS * 1) "age" 2) "firstname" 3) "lastname" redis>
5.OBJECT ENCODING命令
6.OBJECT FREQ命令
命令复杂度 : 该命令的复杂度为O(1)。
限制 :该命令仅在 maxmemory-policy
配置指令设置为 LFU
策略之一时才可用。
返回值 :该命令返回存储在 <key>
处的 Redis 对象的对数访问频率计数器
。
7.PERSIST命令
命令复杂度 : 该命令的复杂度为O(1)。
作用 :移除键上的现有超时,将键从易失性(设置了过期时间的键)变为持久性(不会过期的键,因为没有关联的超时)。
返回值 :
如果键不存在或没有关联的超时,则返回 0。
如果超时已被移除,则返回 1。
1 2 3 4 5 6 7 8 9 10 11 redis> SET mykey "Hello" "OK" redis> EXPIRE mykey 10 (integer) 1 redis> TTL mykey (integer) 10 redis> PERSIST mykey (integer) 1 redis> TTL mykey (integer) -1 redis>
8.RENAME命令
命令复杂度 : 该命令的复杂度为O(1)。
作用 :将键重命名为 newkey。当键不存在时,它会返回错误。如果 newkey 已经存在,它将被覆盖。在这种情况下,RENAME 将执行一个隐式的 DEL 操作
,因此,即使 RENAME 本身通常是一个常数时间的操作,如果被删除的键包含一个非常大的值,也可能会导致高延迟。
[!WARNING]
在集群模式下,key 和 newkey 必须位于相同的哈希槽
中,这意味着在实践中,只有具有相同哈希标签
的键才能在集群中可靠地重命名。
1 2 3 4 5 6 7 redis> SET mykey "Hello" "OK" redis> RENAME mykey myotherkey "OK" redis> GET myotherkey "Hello" redis>
9.SCAN命令 1 SCAN cursor [MATCH pattern] [COUNT count] [TYPE type]
命令复杂度 : 该命令的复杂度为O(1),对于完整的迭代,包括足够的命令调用使游标返回到0,时间复杂度为 O(N),其中 N 是集合内的元素数量。
SCAN 命令及其紧密相关的命令 SSCAN、HSCAN 和 ZSCAN 用于逐步迭代一组元素:
SCAN
迭代当前选定的 Redis 数据库中的键集。
SSCAN
迭代集合类型的元素。
HSCAN
迭代哈希类型的字段及其关联的值。
ZSCAN
迭代有序集合类型的元素及其关联的分数。
注意,SCAN、SSCAN、HSCAN 和 ZSCAN 的工作方式非常相似,因此本文档涵盖了这四个命令。然而,明显的区别是在 SSCAN、HSCAN 和 ZSCAN 的情况下,第一个参数是持有 Set
、Hash
或 Sorted Set
值的键名。SCAN 命令不需要任何键名参数,因为它迭代当前数据库
中的键,所以被迭代的对象是数据库本身。
[!WARNING]
由于这些命令允许增量迭代
,每次只返回少量元素,因此它们可以在生产环境中使用
,而不会像 KEYS 或 SMEMBERS 命令那样产生一些不利的影响,当对大型键集或元素集合调用时,可能会导致服务器阻塞很长时间(甚至几秒钟)。
然而,尽管像 SMEMBERS 这样的阻塞命令能够提供在给定时刻作为集合一部分的所有元素,但是 SCAN 系列命令只能对返回的元素提供有限的保证,因为在迭代过程中我们增量迭代的集合可能会发生变化。
SCAN 是基于游标的迭代器
。这意味着在每次调用命令时,服务器都会返回一个更新后的游标
,用户需要将其作为下一次调用中的游标参数使用。迭代从将游标设置为 0 开始,并在服务器返回的游标为 0 时终止。以下是 SCAN 迭代的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 redis 127.0.0.1:6379> scan 0 1) "17" 2) 1) "key:12" 2) "key:8" 3) "key:4" 4) "key:14" 5) "key:16" 6) "key:17" 7) "key:15" 8) "key:10" 9) "key:3" 10) "key:7" 11) "key:1" redis 127.0.0.1:6379> scan 17 1) "0" 2) 1) "key:5" 2) "key:18" 3) "key:0" 4) "key:2" 5) "key:19" 6) "key:13" 7) "key:6" 8) "key:9" 9) "key:11"
10.TTL命令
命令复杂度 : 该命令的复杂度为O(1)。
返回值 :
以秒为单位的 TTL。
如果键存在但没有关联的到期时间,则返回 -1。
如果键不存在,则返回 -2。
1 2 3 4 5 6 7 redis> SET mykey "Hello" "OK" redis> EXPIRE mykey 10 (integer) 1 redis> TTL mykey (integer) 10 redis>
11.TYPE命令
命令复杂度 : 该命令的复杂度为O(1)。
返回值 :返回存储在键中值的类型的字符串表示。可能返回的不同类型包括:string(字符串)、list(列表)、set(集合)、zset(有序集合)、hash(哈希)和 stream(流)。
1 2 3 4 5 6 7 8 9 10 11 12 13 redis> SET key1 "value" "OK" redis> LPUSH key2 "value" (integer) 1 redis> SADD key3 "value" (integer) 1 redis> TYPE key1 "string" redis> TYPE key2 "list" redis> TYPE key3 "set" redis>
12.UNLINK命令
命令复杂度 :每次删除键都是 O(1)的时间复杂度,无论其大小如何。然后,命令会在不同的线程
中执行 O(N) 的工作以回收内存,其中 N 是被删除对象所包含的元素数量。
作用 :该命令与 DEL 非常相似,它会删除指定的键。就像 DEL 一样,如果键不存在,则会被忽略。然而,该命令会在不同的线程中执行实际的内存回收,因此它不会阻塞
,而 DEL 会。这就是命令名称的由来:该命令只是从键空间中取消链接键。实际的删除操作会稍后以异步
方式进行。
返回值 :返回已取消链接的键的数量。
1 2 3 4 5 6 7 redis> SET key1 "Hello" "OK" redis> SET key2 "World" "OK" redis> UNLINK key1 key2 key3 (integer) 2 redis>
String:字符串命令 1.SET命令 1 SET key value [NX | XX] [GET] [EX seconds | PX milliseconds | EXAT unix-time-seconds | PXAT unix-time-milliseconds | KEEPTTL]
命令复杂度 : 该命令的复杂度为O(1)。
作用 :将键设置为保存字符串值。如果键已经保存了一个值,则无论其类型如何都会被覆盖。在成功的 SET 操作中,与键关联的任何先前的过期时间都将被丢弃。
SET 命令支持一组选项,修改其行为:
EX seconds
:设置指定的到期时间,单位为秒(正整数)。
PX milliseconds
:设置指定的到期时间,单位为毫秒(正整数)。
EXAT timestamp-seconds
:设置键在指定的 Unix 时间点到期,单位为秒(正整数)。
PXAT timestamp-milliseconds
:设置键在指定的 Unix 时间点到期,单位为毫秒(正整数)。
NX
:仅当键不存在时设置键。
XX
:仅当键已存在时设置键。
KEEPTTL
:保留与键关联的到期时间。
GET
:返回键处存储的旧字符串值,如果键不存在,则返回 nil。如果键处存储的值不是字符串,则返回错误并且 SET 操作中止。
1 2 3 4 5 6 7 redis> SET mykey "Hello" "OK" redis> GET mykey "Hello" redis> SET anotherkey "will expire in a minute" EX 60 "OK" redis>
2.GET命令
命令复杂度 : 该命令的复杂度为O(1)。
返回值 :获取键的值。如果键不存在,则返回特殊值 nil。如果存储在键处的值不是字符串,则返回错误,因为 GET 只处理字符串值。
1 2 3 4 5 6 7 redis> GET nonexisting (nil) redis> SET mykey "Hello" "OK" redis> GET mykey "Hello" redis>
3.MSET命令 1 MSET key value [key value ...]
命令复杂度 : 该命令的复杂度为O(N),其中 N 是键值对的个数。
作用 :将给定的键设置为它们各自的值。MSET 将现有的值替换为新值,就像普通的 SET 一样。如果不想覆盖现有值,请参见 MSETNX。
MSET 是原子的,因此所有给定的键都会同时设置
。客户端无法看到某些键已更新而其他键保持不变。
1 2 3 4 5 6 7 redis> MSET key1 "Hello" key2 "World" "OK" redis> GET key1 "Hello" redis> GET key2 "World" redis>
4.MGET命令
命令复杂度 : 该命令的复杂度为O(N),其中 N 是取出的键值对的个数。
返回值 :返回所有指定键的值。对于每个不持有字符串值或不存在的键,都返回特殊值 nil。因此,该操作永远不会失败。
1 2 3 4 5 6 7 8 9 redis> SET key1 "Hello" "OK" redis> SET key2 "World" "OK" redis> MGET key1 key2 nonexisting 1) "Hello" 2) "World" 3) (nil) redis>
5.INCR命令
命令复杂度 : 该命令的复杂度为O(1)。
作用 :将存储在键处的数字增加一。如果键不存在,则在执行操作之前将其设置为 0
。如果键包含错误类型的值或包含无法表示为整数的字符串,则返回错误。此操作仅限于 64 位有符号整数。
返回值 :返回递增后的整数值。
注意:这是一个字符串操作,因为 Redis 没有专门的整数类型。存储在键处的字符串被解释为一个十进制 64 位有符号整数来执行操作。Redis 使用int编码方案表示整数,因此对于实际保存整数的字符串值,存储字符串表示形式的整数不会产生额外开销。
1 2 3 4 5 6 7 redis> SET mykey "10" "OK" redis> INCR mykey (integer) 11 redis> GET mykey "11" redis>
6.INCRBY命令
命令复杂度 : 该命令的复杂度为O(1)。
作用 :将存储在键处的数字增加指定的增量。如果键不存在,则在执行操作之前将其设置为 0
。如果键包含错误类型的值或包含无法表示为整数的字符串,则返回错误。此操作仅限于 64 位有符号整数。
1 2 3 4 5 redis> SET mykey "10" "OK" redis> INCRBY mykey 5 (integer) 15 redis>
7.INCRBYFLOAT命令 1 INCRBYFLOAT key increment
命令复杂度 : 该命令的复杂度为O(1)。
作用 :将存储在键中的表示浮点数的字符串按指定的增量递增。通过使用负的增量值,结果是将键处存储的值递减。如果键不存在,则在执行操作之前将其设置为 0
。如果发生以下条件之一,则返回错误:
键包含错误类型的值(不是字符串)。
当前键内容或指定的增量无法解析为双精度浮点数。
如果命令成功,则将新的递增值存储为键的新值(替换旧值),并作为字符串返回给调用者。
字符串键中已包含的值和递增参数都可以选择以指数表示法提供,但是在递增之后计算的值始终以相同的格式存储,即一个整数数字,后跟(如果需要)一个点,以及表示数字小数部分的变长数字。尾随的零总是被删除。
1 2 3 4 5 6 7 8 9 10 11 redis> SET mykey 10.50 "OK" redis> INCRBYFLOAT mykey 0.1 "10.6" redis> INCRBYFLOAT mykey -5 "5.6" redis> SET mykey 5.0e3 "OK" redis> INCRBYFLOAT mykey 2.0e2 "5200" redis>
8.STRLEN命令
命令复杂度 : 该命令的复杂度为O(1)。
返回值 :返回存储在键处的字符串值的长度。当键持有非字符串值时,返回错误。
1 2 3 4 5 6 7 redis> SET mykey "Hello world" "OK" redis> STRLEN mykey (integer) 11 redis> STRLEN nonexisting (integer) 0 redis>
Hash:哈希命令 1.HSET命令 1 HSET key field value [field value ...]
命令复杂度 :每添加一个键值对的时间复杂度为 O(1),因此当命令以多个键值对调用时,添加 N 个键值对的时间复杂度为 O(N)。
作用 :该命令将覆盖哈希中存在的指定字段的值。如果键不存在,则创建一个持有哈希的新键。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 redis> HSET myhash field1 "Hello" (integer) 1 redis> HGET myhash field1 "Hello" redis> HSET myhash field2 "Hi" field3 "World" (integer) 2 redis> HGET myhash field2 "Hi" redis> HGET myhash field3 "World" redis> HGETALL myhash 1) "field1" 2) "Hello" 3) "field2" 4) "Hi" 5) "field3" 6) "World" redis>
2.HGET命令
命令复杂度 : 该命令的复杂度为O(1)。
返回值 :返回 key 所对应的 hash 结构的 field 字段的值。
1 2 3 4 5 6 7 redis> HSET myhash field1 "foo" (integer) 1 redis> HGET myhash field1 "foo" redis> HGET myhash field2 (nil) redis>
3.HGETALL命令
命令复杂度 : 该命令的时间复杂度为 O(N),其中 N 是哈希表的大小。
返回值 :返回存储在键中的哈希表的所有字段和值。在返回的值中,每个字段名都跟随其值,因此回复的长度是哈希表大小的两倍。
1 2 3 4 5 6 7 8 9 10 redis> HSET myhash field1 "Hello" (integer) 1 redis> HSET myhash field2 "World" (integer) 1 redis> HGETALL myhash 1) "field1" 2) "Hello" 3) "field2" 4) "World" redis>
4.HKEYS命令
命令复杂度 : 该命令的时间复杂度为 O(N),其中 N 是哈希表的大小。
返回值 :返回存储在键中的哈希表中的所有字段名。
1 2 3 4 5 6 7 8 redis> HSET myhash field1 "Hello" (integer) 1 redis> HSET myhash field2 "World" (integer) 1 redis> HKEYS myhash 1) "field1" 2) "field2" redis>
5.HVALS命令
命令复杂度 : 该命令的时间复杂度为 O(N),其中 N 是哈希表的大小。
返回值 :返回存储在键中的哈希表中的所有字段值。
1 2 3 4 5 6 7 8 redis> HSET myhash field1 "Hello" (integer) 1 redis> HSET myhash field2 "World" (integer) 1 redis> HVALS myhash 1) "Hello" 2) "World" redis>
6.应用场景:购物车 以用户 id 为 key,商品 id 为 field,商品数量为 value,恰好构成了购物车的3个要素,如下图所示。
涉及到的相关命令:
添加商品:HSET cart:{userId} {productId} 1
添加数量:HINCRBY cart:{userId} {productId} 1
商品总数:HLEN cart:{userId}
删除商品:HDEL cart:{userId} {productId}
获取购物车所有商品:HGETALL cart:{userId}
当前仅仅是将商品ID存储到了Redis中,在回显商品显示信息时还需要回表查数据库,获取完整的商品信息。
List:列表命令 1.LPUSH命令 1 LPUSH key element [element ...]
1 2 3 4 5 6 7 8 redis> LPUSH mylist "world" (integer) 1 redis> LPUSH mylist "hello" (integer) 2 redis> LRANGE mylist 0 -1 1) "hello" 2) "world" redis>
2.LPOP命令
命令复杂度 :该命令的时间复杂度为 O(N),其中 N 是返回元素的数量。
作用 :移除并返回存储在键中的列表的第一个元素。默认情况下,该命令从列表开头弹出单个元素。当提供可选的 count
参数时,返回的结果将包含最多 count 个元素,取决于列表的长度。
1 2 3 4 5 6 7 8 9 10 11 redis> RPUSH mylist "one" "two" "three" "four" "five" (integer) 5 redis> LPOP mylist "one" redis> LPOP mylist 2 1) "two" 2) "three" redis> LRANGE mylist 0 -1 1) "four" 2) "five" redis>
3.LRANGE命令
命令复杂度 :该命令的时间复杂度为 O(S+N),其中 S 是 start 偏移量与头部的距离(针对小型列表)或 start 偏移量与最近的头尾的距离(针对大型列表,加快遍历速度),N 是范围内元素的数量。
返回值 :返回存储在键中的列表的指定元素。起始偏移量和停止偏移量是从零开始的索引,其中 0 表示列表的第一个元素(列表的头部),1 表示下一个元素,依此类推。这些偏移量也可以是负数,表示从列表末尾开始的偏移量。例如,-1 表示列表的最后一个元素,-2 表示倒数第二个元素,依此类推。
超出范围的索引不会产生错误。如果起始索引大于列表的末尾,则返回一个空列表。如果停止索引大于列表的实际末尾,Redis 将把它视为列表的最后一个元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 redis> RPUSH mylist "one" (integer) 1 redis> RPUSH mylist "two" (integer) 2 redis> RPUSH mylist "three" (integer) 3 redis> LRANGE mylist 0 0 1) "one" redis> LRANGE mylist -3 2 1) "one" 2) "two" 3) "three" redis> LRANGE mylist -100 100 1) "one" 2) "two" 3) "three" redis> LRANGE mylist 5 10 (empty array) redis>
4.LSET命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 redis> RPUSH mylist "one" (integer) 1 redis> RPUSH mylist "two" (integer) 2 redis> RPUSH mylist "three" (integer) 3 redis> LSET mylist 0 "four" "OK" redis> LSET mylist -2 "five" "OK" redis> LRANGE mylist 0 -1 1) "four" 2) "five" 3) "three" redis>
5.LREM命令
命令复杂度 :该命令的时间复杂度为 O(N+M),其中 N 是列表长度,M 是删除元素数量。
从存储在键中的列表中移除前 count
次出现的与指定元素相等的元素。count 参数影响操作的方式如下:
count > 0
:从头到尾
移除与元素相等的元素。
count < 0
:从尾到头
移除与元素相等的元素。
count = 0
:移除所有
与元素相等的元素。
注意,不存在的键被视为空列表,因此当键不存在时,该命令将始终返回 0。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 redis> RPUSH mylist "hello" (integer) 1 redis> RPUSH mylist "hello" (integer) 2 redis> RPUSH mylist "foo" (integer) 3 redis> RPUSH mylist "hello" (integer) 4 redis> LREM mylist -2 "hello" (integer) 2 redis> LRANGE mylist 0 -1 1) "hello" 2) "foo" redis>
6.LMPOP命令 1 LMPOP numkeys key [key ...] <LEFT | RIGHT> [COUNT count]
命令复杂度 :该命令的时间复杂度为 O(N+M),其中 N 是提供的key的个数,M 是返回元素的数量。
作用 :根据传递的参数,从第一个非空列表
的左侧或右侧弹出元素。返回的元素数量受到非空列表长度和 count 参数(默认为 1)中较小者的限制。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 redis> LMPOP 2 non1 non2 LEFT COUNT 10 (error) object of type 'NoneType' has no len() redis> LPUSH mylist "one" "two" "three" "four" "five" (integer) 5 redis> LMPOP 1 mylist LEFT 1) "mylist" 2) 1) "five" redis> LRANGE mylist 0 -1 1) "four" 2) "three" 3) "two" 4) "one" redis> LMPOP 1 mylist RIGHT COUNT 10 1) "mylist" 2) 1) "one" 2) "two" 3) "three" 4) "four" redis> LPUSH mylist "one" "two" "three" "four" "five" (integer) 5 redis> LPUSH mylist2 "a" "b" "c" "d" "e" (integer) 5 redis> LMPOP 2 mylist mylist2 right count 3 1) "mylist" 2) 1) "one" 2) "two" 3) "three" redis> LRANGE mylist 0 -1 1) "five" 2) "four" redis> LMPOP 2 mylist mylist2 right count 5 1) "mylist" 2) 1) "four" 2) "five" redis> LMPOP 2 mylist mylist2 right count 10 1) "mylist2" 2) 1) "a" 2) "b" 3) "c" 4) "d" 5) "e" redis> EXISTS mylist mylist2 (integer) 0 redis>
7.BLPOP命令 1 BLPOP key [key ...] timeout
命令复杂度 :该命令的时间复杂度为 O(N),其中 N 是提供的key的个数。
作用 :BLPOP 是一个阻塞列表弹出原语
。它是 LPOP 的阻塞版本,因为当给定列表中没有任何元素可弹出时,它会阻塞连接。从第一个非空列表的头部弹出一个元素,并按照给定的顺序检查给定的键。
8.LMOVE命令 1 LMOVE source destination <LEFT | RIGHT> <LEFT | RIGHT>
命令复杂度 :该命令的时间复杂度为 O(1)。
作用 :原子地返回并移除存储在源列表(source)中的第一个/最后一个元素(头部/尾部取决于 wherefrom
参数),并将该元素推送到存储在目标列表(destination)中的第一个/最后一个位置(头部/尾部取决于 whereto
参数)。例如:假设源列表(source)包含列表 a、b、c,目标列表(destination)包含列表 x、y、z。执行 LMOVE source destination RIGHT LEFT 将导致源列表包含 a、b,目标列表包含 c、x、y、z。
如果源列表不存在,则返回值为 nil,且不执行任何操作。如果源列表和目标列表相同,则操作相当于从列表中移除第一个/最后一个元素,并将其推送为列表的第一个/最后一个元素,因此可以将其视为列表旋转命令(或者如果 wherefrom 与 whereto 相同,则视为无操作)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 redis> RPUSH mylist "one" (integer) 1 redis> RPUSH mylist "two" (integer) 2 redis> RPUSH mylist "three" (integer) 3 redis> LMOVE mylist myotherlist RIGHT LEFT "three" redis> LMOVE mylist myotherlist LEFT RIGHT "one" redis> LRANGE mylist 0 -1 1) "two" redis> LRANGE myotherlist 0 -1 1) "three" 2) "one" redis>
9.应用场景:可靠队列
Redis通常被用作消息服务器来实现后台作业处理或其他类型的消息任务。一个简单的队列通常通过在生产者端将值推入列表中来获得,然后在消费者端使用RPOP(使用轮询)或BRPOP(如果客户端更适合使用阻塞操作)来等待这些值。然而,在这种情况下,获得的队列是不可靠的,因为消息可能会丢失
,例如在存在网络问题或者在消息被接收但仍需处理时消费者崩溃。
LMOVE(或其阻塞变体BLMOVE)提供了一种避免这个问题的方法:消费者获取消息的同时将其推送到一个处理列表中
,一旦消息已经被成功处理,可以使用LREM
命令从处理列表中删除消息。一个额外的客户端可以监视处理列表中停留时间过长的项目
,并在需要时将这些超时的项目再次推送回队列中。
Set:集合命令 1.SADD命令 1 SADD key member [member ...]
命令复杂度 :每次添加元素的时间复杂度为O(1),因此当命令同时使用多个参数调用时,添加N个元素的时间复杂度为O(N)。
作用 :将指定的成员添加到存储在键中的集合中。已经是该集合成员的指定成员将被忽略。如果键不存在,则在添加指定成员之前将创建一个新的集合。
1 2 3 4 5 6 7 8 9 10 redis> SADD myset "Hello" (integer) 1 redis> SADD myset "World" (integer) 1 redis> SADD myset "World" (integer) 0 redis> SMEMBERS myset 1) "Hello" 2) "World" redis>
2.SREM命令 1 SREM key member [member ...]
命令复杂度 :该命令的时间复杂度为 O(N),其中 N 是要移除的元素数量。
作用 ;该命令从存储在 key 中的集合中移除指定的成员。被指定移除的成员如果不是该集合的成员,则被忽略。如果 key 不存在,那么它会被视为空集合,并且该命令返回 0。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 redis> SADD myset "one" (integer) 1 redis> SADD myset "two" (integer) 1 redis> SADD myset "three" (integer) 1 redis> SREM myset "one" (integer) 1 redis> SREM myset "four" (integer) 0 redis> SMEMBERS myset 1) "two" 2) "three" redis>
3.SCARD命令
命令复杂度 :该命令的时间复杂度为 O(1)。
返回值 :返回存储在 key 对应的集合的元素数量。
1 2 3 4 5 6 7 redis> SADD myset "Hello" (integer) 1 redis> SADD myset "World" (integer) 1 redis> SCARD myset (integer) 2 redis>
4.SISMEMBER命令
命令复杂度 :该命令的时间复杂度为 O(1)。
返回值 :返回 member 是否是存储在 key 中的集合的成员。
1 2 3 4 5 6 7 redis> SADD myset "one" (integer) 1 redis> SISMEMBER myset "one" (integer) 1 redis> SISMEMBER myset "two" (integer) 0 redis>
5.SINTER命令
命令复杂度 :在最坏的情况下,时间复杂度为 O(N*M),其中 N 是最小集合的基数,而 M 是集合的数量。
返回值 :返回由所有给定集合的交集产生的集合的成员。
1 2 3 4 5 6 7 8 9 10 11 12 13 redis> SADD key1 "b" (integer) 1 redis> SADD key1 "c" (integer) 1 redis> SADD key2 "c" (integer) 1 redis> SADD key2 "d" (integer) 1 redis> SADD key2 "e" (integer) 1 redis> SINTER key1 key2 1) "c" redis>
6.SUNION命令
命令复杂度 :该命令的时间复杂度为 O(1),其中 N 是给定的所有集合的元素数量之和。
返回值 :返回由所有给定集合的并集产生的集合的成员。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 redis> SADD key1 "a" (integer) 1 redis> SADD key1 "b" (integer) 1 redis> SADD key1 "c" (integer) 1 redis> SADD key2 "c" (integer) 1 redis> SADD key2 "d" (integer) 1 redis> SADD key2 "e" (integer) 1 redis> SUNION key1 key2 1) "a" 2) "b" 3) "c" 4) "d" 5) "e" redis>
7.SDIFF命令
命令复杂度 :该命令的时间复杂度为 O(1),其中 N 是给定的所有集合的元素数量之和。
返回值 :返回第一个集合与所有后续集合之间差异的成员。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 redis> SADD key1 "a" (integer) 1 redis> SADD key1 "b" (integer) 1 redis> SADD key1 "c" (integer) 1 redis> SADD key2 "c" (integer) 1 redis> SADD key2 "d" (integer) 1 redis> SADD key2 "e" (integer) 1 redis> SDIFF key1 key2 1) "a" 2) "b" redis>
8.应用场景:抽奖活动 存储某活动中中奖的用户名 ,Set 类型因为有去重功能,可以保证同一个用户不会中奖两次。
key 为抽奖活动名,value 为员工名称,把所有员工名称放入抽奖箱:
1 SADD Tom Jerry John Sean Marry Lindy Sary Mark
如果允许重复中奖,可以使用 SRANDMEMBER
命令。
如果不允许重复中奖,可以使用 SPOP
命令。
Sorted Set:有序集合命令 1.ZADD命令 1 ZADD key [NX | XX] [GT | LT] [CH] [INCR] score member [score member ...]
命令复杂度 :每添加一个元素的时间复杂度为O(log(N)),其中N是有序集合中的元素数量。
作用 :该命令将所有指定的成员以及指定的分数添加到存储在键为key的有序集合中。可以指定多个分数/成员对。如果指定的成员已经是有序集合的成员,则更新其分数,并将元素重新插入到正确的位置以确保正确的排序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 redis> ZADD myzset 1 "one" (integer) 1 redis> ZADD myzset 1 "uno" (integer) 1 redis> ZADD myzset 2 "two" 3 "three" (integer) 2 redis> ZRANGE myzset 0 -1 WITHSCORES 1) "one" 2) "1" 3) "uno" 4) "1" 5) "two" 6) "2" 7) "three" 8) "3" redis>
2.ZREM命令 1 ZREM key member [member ...]
命令复杂度 :该命令的时间复杂度为O(M*log(N)),其中 N 是有序集合中元素的数量,M 是操作中被移除的元素数量。
作用 :该命令从存储在键为key的有序集合中移除指定的成员。不存在的成员将被忽略。当键存在但不持有有序集合时,会返回错误。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 redis> ZADD myzset 1 "one" (integer) 1 redis> ZADD myzset 2 "two" (integer) 1 redis> ZADD myzset 3 "three" (integer) 1 redis> ZREM myzset "two" (integer) 1 redis> ZRANGE myzset 0 -1 WITHSCORES 1) "one" 2) "1" 3) "three" 4) "3" redis>
3.ZSCORE命令
命令复杂度 :该命令的时间复杂度为O(1)。
作用 :返回键为key的有序集合中成员member的分数。
1 2 3 4 5 redis> ZADD myzset 1 "one" (integer) 1 redis> ZSCORE myzset "one" "1" redis>
4.ZRANK命令 1 ZRANK key member [WITHSCORE]
命令复杂度 :该命令的时间复杂度为O(log(N))。
作用 :该命令返回存储在键为key的有序集合中的成员的排名,其中分数从低到高排序。排名是从0开始的,这意味着具有最低分数的成员的排名为0。
5.ZCARD命令
命令复杂度 :该命令的时间复杂度为O(1)。
作用 :该命令返回存储在键为key的有序集合中的元素数量。
1 2 3 4 5 6 7 redis> ZADD myzset 1 "one" (integer) 1 redis> ZADD myzset 2 "two" (integer) 1 redis> ZCARD myzset (integer) 2 redis>
6.ZCOUNT命令
命令复杂度 :该命令的时间复杂度为O(log(N)),其中 N 是有序集合中元素的数量。
作用 :该命令返回键为key的有序集合中分数介于min和max之间的元素数量。
注意:该命令的复杂度仅为O(log(N)),因为它使用元素的排名(参见ZRANK)来获取范围的概念。因此,无需按范围大小进行工作。
1 2 3 4 5 6 7 8 9 10 11 redis> ZADD myzset 1 "one" (integer) 1 redis> ZADD myzset 2 "two" (integer) 1 redis> ZADD myzset 3 "three" (integer) 1 redis> ZCOUNT myzset -inf +inf (integer) 3 redis> ZCOUNT myzset (1 3 (integer) 2 redis>
7.ZINCRBY命令 1 ZINCRBY key increment member
命令复杂度 :该命令的时间复杂度为O(log(N)),其中 N 是有序集合中元素的数量。
作用 :将存储在键为key的有序集合中的成员的分数增加increment。如果成员不存在于有序集合中,则将其添加到有序集合中,并将increment作为其分数(就好像其先前的分数为0.0)。如果键不存在,则创建一个具有指定成员作为唯一成员的新有序集合。
1 2 3 4 5 6 7 8 9 10 11 12 redis> ZADD myzset 1 "one" (integer) 1 redis> ZADD myzset 2 "two" (integer) 1 redis> ZINCRBY myzset 2 "one" "3" redis> ZRANGE myzset 0 -1 WITHSCORES 1) "two" 2) "2" 3) "one" 4) "3" redis>
8.ZRANGE命令 1 ZRANGE key start stop [BYSCORE | BYLEX] [REV] [LIMIT offset count] [WITHSCORES]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 redis> ZADD myzset 1 "one" 2 "two" 3 "three" (integer) 3 redis> ZRANGE myzset 0 -1 1) "one" 2) "two" 3) "three" redis> ZRANGE myzset 2 3 1) "three" redis> ZRANGE myzset -2 -1 1) "two" 2) "three" redis> ZRANGE myzset 0 1 WITHSCORES 1) "one" 2) "1" 3) "two" 4) "2" redis> ZRANGE myzset (1 +inf BYSCORE LIMIT 1 1 1) "three" redis>
9.ZREMRANGEBYSCORE命令 1 ZREMRANGEBYSCORE key min max
1 2 3 4 5 6 7 8 9 10 11 12 13 14 redis> ZADD myzset 1 "one" (integer) 1 redis> ZADD myzset 2 "two" (integer) 1 redis> ZADD myzset 3 "three" (integer) 1 redis> ZREMRANGEBYSCORE myzset -inf (2 (integer) 1 redis> ZRANGE myzset 0 -1 WITHSCORES 1) "two" 2) "2" 3) "three" 4) "3" redis>
10.应用场景:排行榜 我们以博文点赞排名为例,小林发表了五篇博文,分别获得赞为 200、40、100、50、150。
文章 arcticle:4 新增一个赞,可以使用 ZINCRBY
命令(为有序集合key中元素member的分值加上increment):
查看某篇文章的赞数,可以使用 ZSCORE
命令(返回有序集合key中元素个数):
获取小林文章赞数最多的 3 篇文章,可以使用 ZREVRANGE
命令(倒序获取有序集合 key 从start下标到stop下标的元素):
获取小林 100 赞到 200 赞的文章,可以使用 ZRANGEBYSCORE
命令(返回有序集合中指定分数区间内的成员,分数由低到高排序):
Transactions:事务命令 Redis事务允许将一组命令在单个步骤中执行,它们围绕着MULTI
、EXEC
、DISCARD
和WATCH
命令展开。Redis事务提供了两个重要的保证:
所有事务中的命令都是串行化
的,按顺序执行。在Redis事务的执行过程中,不会为其他客户端发送的请求服务。这保证了命令作为单个隔离操作执行。
EXEC命令触发执行事务中的所有命令,因此如果在事务上下文中的客户端在调用EXEC命令之前失去与服务器的连接,则不会执行任何操作。相反,如果调用了EXEC命令,则会执行所有操作。在使用AOF时,Redis确保使用单个write(2)系统调用将事务写入磁盘。但是,如果Redis服务器崩溃或以某种硬性方式被系统管理员终止,则可能仅注册部分操作。Redis将在重新启动时检测到此情况,并显示错误退出。使用redis-check-aof
工具,可以修复追加模式文件,从而删除部分事务,以便服务器可以重新启动。
从版本2.2开始,Redis允许在以上两种保证的基础上提供额外的保证,以一种非常类似于检查并设置
(CAS)操作的乐观锁定方式。
在Redis中,通过使用MULTI命令可以进入事务。该命令始终会回复OK。在此时,用户可以发出多个命令。而不是立即执行这些命令,Redis会将它们排队。一旦调用EXEC命令,所有命令都将执行。如果调用DISCARD命令,将清空事务队列并退出事务。
1 2 3 4 5 6 7 8 9 > MULTI OK > INCR foo QUEUED > INCR bar QUEUED > EXEC 1) (integer) 1 2) (integer) 1
在执行EXEC之后发生的错误不会以特殊方式处理:即使在事务期间某个命令失败,所有其他命令仍将被执行
。
1 2 3 4 5 6 7 8 9 10 11 12 13 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. MULTI +OK SET a abc +QUEUED LPOP a +QUEUED EXEC *2 +OK -WRONGTYPE Operation against a key holding the wrong kind of value
WATCH用于在Redis事务中提供检查并设置(CAS)行为。被WATCH的键会被监视以侦测对它们的更改。如果在执行EXEC命令之前至少有一个被监视的键被修改,整个事务会中止,并且EXEC返回一个空回复来通知事务失败。
1 2 3 4 5 6 WATCH mykey val = GET mykey val = val + 1 MULTI SET mykey $val EXEC
WATCH命令实际上是一个使EXEC变得有条件的命令:我们要求Redis仅在没有任何被WATCH的键被修改时执行事务。这包括客户端进行的修改,如写入命令,以及Redis本身进行的修改,如过期或驱逐。如果在键被WATCH和EXEC接收到之间被修改,则整个事务将被中止。
事务中的命令不会触发WATCH条件,因为它们只是排队
,直到EXEC被发送。当调用EXEC
时,所有键都将取消监视,无论事务是否中止。当客户端连接关闭
时,所有键都将取消监视。
WATCH命令可以用来创建Redis原本不支持的新的原子操作的一个很好的例子是实现ZPOP,它是一个以原子方式从有序集合中弹出具有较低分数的元素。以下是最简单的实现方式:
1 2 3 4 5 WATCH zset element = ZRANGE zset 0 0 MULTI ZREM zset element EXEC