Redis 命令介绍
# 公用命令
可以删除任意数据结构的 key
del key
查看所有 key
keys *
根据给定的选项,对输入列表、集合或者有序集合进行排序,然后返回或者存储排序的结果。
sort source-key [by pattern] [limit offset count] [get pattern [get pattern ...]] [asc|desc] [alpha] [store dest-key]
查看数据库有多少个 key
dbsize
清除所有库的数据
flushall
清除当前库的所有数据
flushdb
查看 reids 内存信息等
info
监控所有客户发送的命令(redis 编译执行成功的命令)
monitor
# 处理时间
移除键的过期时间
persist key
查看给定键距离过期还有多少秒
ttl key
给定键在指定的秒数后过期
expire key seconds
将给定键的过期时间设置为给定的 unix 时间戳
expireat key timestamp
查看给定键距离过期时间还有多少毫秒,这个命令在 reids2.6 以上版本可用。
pttl key
让给定键在指定的毫秒数之后过期,这个命令在 redis2.6 以上版本可用。
pexpire key milliseconds
将一个毫秒级精度的 unix 时间戳设置为给定键的过期时间,这个命令在 redis2.6 以上版本可用。
pexpireat key timestamp-milliseconds
# 自增和自减
将键存储的值 + 1
incr key
将键存储的值 - 1
decr key
将键存储的值加上整数 amount
incrby key amount
将键存储的值减去整数 amount
decrby key amount
将键存储的值加上浮点数 amount,这个命令在 Redis2.6 以上版本可用
incrbyfloat key amount
# 字符串 String
可以是字符串(简单的字符串、复杂的字符串(例如 JSON、XML))、数字(整数、浮点数),甚至是二进制(图片、音频、视频),但是值最大不能超过 512MB
创建一个键值对 set key value
127.0.0.1:6379> set a 1234567890
OK
2
获取 key 存储的值 get key
127.0.0.1:6379> get a
"1234567890"
2
将值 value 追加到给定 key 当前存储的值的末尾,追加成功的发返回值为这个字符串的长度 (length) append key value
127.0.0.1:6379> append a a
(integer) 11
127.0.0.1:6379> get a
"1234567890a"
2
3
4
获取一个由偏移量 start 至 end 范围内的所有字符组成的字串,包括 start 和 end 在内。getrange key start end
127.0.0.1:6379> getrange a 0 3
"1234"
2
将从 start 偏移量开始的字串设置为给定值 setrange key offset value
127.0.0.1:6379> setrange a 3 bcde
(integer) 11
127.0.0.1:6379> get a
"123bcde890a"
2
3
4
# 列表 list
用来存储多个有序的字符串,列表中的每个字符串称为元素(element),一个列表最多可以存储 2^32 -1 个元素
将一个或多个值推入列表的右端 rpush key value [...]
127.0.0.1:6379> LRANGE b 0 -1
1) "5"
2) "6"
127.0.0.1:6379> RPUSH b 7 8
(integer) 4
127.0.0.1:6379> LRANGE b 0 -1
1) "5"
2) "6"
3) "7"
4) "8"
2
3
4
5
6
7
8
9
10
获取 list 元素数量 llen
127.0.0.1:6379[1]> llen 32021420001:90000300009999:10002:1601198414621
(integer) 2
2
lpush key value [...] -> 将一个或多个值推入列表的左端
127.0.0.1:6379> LPUSH b 1 2
(integer) 6
127.0.0.1:6379> LRANGE b 0 -1
1) "2"
2) "1"
3) "5"
4) "6"
5) "7"
6) "8"
2
3
4
5
6
7
8
9
rpop key -> 移除并返回列表最右端的元素
127.0.0.1:6379> rpop b
"8"
127.0.0.1:6379> LRANGE b 0 -1
1) "2"
2) "1"
3) "5"
4) "6"
5) "7"
2
3
4
5
6
7
8
lpop key -> 移除并返回列表最左端的元素
127.0.0.1:6379> lpop b
"2"
127.0.0.1:6379> LRANGE b 0 -1
1) "1"
2) "5"
3) "6"
4) "7"
2
3
4
5
6
7
lindex key offset -> 返回列表中偏移量为 offset 的元素 (下标从 0 开始)
127.0.0.1:6379> lindex b 3
"7"
2
lrange key start end -> 返回列表从 start 偏移量到 end 偏移量范围的所有元素。包含 start 和 end 本身。lrange key 0 -1 为查询所有
127.0.0.1:6379> LRANGE b 0 2
1) "1"
2) "5"
3) "6"
2
3
4
ltrim key start end -> 对列表进行修键,只保留从 start 至 end 偏移量的元素,包含 start 和 end。
127.0.0.1:6379> LTRIM b 1 2
OK
127.0.0.1:6379> LRANGE b 0 -1
1) "5"
2) "6"
2
3
4
5
blpop key [...] timeout -> 从第一个非空列表中弹出位于最左端的元素,或者在 timeout 秒之内阻塞并等待可弹出的元素出现 (一下测试没有元素所以 nil)
127.0.0.1:6379> BLPOP c 10
(nil)
(10.03s)
2
3
brpop key [...] timeout -> 从第一个非空列表中弹出位于最右端的元素,或者在 timeout 秒之内阻塞并等待可弹出的元素出现 (一下测试没有元素所以 nil)
127.0.0.1:6379> brpop c 10
(nil)
(10.07s)
2
3
rpoplpush source-key dest-key -> 从 source-key 列表中弹出位于最右端的元素,然后将这个元素推入 dest-key 列表的最左端,并向用户返回这个元素
brpoplpush source-key dest-key timeout -> 从 source-key 列表中弹出位于最右端的元素,然后将这个元素推入 dest-key 列表的最左端,并向用户返回这个元素;如果 source-key 为空,那么在 timeout 秒之内阻塞并等待可弹出的元素出现。
# 集合 set
用来保存多个的字符串元素,但和列表类型不一样的是,集合中不允许有重复元素,并且集合中的元素是无序的,不能通过索引下标获取元素
sadd key item[...] -> 将一个或多个元素添加到集合里面,并返回被添加元素当中原本并不存在于集合里面的元素数量。
srem key item[...] -> 从集合里面删除一个或多个元素,并返回被移除元素的数量。
sismember key item -> 检查元素item是否存在于集合key里面。
scard key -> 返回集合包含的元素数量。
smembers key -> 返回集合包含的所有元素。
srandmember key [count] -> 从集合里随机的返回一个或多个元素,当count 为正整数时,命令返回的随机元素不会重复;当count为负数时,命令返回的随机元素可能会出现重复。
spop key -> 随机的移除集合中的一个元素,并返回被移除的元素。
smove source-key dest-key item -> 如果集合source-key包含元素item,那么从集合source-key 里面移除y元素item,并将元素item添加到集合dest-key中;如果item成功移除,那么命令返回1,否则返回0;
sdiff key[...] -> 返回那些存在于第一个集合、但不存在于其他集合中的元素(数学上的差集运算)
sdiffstore dest-key key[...] -> 将那些存在于第一个集合但不存在于其他集合的元素(数学上的差集运算)存储到dest-key 键里面
sinter key[...] -> 返回那些同时存在于所有集合中的元素(数学上的交集运算)
sinter dest-key key[...] -> 那些同时存在于所有集合中的元素(数学上的交集运算)存储到dest-key键里面。
sunion key[...] -> 返回那些至少存在于一个集合中的元素(数学上讲的并集运算)
sunionstore dest-key key[...] -> 那些至少存在于一个集合中的元素(数学上讲的并集运算)存储到dest-key键里面。
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
# 散列 hash 哈希类型
hset key-name key value -> 创建一个散列并赋值
hget key-name key -> 返回指定散列键的值
hgetall key-name -> 获取散列包含的所有键值对
hmset key-name key value[key value ...] -> 为散列里面的一个或多个键设置值
hmget key-name key[...] -> 从散列里面获取一个或多个键的值
hlen key-name -> 返回散列包含的键值对数量
hdel key-name key[...] -> 删除散列里面的一个或多个键值对,返回成功找到并删除的键值对数量。
hexists key-name key -> 检查给定的键是否存在于散列中
hkeys key-name -> 获取散列包含的所有键
hvals key-name -> 获取散列包含的所有值
hincrby key-name key increment -> 将键key存储的值加上整数increment
hincrbyfloat key-name key increment -> 将键key存储的值加上浮点数increment
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 有序集合 zset
不能有重复的元素,而且还可以排序,它和列表使用索引下标作为排序依据不同的是,它给每个元素设置一个分数 (score) 作为排序的依据(默认升序)
zadd key score member [score member ...] -> 将带有给定分值的成员添加到有序集合里面
zrem key member[...] -> 从有序集合里面移除给定的成员,并返回被移除成员的数量
zcard key -> 返回有序集合包含的成员数量
zincrby key increment member -> 将member成员的分值加上increment
zcount key min max -> 返回分值介于min 和max 之间的成员数量
zrank key member -> 返回成员member在有序集合中的排名
zscore key member -> 返回成员member的分值
zrange key start stop [withscores] -> 返回有序集合中排名介于start 和 stop 之间的成员,如果给定了可选的 withscores 选项,那么会将成员的分值一并返回。zrange key 0 -1 查询所有成员
zrevrank key member -> 返回有序集合里成员member的排名,成员按照分值从大到小排列
zrevrange key start stop [withscores] -> 返回有序集合给定排名范围内的成员,按照分值从大到小排列
zrangebyscore key min max [withscores] [left offset count] -> 返回有序集合中,分值介于min和max之间的所有成员
zrevrangebyscore key max min [withscores] [left offset count] -> 获取有序集合中分值介于min和max之间的所有成员,并按照分值从大到小的顺序来返回他们。
zremrangebyrank key start top -> 移除有序集合中排名介于start 和 stop 之间的成员。
zremrangebyscore key min max -> 移除有序集合中分值介于min和max 之间的成员。
zinterstore dest-key key-count key[...] [weights weight[...] ] [aggregate sum|min|max] -> 对给定的有序集合执行类似于集合的交集运算
zunionstore dest-key key-count key[...] [weights weight[...] ] [aggregate sum|min|max] -> 对指定的有序集合执行类似于集合的并集运算
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
# 订阅 / 发布
subscribe channel[...] -> 订阅给定的一个或多个频道
unsubscribe channel[...] -> 退订给定的一个或多个频道,如果执行时没有给定任何频道,那么退订所有频道
publish channel message -> 向给定的频道发送消息
psubscribe pattern[...] -> 订阅与给定模式相匹配的所有频道
punsubscribe pattern[...] -> 退订给定的模式,如果执行时没有给定任何模式,那么退订所有模式。
2
3
4
5
6
7
8
9
10
# Redis5 之 Streams 数据类型
Redis 5.0 全新的数据类型:streams,官方把它定义为:以更抽象的方式建模日志的数据结构。Redis 的 streams 主要是一个 append only 的数据结构,至少在概念上它是一种在内存中表示的抽象数据类型,只不过它们实现了更强大的操作,以克服日志文件本身的限制。
如果你了解 MQ,那么可以把 streams 当做 MQ。如果你还了解 kafka,那么甚至可以把 streams 当做 kafka。
另外,这个功能有点类似于 redis 以前的 Pub/Sub,但是也有基本的不同:
streams 支持多个客户端(消费者)等待数据(Linux 环境开多个窗口执行 XREAD 即可模拟),并且每个客户端得到的是完全相同的数据。
Pub/Sub 是发送忘记的方式,并且不存储任何数据;而 streams 模式下,所有消息被无限期追加在 streams 中,除非用于显示执行删除(XDEL)。
streams 的 Consumer Groups 也是 Pub/Sub 无法实现的控制方式。
# streams 数据结构
streams 数据结构本身非常简单,但是 streams 依然是 Redis 到目前为止最复杂的类型,其原因是实现的一些额外的功能:一系列的阻塞操作允许消费者等待生产者加入到 streams 的新数据。另外还有一个称为 Consumer Groups (消费组) 的概念,这个概念最先由 kafka 提出,Redis 有一个类似实现,和 kafka 的 Consumer Groups 的目的是一样的:允许一组客户端协调消费相同的信息流!
# streams 基础
为了理解 streams 的目的,以及如何使用它,我们先忽略掉所有高级特性,只把注意力放在数据结构本身,以及那些操作和访问 streams 的命令。这基本上也是大多数其他 Redis 数据类型共有的部分,例如 Lists,Sets,Sorted Sets 等。然而需要注意的是,Lists 也有一个更复杂的阻塞式的 API,例如 BLPOP,BRPOP 等。streams 这方便的 API 也没什么不同,只是更复杂,更强大(更牛逼,哈)!
# streams 命令
废话不多说,先上手玩玩这个全新的数据类型。streams 这个数据类型对应有如下 13 个操作命令,所有命令都以 "X" 开头:
XADD
用法:XADD key ID field string [field string …]
正如其名,这个命令就是用来添加的,给 streams 追加(append,前面提到过:streams 主要是一个 append only 的数据结构)一个新的 entry(和 Java 里的 Map 类似,Redis 里的 streams 中的数据也称为 entry)。
key:的含义就是同一类型 streams 的名称;
ID: streams 中 entry 的唯一标识符,如果执行 XADD 命令时,传入星号(*),那么,ID 会自动生成,且自动生成的 ID 会在执行 XADD 后返回,默认生成的 ID 格式为 millisecondsTime+sequenceNumber,即当前毫秒级别的时间戳加上一个自增序号值,例如 "1540013735401-0"。并且执行 XADD 时,不接受少于或等于上一次执行 XADD 的 ID,否则会报错:ERR The ID specified in XADD is equal or smaller than the target stream top item;
field&string:接下来就是若干组 field string。可以把它理解为表示属性的 json 中的 key-value。例如,某一 streams 的 key 命名为 userInfo,且某个用户信息为 {"username":"afei", "password":"123456"},那么执行 XADD 命令如下:
127.0.0.1:6379> xadd userInfo * name afei password 123456
"1594456377383-0"
127.0.0.1:6379>
2
3
由于命令中 ID 字段的值是 * ,所以自定生成 ID,1594456377383-0 就是自动生成的 ID。 XADD 命令也支持显示指定 ID,例如:XADD key 0-2 field string。
需要注意的是,ID 的时间戳部分是部署 Redis 服务器的本地时间,如果发生时钟回拨会怎么样?如果发生时钟回拨,生成的 ID 的时间戳部分就是回拨后的时间,然后加上这个时间的递增序列号。例如当前时间戳 1540014082060,然后这时候发生了时钟回拨,且回拨 5ms,那么时间戳就是 1540014082055。假设以前已经生成了 1540014082055-0,1540014082055-1,那么这次由于时钟回拨,生成的 ID 就是 1540014082055-2。所以允许自动生成的 ID 在发生时钟回拨时少于上次的 ID,但是不允许显示指定一个少于上次的 ID。
如果我们以相同的 key 插入一遍,他不会像普通的 key-value 一样做替换,而是在相同 key 维护这一个列表。
xdel
- 用法:XDEL key ID [ID …]
和 XADD 相反,这是命令用来从 streams 中删除若干个 entry,并且会返回实际删除数,这个删除数可能和参数 ID 个数不等,因为某些 ID 表示的消息可能不存在。执行命令如下,第二个参数 ID 是不存在的,所以 XDEL 的返回结果是 1:
127.0.0.1:6379> xdel userInfo 1594456377383-0
(integer) 1
2
xlen
- 用法:XLEN key
很好理解,这个命令就是用来返回相同 key 的数量,上面又说相同 key 是不会覆盖的,是维护了一个列表,所以这个是相同 key 列表的 size。执行如下:
127.0.0.1:6379> xadd user * name zhangsan
"1594457206541-0"
127.0.0.1:6379> xlen user
(integer) 1
127.0.0.1:6379> xadd user * name zhangsan sex 0
"1594457274424-0"
127.0.0.1:6379> xlen user
(integer) 2
127.0.0.1:6379> xadd user * name zhangsan sex 0 password 123
"1594457287981-0"
127.0.0.1:6379> xlen user
(integer) 3
127.0.0.1:6379> xdel user 1594457287981-0
(integer) 1
127.0.0.1:6379> xlen user
(integer) 2
127.0.0.1:6379>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# streams 三种查询模式
redis 提供了三种查询 streams 数据的模式:
范围查询:因为 streams 的每个 entry,其默认生成的 ID 是基于时间且递增的;
监听模式:类比 linux 中的 tailf 命令,实时接收新增加到 streams 中的 entry(也有点像一个消息系统,事实上笔者认为它就是借鉴了 kafka);
消费者组:即 Consumer Groups,特殊的监听模式。从一个消费者的角度来看 streams,一个 streams 能被分区到多个处理消息的消费者,对于任意一条消息,同一个消费者组中只有一个消费者可以处理(和 kafka 的消费者组完全一样)。这样还能够横向扩容消费者,从而提升处理消息的能力,而不需要只让把让一个消费者处理所有消息。
xrange
- 用法:XRANGE key start end [COUNT count]
这个命令属于第 1 种模式,即基于范围查询。这个命令用来返回 streams 某个顺序范围下的元素,start 参数是更小的 ID,end 参数是更大的 ID。有两个特殊的 ID 用符号 "-" 和 "+" 表示,符号 "-" 表示最小的 ID,符号 "+" 表示最大的 ID:
127.0.0.1:6379> XRANGE user 1540014096298-0 1594457274424-0
1) 1) "1594457206541-0"
2) 1) "name"
2) "zhangsan"
2) 1) "1594457274424-0"
2) 1) "name"
2) "zhangsan"
3) "sex"
4) "0"
2
3
4
5
6
7
8
9
127.0.0.1:6379> xrange user - +
1) 1) "1594457206541-0"
2) 1) "name"
2) "zhangsan"
2) 1) "1594457274424-0"
2) 1) "name"
2) "zhangsan"
3) "sex"
4) "0"
3) 1) "1594458356220-0"
2) 1) "name"
2) "wu"
2
3
4
5
6
7
8
9
10
11
12
XRANGE 还能实现遍历某个范围区间的功能,例如我想遍历 2018-10-20 号新增的用户信息。首先得到 2018-10-20 00:00:00 对应的时间戳为 1539964800000,再得到 2018-10-20 23:59:59 对应的时间戳为 1540051199000,然后执行如下命令:
127.0.0.1:6379> xrange user 1594457206541-0 1594458356220-0 count 1
1) 1) "1594457206541-0"
2) 1) "name"
2) "zhangsan"
127.0.0.1:6379> xrange user 1594457206541-0 1594458356220-0 count 2
1) 1) "1594457206541-0"
2) 1) "name"
2) "zhangsan"
2) 1) "1594457274424-0"
2) 1) "name"
2) "zhangsan"
3) "sex"
4) "0"
2
3
4
5
6
7
8
9
10
11
12
13
xrevrange
- 用法:XREVRANGE key end start [COUNT count]
这个命令也属于第 1 种模式,且和 XRANGE 相反,返回一个逆序范围。end 参数是更大的 ID,start 参数是更小的 ID
xread
- 用法:XREAD [COUNT count] [BLOCK milliseconds] STREAMS key [key …] ID [ID …]
很明显,这个命令就是用来实现第 2 个模式,即监听模式。其作用是返回 streams 中从来没有读取的,且比参数 ID 更大的元素。
这里我开了两个窗口测试,且第一个没有做新增,第二个做了新增.
127.0.0.1:6379> XREAD COUNT 10 BLOCK 60000 STREAMS user 1594458356220-0
(nil)
(60.02s)
2
3
4
5
6
127.0.0.1:6379> XREAD COUNT 10 BLOCK 60000 STREAMS user 1594458356220-0
1) 1) "user"
2) 1) 1) "1594458985980-0"
2) 1) "name"
2) "ceshi"
(13.37s)
127.0.0.1:6379>
2
3
4
5
6
7
使用 xread 会阻塞特定时间,等待比我 ID 大的数据,如果使用最小 ID 进行测试,会跟 xrange user - + 效果是一样的。
注意:BLOCK 为 0 表示一致等待知道有新的数据,否则永远不会超时。并且 ID 的值我们用特殊字符 $
表示,这个特殊字符表示我们只获取最新添加的消息。
127.0.0.1:6379> xread count 10 block 0 streams user $
2
3
xread 还支持同时监听多个 streams
127.0.0.1:6379> XREAD BLOCK 0 STREAMS user_01 user_02 user_03 user_04 $ $ $ $
2
3
4
XREAD 除了 COUNT 和 BLOCK,没有其他选项了。所有 XREAD 是一个非常基本的命令。更多高级特性可以往下看接下来要介绍的 XREADGROUP。
XREADGROUP
- 用法:XREADGROUP GROUP group consumer [COUNT count] [BLOCK milliseconds] STREAMS key [key …] ID [ID …]
很明显,这就是第三种模式:消费者组模式。 - 如果你了解 kafka 的消费者组,那么你就也了解了 streams 的消费者组。如果不了解也没关系,笔者简单解释一下,假设有三个消费者 C1,C2,C3。在 streams 中总计有 7 条消息:1, 2, 3, 4, 5, 6, 7,那么消费关系如下所示:
1 -> C1
2 -> C2
3 -> C3
4 -> C1
5 -> C2
6 -> C3
7 -> C1 - 消费者组具备如下几个特点:
同一个消息不会被投递到一个消费者组下的多个消费者,只可能是一个消费者。
同一个消费者组下,每个消费者都是唯一的,通过大小写敏感的名字区分。
消费者组中的消费者请求的消息,一定是新的,从来没有投递过的消息。
消费一个消息后,需要用命令(XACK)确认,意思是说:这条消息已经给成功处理。正因为如此,当访问 streams 的历史消息时,每个消费者只能看到投递给它自己的消息。
XACK
- 用法:XACK key group ID [ID …]
- 这是消费者组相关的另一个重要的命令。标记一个处理中的消息为已被正确处理,如此一来,这条消息就会被从消费者组的 pending 消息集合中删除,类似 MQ 中的 ack。
XGROUP
- 用法:xgroup create key groupname id
- 这也是消费者组的一个重要命令,这个命令用来管理消费者组,例如创建,删除等。
XREADGROUP,XACK,XGROUP 三种命令构成了消费者组相关的操作命令。
目前 XGROUP CREATE 的 streams 必须是一个存在的 streams,否则会报错。
创建一个消费组
127.0.0.1:6379> XGROUP CREATE user GRP-AFEI $
OK
2