Author: yanpenggong Email: yanpenggong@163.com
Github: kungs8 CSDN: https://blog.csdn.net/yanpenggong
[toc]
1. Linux 安装 Redis 并配置
1.1 下载,执行编译并安装
下载地址:http://redis.io/download,下载最新稳定版本。
本教程使用的最新文档版本为 6.2.6,下载并安装:
1 | [root@localhost ~]# cd /opt/software/ |
注意:
如果没有wget,则会报错,通过使用
yum install wget
就行。
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 [root@localhost Redis_dir]# wget http://download.redis.io//releases/redis-6.2.6.tar.gz
-bash: wget: 未找到命令
[root@localhost Redis_dir]# yum install wget
已加载插件:fastestmirror
Loading mirror speeds from cached hostfile
* base: mirror.lzu.edu.cn
* extras: mirror.lzu.edu.cn
* updates: mirrors.aliyun.com
正在解决依赖关系
正在检查事务
软件包 wget.x86_64.0.1.14-18.el7_6.1 将被 安装
解决依赖关系完成
依赖关系解决
=======================================================================================================================
Package 架构 版本 源 大小
============================================================================```=====================================
正在安装:
wget x86_64 1.14-18.el7_6.1 base 547 k
事务概要
=======================================================================================================================
安装 1 软件包
总下载量:547 k
安装大小:2.0 M
Is this ok [y/d/N]: y
Downloading packages:
wget-1.14-18.el7_6.1.x86_64.rpm | 547 kB 00:00:00
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
正在安装 : wget-1.14-18.el7_6.1.x86_64 1/1
验证中 : wget-1.14-18.el7_6.1.x86_64 1/1
已安装:
wget.x86_64 0:1.14-18.el7_6.1
完毕!
[root@localhost Redis_dir]#系统缺少gcc环境的报错(安装Redis执行make命令时遇到此错误)
问题:
1
2
3
4
5
6
7
8
9
10
11 make[3]: cc:命令未找到
make[3]: *** [alloc.o] 错误 127
make[3]: 离开目录"/opt/software/redis-6.2.6/deps/hiredis"
make[2]: *** [hiredis] 错误 2
make[2]: 离开目录"/opt/software/redis-6.2.6/deps"
make[1]: [persist-settings] 错误 2 (忽略)
CC adlist.o
/bin/sh: cc: 未找到命令
make[1]: *** [adlist.o] 错误 127
make[1]: 离开目录"/opt/software/redis-6.2.6/src"
make: *** [all] 错误 2解决办法:
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91 [root@localhost redis-6.2.6]# yum install gcc c++
已加载插件:fastestmirror
Loading mirror speeds from cached hostfile
* base: mirror.lzu.edu.cn
* extras: mirror.lzu.edu.cn
* updates: mirrors.aliyun.com
没有可用软件包 c++。
正在解决依赖关系
正在检查事务
软件包 gcc.x86_64.0.4.8.5-44.el7 将被 安装
正在处理依赖关系 cpp = 4.8.5-44.el7,它被软件包 gcc-4.8.5-44.el7.x86_64 需要
正在处理依赖关系 glibc-devel >= 2.2.90-12,它被软件包 gcc-4.8.5-44.el7.x86_64 需要
正在处理依赖关系 libmpfr.so.4()(64bit),它被软件包 gcc-4.8.5-44.el7.x86_64 需要
正在处理依赖关系 libmpc.so.3()(64bit),它被软件包 gcc-4.8.5-44.el7.x86_64 需要
正在检查事务
软件包 cpp.x86_64.0.4.8.5-44.el7 将被 安装
软件包 glibc-devel.x86_64.0.2.17-325.el7_9 将被 安装
正在处理依赖关系 glibc-headers = 2.17-325.el7_9,它被软件包 glibc-devel-2.17-325.el7_9.x86_64 需要
正在处理依赖关系 glibc-headers,它被软件包 glibc-devel-2.17-325.el7_9.x86_64 需要
软件包 libmpc.x86_64.0.1.0.1-3.el7 将被 安装
软件包 mpfr.x86_64.0.3.1.1-4.el7 将被 安装
正在检查事务
软件包 glibc-headers.x86_64.0.2.17-325.el7_9 将被 安装
正在处理依赖关系 kernel-headers >= 2.2.1,它被软件包 glibc-headers-2.17-325.el7_9.x86_64 需要
正在处理依赖关系 kernel-headers,它被软件包 glibc-headers-2.17-325.el7_9.x86_64 需要
正在检查事务
软件包 kernel-headers.x86_64.0.3.10.0-1160.62.1.el7 将被 安装
解决依赖关系完成
依赖关系解决
=======================================================================================================================
Package 架构 版本 源 大小
=======================================================================================================================
正在安装:
gcc x86_64 4.8.5-44.el7 base 16 M
为依赖而安装:
cpp x86_64 4.8.5-44.el7 base 5.9 M
glibc-devel x86_64 2.17-325.el7_9 updates 1.1 M
glibc-headers x86_64 2.17-325.el7_9 updates 691 k
kernel-headers x86_64 3.10.0-1160.62.1.el7 updates 9.1 M
libmpc x86_64 1.0.1-3.el7 base 51 k
mpfr x86_64 3.1.1-4.el7 base 203 k
事务概要
=======================================================================================================================
安装 1 软件包 (+6 依赖软件包)
总下载量:33 M
安装大小:60 M
Is this ok [y/d/N]: r
Is this ok [y/d/N]: y
Downloading packages:
(1/7): glibc-headers-2.17-325.el7_9.x86_64.rpm | 691 kB 00:00:00
(2/7): glibc-devel-2.17-325.el7_9.x86_64.rpm | 1.1 MB 00:00:00
(3/7): cpp-4.8.5-44.el7.x86_64.rpm | 5.9 MB 00:00:01
(4/7): libmpc-1.0.1-3.el7.x86_64.rpm | 51 kB 00:00:00
(5/7): mpfr-3.1.1-4.el7.x86_64.rpm | 203 kB 00:00:00
(6/7): kernel-headers-3.10.0-1160.62.1.el7.x86_64.rpm | 9.1 MB 00:00:01
(7/7): gcc-4.8.5-44.el7.x86_64.rpm | 16 MB 00:00:02
-----------------------------------------------------------------------------------------------------------------------
总计 11 MB/s | 33 MB 00:00:02
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
正在安装 : mpfr-3.1.1-4.el7.x86_64 1/7
正在安装 : libmpc-1.0.1-3.el7.x86_64 2/7
正在安装 : cpp-4.8.5-44.el7.x86_64 3/7
正在安装 : kernel-headers-3.10.0-1160.62.1.el7.x86_64 4/7
正在安装 : glibc-headers-2.17-325.el7_9.x86_64 5/7
正在安装 : glibc-devel-2.17-325.el7_9.x86_64 6/7
正在安装 : gcc-4.8.5-44.el7.x86_64 7/7
验证中 : kernel-headers-3.10.0-1160.62.1.el7.x86_64 1/7
验证中 : mpfr-3.1.1-4.el7.x86_64 2/7
验证中 : glibc-devel-2.17-325.el7_9.x86_64 3/7
验证中 : gcc-4.8.5-44.el7.x86_64 4/7
验证中 : glibc-headers-2.17-325.el7_9.x86_64 5/7
验证中 : libmpc-1.0.1-3.el7.x86_64 6/7
验证中 : cpp-4.8.5-44.el7.x86_64 7/7
已安装:
gcc.x86_64 0:4.8.5-44.el7
作为依赖被安装:
cpp.x86_64 0:4.8.5-44.el7 glibc-devel.x86_64 0:2.17-325.el7_9
glibc-headers.x86_64 0:2.17-325.el7_9 kernel-headers.x86_64 0:3.10.0-1160.62.1.el7
libmpc.x86_64 0:1.0.1-3.el7 mpfr.x86_64 0:3.1.1-4.el7
完毕!
[root@localhost redis-6.2.6]#安装好gcc 和c++ 后,必须清空后再编译,否则会报如下错误
问题:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 [root@localhost redis-6.2.6]# make
cd src && make all
make[1]: 进入目录"/opt/software/redis-6.2.6/src"
CC Makefile.dep
make[1]: 离开目录"/opt/software/redis-6.2.6/src"
make[1]: 进入目录"/opt/software/redis-6.2.6/src"
CC adlist.o
In file included from adlist.c:34:0:
zmalloc.h:50:31: 致命错误:jemalloc/jemalloc.h:没有那个文件或目录
include <jemalloc/jemalloc.h>
^
编译中断。
make[1]: *** [adlist.o] 错误 1
make[1]: 离开目录"/opt/software/redis-6.2.6/src"
make: *** [all] 错误 2
[root@localhost redis-6.2.6]#解决办法:
1
2 [root@localhost redis-6.2.6]# make distclean # 清空上次编译失败残留文件
[root@localhost redis-6.2.6]# make && make install # 执行编译及安装
执行完 make 命令后,redis-6.2.6 目录下会出现编译后的 redis 服务程序 redis-server
,还有用于测试的客户端程序 redis-cli
,两个程序位于安装目录 src 目录下。
1.2 启动Redis服务
下面启动 redis 服务:
1 | [root@localhost src]# cd src/ |
redis.conf
是一个默认的配置文件。我们可以根据需要使用自己的配置文件。
启动 redis 服务进程后,就可以使用测试客户端程序( redis-cli
)和 redis 服务交互了。 比如:
1 | [root@localhost ~]# cd /opt/software/redis-6.2.6/src |
1.3 Redis 配置后台服务和访问密码
配置 Redis 为后台服务 将配置文件中的 daemonize no 改成 daemonize yes,配置 redis 为后台启动。
Redis 设置访问密码 在配置文件中找到 requirepass,去掉前面的注释,并修改后面的密码。
常用配置文件例子 redis.conf 如下:
1 | 默认端口6379 |
修改protected-mode
参数,将其改为 protected-mode no
。这样就可以解除redis的保护机制,可以被其他主机连接。
同时还要把对应的端口打开:
1 | [root@localhost src]# firewall-cmd --query-port=6379/tcp # 检测端口是否打开 |
查看防火墙所有开放的端口
1 firewall-cmd --zone=public --list-ports关闭端口
1 firewall-cmd --zone=public --remove-port=6379/tcp --permanent关闭防火墙
如果要开放的端口太多,嫌麻烦,可以关闭防火墙,安全性自行评估
1 systemctl stop firewalld.service查看防火墙状态
1
2 [root@localhost src]# firewall-cmd --state
running查看监听的端口
1
2
3
4
5
6
7
8
9 [root@localhost src]# netstat -lnpt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 7293/./redis-server
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1062/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1237/master
tcp6 0 0 ::1:6379 :::* LISTEN 7293/./redis-server
tcp6 0 0 :::22 :::* LISTEN 1062/sshd
tcp6 0 0 ::1:25 :::* LISTEN 1237/masterlinux命令报错信息:-bash: netstat: 未找到命令
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 [root@localhost src]# netstat -lnpt
-bash: netstat: 未找到命令
[root@localhost src]# yum -y install net-tools
已加载插件:fastestmirror
Loading mirror speeds from cached hostfile
* base: mirror.lzu.edu.cn
* extras: mirror.lzu.edu.cn
* updates: mirrors.aliyun.com
正在解决依赖关系
正在检查事务
软件包 net-tools.x86_64.0.2.0-0.25.20131004git.el7 将被 安装
解决依赖关系完成
依赖关系解决
=======================================================================================================================
Package 架构 版本 源 大小
=======================================================================================================================
正在安装:
net-tools x86_64 2.0-0.25.20131004git.el7 base 306 k
事务概要
=======================================================================================================================
安装 1 软件包
总下载量:306 k
安装大小:917 k
Downloading packages:
net-tools-2.0-0.25.20131004git.el7.x86_64.rpm | 306 kB 00:00:00
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
正在安装 : net-tools-2.0-0.25.20131004git.el7.x86_64 1/1
验证中 : net-tools-2.0-0.25.20131004git.el7.x86_64 1/1
已安装:
net-tools.x86_64 0:2.0-0.25.20131004git.el7
完毕!
[root@localhost src]#检查端口被哪个进程占用
1
2
3
4 [root@localhost src]# netstat -lnpt |grep 6379
tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 7293/./redis-server
tcp6 0 0 ::1:6379 :::* LISTEN 7293/./redis-server
[root@localhost src]#查看进程的详细信息
1
2
3
4
5
6
7 [root@localhost src]# ps -ef | grep redis
root 7293 1 0 14:23 ? 00:00:07 ./redis-server 127.0.0.1:6379
root 7379 1390 0 14:41 pts/0 00:00:00 grep --color=auto redis
[root@localhost src]# ps 7293
PID TTY STAT TIME COMMAND
7293 ? Ssl 0:07 ./redis-server 127.0.0.1:6379
[root@localhost src]#终止进程
1 kill -9 7293
2. Redis 配置
2.1 获取Redis 配置
在 Redis 中,Redis 的根目录中有一个配置文件(redis.conf)。您可以通过 Redis CONFIG
命令获取和设置所有 Redis 配置。
语法
以下是 Redis CONFIG 命令的基本语法。
1
127.0.0.1:6379> CONFIG GET CONFIG_SETTING_NAME
实例1:
CONFIG GET loglevel
1
2
3
4127.0.0.1:6379> CONFIG GET "loglevel"
1) "loglevel"
2) "notice"
127.0.0.1:6379>实例2:
CONFIG GET *
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298127.0.0.1:6379> CONFIG GET *
1) "rdbchecksum"
2) "yes"
3) "daemonize"
4) "yes"
5) "io-threads-do-reads"
6) "no"
7) "lua-replicate-commands"
8) "yes"
9) "always-show-logo"
10) "no"
11) "protected-mode"
12) "no"
13) "rdbcompression"
14) "yes"
15) "rdb-del-sync-files"
16) "no"
17) "activerehashing"
18) "yes"
19) "stop-writes-on-bgsave-error"
20) "yes"
21) "set-proc-title"
22) "yes"
23) "dynamic-hz"
24) "yes"
25) "lazyfree-lazy-eviction"
26) "no"
27) "lazyfree-lazy-expire"
28) "no"
29) "lazyfree-lazy-server-del"
30) "no"
31) "lazyfree-lazy-user-del"
32) "no"
33) "lazyfree-lazy-user-flush"
34) "no"
35) "repl-disable-tcp-nodelay"
36) "no"
37) "repl-diskless-sync"
38) "no"
39) "gopher-enabled"
40) "no"
41) "aof-rewrite-incremental-fsync"
42) "yes"
43) "no-appendfsync-on-rewrite"
44) "no"
45) "cluster-require-full-coverage"
46) "yes"
47) "rdb-save-incremental-fsync"
48) "yes"
49) "aof-load-truncated"
50) "yes"
51) "aof-use-rdb-preamble"
52) "yes"
53) "cluster-replica-no-failover"
54) "no"
55) "cluster-slave-no-failover"
56) "no"
57) "replica-lazy-flush"
58) "no"
59) "slave-lazy-flush"
60) "no"
61) "replica-serve-stale-data"
62) "yes"
63) "slave-serve-stale-data"
64) "yes"
65) "replica-read-only"
66) "yes"
67) "slave-read-only"
68) "yes"
69) "replica-ignore-maxmemory"
70) "yes"
71) "slave-ignore-maxmemory"
72) "yes"
73) "jemalloc-bg-thread"
74) "yes"
75) "activedefrag"
76) "no"
77) "syslog-enabled"
78) "no"
79) "cluster-enabled"
80) "no"
81) "appendonly"
82) "no"
83) "cluster-allow-reads-when-down"
84) "no"
85) "crash-log-enabled"
86) "yes"
87) "crash-memcheck-enabled"
88) "yes"
89) "use-exit-on-panic"
90) "no"
91) "disable-thp"
92) "yes"
93) "cluster-allow-replica-migration"
94) "yes"
95) "replica-announced"
96) "yes"
97) "aclfile"
98) ""
99) "unixsocket"
100) ""
101) "pidfile"
102) "/var/run/redis_6379.pid"
103) "replica-announce-ip"
104) ""
105) "slave-announce-ip"
106) ""
107) "masteruser"
108) ""
109) "cluster-announce-ip"
110) ""
111) "syslog-ident"
112) "redis"
113) "dbfilename"
114) "dump.rdb"
115) "appendfilename"
116) "appendonly.aof"
117) "server_cpulist"
118) ""
119) "bio_cpulist"
120) ""
121) "aof_rewrite_cpulist"
122) ""
123) "bgsave_cpulist"
124) ""
125) "ignore-warnings"
126) ""
127) "proc-title-template"
128) "{title} {listen-addr} {server-mode}"
129) "masterauth"
130) ""
131) "requirepass"
132) "yanpenggong"
133) "supervised"
134) "no"
135) "syslog-facility"
136) "local0"
137) "repl-diskless-load"
138) "disabled"
139) "loglevel"
140) "notice"
141) "maxmemory-policy"
142) "noeviction"
143) "appendfsync"
144) "everysec"
145) "oom-score-adj"
146) "no"
147) "acl-pubsub-default"
148) "allchannels"
149) "sanitize-dump-payload"
150) "no"
151) "databases"
152) "16"
153) "port"
154) "6379"
155) "io-threads"
156) "1"
157) "auto-aof-rewrite-percentage"
158) "100"
159) "cluster-replica-validity-factor"
160) "10"
161) "cluster-slave-validity-factor"
162) "10"
163) "list-max-ziplist-size"
164) "-2"
165) "tcp-keepalive"
166) "300"
167) "cluster-migration-barrier"
168) "1"
169) "active-defrag-cycle-min"
170) "1"
171) "active-defrag-cycle-max"
172) "25"
173) "active-defrag-threshold-lower"
174) "10"
175) "active-defrag-threshold-upper"
176) "100"
177) "lfu-log-factor"
178) "10"
179) "lfu-decay-time"
180) "1"
181) "replica-priority"
182) "100"
183) "slave-priority"
184) "100"
185) "repl-diskless-sync-delay"
186) "5"
187) "maxmemory-samples"
188) "5"
189) "maxmemory-eviction-tenacity"
190) "10"
191) "timeout"
192) "300"
193) "replica-announce-port"
194) "0"
195) "slave-announce-port"
196) "0"
197) "tcp-backlog"
198) "511"
199) "cluster-announce-bus-port"
200) "0"
201) "cluster-announce-port"
202) "0"
203) "cluster-announce-tls-port"
204) "0"
205) "repl-timeout"
206) "60"
207) "repl-ping-replica-period"
208) "10"
209) "repl-ping-slave-period"
210) "10"
211) "list-compress-depth"
212) "0"
213) "rdb-key-save-delay"
214) "0"
215) "key-load-delay"
216) "0"
217) "active-expire-effort"
218) "1"
219) "hz"
220) "10"
221) "min-replicas-to-write"
222) "0"
223) "min-slaves-to-write"
224) "0"
225) "min-replicas-max-lag"
226) "10"
227) "min-slaves-max-lag"
228) "10"
229) "maxclients"
230) "10000"
231) "active-defrag-max-scan-fields"
232) "1000"
233) "slowlog-max-len"
234) "128"
235) "acllog-max-len"
236) "128"
237) "lua-time-limit"
238) "5000"
239) "cluster-node-timeout"
240) "15000"
241) "slowlog-log-slower-than"
242) "10000"
243) "latency-monitor-threshold"
244) "0"
245) "proto-max-bulk-len"
246) "536870912"
247) "stream-node-max-entries"
248) "100"
249) "repl-backlog-size"
250) "1048576"
251) "maxmemory"
252) "0"
253) "hash-max-ziplist-entries"
254) "512"
255) "set-max-intset-entries"
256) "512"
257) "zset-max-ziplist-entries"
258) "128"
259) "active-defrag-ignore-bytes"
260) "104857600"
261) "hash-max-ziplist-value"
262) "64"
263) "stream-node-max-bytes"
264) "4096"
265) "zset-max-ziplist-value"
266) "64"
267) "hll-sparse-max-bytes"
268) "3000"
269) "tracking-table-max-keys"
270) "1000000"
271) "client-query-buffer-limit"
272) "1073741824"
273) "repl-backlog-ttl"
274) "3600"
275) "auto-aof-rewrite-min-size"
276) "67108864"
277) "logfile"
278) ""
279) "watchdog-period"
280) "0"
281) "dir"
282) "/opt/software/redis-6.2.6"
283) "save"
284) "900 1 300 10 60 10000"
285) "client-output-buffer-limit"
286) "normal 0 0 0 slave 268435456 67108864 60 pubsub 33554432 8388608 60"
287) "unixsocketperm"
288) "0"
289) "slaveof"
290) ""
291) "notify-keyspace-events"
292) ""
293) "bind"
294) "0.0.0.0"
295) "oom-score-adj-values"
296) "0 200 800"
127.0.0.1:6379>
2.2 编辑配置
要更新配置,可以直接编辑 redis.conf 文件,也可以通过 CONFIG set 命令更新配置。
语法
1
127.0.0.1:6379> CONFIG SET CONFIG_SETTING_NAME NEW_CONFIG_VALUE
实例
1
2
3
4
5
6127.0.0.1:6379> CONFIG SET loglevel "notice"
OK
127.0.0.1:6379> CONFIG GET loglevel
1) "loglevel"
2) "notice"
127.0.0.1:6379>常用配置参数说明
redis.conf 配置项说明如下:
| 序号 | 配置项 | 说明 |
| —— | —————————————————————————————— | —————————————————————————————— |
| 1 |daemonize no
| Redis 默认不是以守护进程的方式运行,可以通过该配置项修改,使用 yes 启用守护进程(Windows 不支持守护线程的配置为 no ) |
| 2 |pidfile /var/run/redis.pid
| 当 Redis 以守护进程方式运行时,Redis 默认会把 pid 写入 /var/run/redis.pid 文件,可以通过 pidfile 指定 |
| 3 |port 6379
| 指定 Redis 监听端口,默认端口为 6379,作者在自己的一篇博文中解释了为什么选用 6379 作为默认端口,因为 6379 在手机按键上 MERZ 对应的号码,而 MERZ 取自意大利歌女 Alessia Merz 的名字 |
| 4 |bind 127.0.0.1
| 绑定的主机地址 |
| 5 |timeout 300
| 当客户端闲置多长秒后关闭连接,如果指定为 0 ,表示关闭该功能 |
| 6 |loglevel notice
| 指定日志记录级别,Redis 总共支持四个级别:debug、verbose、notice、warning,默认为 notice |
| 7 |logfile stdout
| 日志记录方式,默认为标准输出,如果配置 Redis 为守护进程方式运行,而这里又配置为日志记录方式为标准输出,则日志将会发送给 /dev/null |
| 8 |databases 16
| 设置数据库的数量,默认数据库为0,可以使用SELECT 命令在连接上指定数据库id |
| 9 |save <seconds> <changes>
Redis 默认配置文件中提供了三个条件:
-save 900 1
: 900 秒(15 分钟)内有 1 个更改
-save 300 10
: 300 秒(5 分钟)内有 10 个更改
-save 60 10000
: 60 秒内有 10000 个更改 | 指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合 |
| 10 |rdbcompression yes
| 指定存储至本地数据库时是否压缩数据,默认为 yes,Redis 采用 LZF 压缩,如果为了节省 CPU 时间,可以关闭该选项,但会导致数据库文件变的巨大 |
| 11 |dbfilename dump.rdb
| 指定本地数据库文件名,默认值为 dump.rdb |
| 12 |dir ./
| 指定本地数据库存放目录 |
| 13 |slaveof <masterip> <masterport>
| 设置当本机为 slave 服务时,设置 master 服务的 IP 地址及端口,在 Redis 启动时,它会自动从 master 进行数据同步 |
| 14 |masterauth <master-password>
| 当 master 服务设置了密码保护时,slave 服务连接 master 的密码 |
| 15 |requirepass foobared
| 设置 Redis 连接密码,如果配置了连接密码,客户端在连接 Redis 时需要通过AUTH <password>
命令提供密码,默认关闭 |
| 16 |maxclients 128
| 设置同一时间最大客户端连接数,默认无限制,Redis 可以同时打开的客户端连接数为 Redis 进程可以打开的最大文件描述符数,如果设置 maxclients 0,表示不作限制。当客户端连接数到达限制时,Redis 会关闭新的连接并向客户端返回 max number of clients reached 错误信息 |
| 17 |maxmemory <bytes>
| 指定 Redis 最大内存限制,Redis 在启动时会把数据加载到内存中,达到最大内存后,Redis 会先尝试清除已到期或即将到期的 Key,当此方法处理 后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。Redis 新的 vm 机制,会把 Key 存放内存,Value 会存放在 swap 区 |
| 18 |appendonly no
| 指定是否在每次更新操作后进行日志记录,
Redis 在默认情况下是异步的把数据写入磁盘,如果不开启,可能会在断电时导致一段时间内的数据丢失。
因为 redis 本身同步数据文件是按上面 save 条件来同步的,所以有的数据会在一段时间内只存在于内存中。默认为 no |
| 19 |appendfilename appendonly.aof
| 指定更新日志文件名,默认为 appendonly.aof |
| 20 |appendfsync everysec
| 指定更新日志条件,共有 3 个可选值:
- no:表示等操作系统进行数据缓存同步到磁盘(快)
- always:表示每次更新操作后手动调用 fsync() 将数据写到磁盘(慢,安全)
- everysec:表示每秒同步一次(折中,默认值) |
| 21 |vm-enabled no
| 指定是否启用虚拟内存机制,默认值为 no,
简单的介绍一下,VM 机制将数据分页存放,由 Redis 将访问量较少的页即冷数据 swap 到磁盘上,访问多的页面由磁盘自动换出到内存中(在后面的内容会仔细分析 Redis 的 VM 机制) |
| 22 |vm-swap-file /tmp/redis.swap
| 虚拟内存文件路径,默认值为 /tmp/redis.swap,不可多个 Redis 实例共享 |
| 23 |vm-max-memory 0
| 将所有大于 vm-max-memory 的数据存入虚拟内存,无论 vm-max-memory 设置多小,所有索引数据都是内存存储的(Redis 的索引数据 就是 keys),
也就是说,当 vm-max-memory 设置为 0 的时候,其实是所有 value 都存在于磁盘。默认值为 0 |
| 24 |vm-page-size 32
| Redis swap 文件分成了很多的 page,一个对象可以保存在多个 page 上面,但一个 page 上不能被多个对象共享,
vm-page-size 是要根据存储的 数据大小来设定的,
建议如果存储很多小对象,page 大小最好设置为 32 或者 64bytes;
如果存储很大大对象,则可以使用更大的 page,如果不确定,就使用默认值 |
| 25 |vm-pages 134217728
| 设置 swap 文件中的 page 数量,由于页表(一种表示页面空闲或使用的 bitmap)是在放在内存中的,,在磁盘上每 8 个 pages 将消耗 1byte 的内存。 |
| 26 |vm-max-threads 4
| 设置访问swap文件的线程数,最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的,可能会造成比较长时间的延迟。默认值为4 |
| 27 |glueoutputbuf yes
| 设置在向客户端应答时,是否把较小的包合并为一个包发送,默认为开启 |
| 28 |hash-max-zipmap-entries 64
hash-max-zipmap-value 512
| 指定在超过一定的数量或者最大的元素超过某一临界值时,采用一种特殊的哈希算法 |
| 29 |activerehashing yes
| 指定是否激活重置哈希,默认为开启(后面在介绍 Redis 的哈希算法时具体介绍) |
| 30 |include /path/to/local.conf
| 指定包含其它的配置文件,可以在同一主机上多个Redis实例之间使用同一份配置文件,而同时各个实例又拥有自己的特定配置文件 |
3. Redis数据类型
Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合), 位图(Bitmaps), 基数统计(HyperLogLogs)。
各个数据类型应用场景:
类型 | 简介 | 特性 | 场景 |
---|---|---|---|
String(字符串) | 二进制安全 | 可以包含任何数据,比如jpg图片或者序列化的对象,一个键最大能存储512M | —- |
Hash(字典) | 键值对集合,即编程语言中的Map类型 | 适合存储对象,并且可以像数据库中update一个属性一样只修改某一项属性值(Memcached中需要取出整个字符串反序列化成对象修改完再序列化存回去) | 存储、读取、修改用户属性 |
List(列表) | 链表(双向链表) | 增删快,提供了操作某一段元素的API | 1,最新消息排行等功能(比如朋友圈的时间线) 2,消息队列 |
Set(集合) | 哈希表实现,元素不重复 | 1、添加、删除,查找的复杂度都是O(1) 2、为集合提供了求交集、并集、差集等操作 | 1、共同好友 2、利用唯一性,统计访问网站的所有独立ip 3、好友推荐时,根据tag求交集,大于某个阈值就可以推荐 |
Sorted Set(有序集合) | 将Set中的元素增加一个权重参数score,元素按score有序排列 | 数据插入集合时,已经进行天然排序 | 1、排行榜 2、带权重的消息队列 |
3.1 string(字符串)
string 是 redis 最基本的类型,你可以理解成与 Memcached 一模一样的类型,一个 key 对应一个 value。
string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据。比如jpg图片或者序列化的对象。
string 类型是 Redis 最基本的数据类型,string 类型的值最大能存储 512MB。
可以在Redis中使用字符串做一些有趣的事情,例如,您可以:
- 使用INCR系列中的命令将字符串用作原子计数器:INCR、DECR、INCRBY。
- 使用 APPEND 命令附加到字符串。
- 使用字符串作为 <a href=”#GETRANGE 和 SETRANGE 的随机访问向量。
- 在小空间中编码大量数据,或使用 GETBIT 和 SETBIT 创建Redis支持的Bloom过滤器。
检查所有 可用的字符串命令 以获取更多信息,或阅读==Redis数据类型的简介==。
实例:
1 | 127.0.0.1:6379> SET kungs "yanpenggong" |
在以上实例中,使用了 Redis 的 SET 和 GET 命令。键为 kungs
,对应的值为 yanpenggong
。
注意:一个键最大能存储 512MB。
3.2 hash(哈希)
Redis hash 是一个键值(key=>value)对集合。
Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。
实例:
DEL kungs 用于删除前面测试用过的 key,不然会报错:(error) WRONGTYPE Operation against a key holding the wrong kind of value
1 | 127.0.0.1:6379> SET kungs "yanpenggong" |
实例中我们使用了 Redis HMSET, HGET 命令,HMSET 设置了两个 field=>value 对, HGET 获取对应 field 对应的 value。
每个 hash 可以存储 232 -1 键值对(40多亿)。
3.3 list(列表)
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。
1 | 127.0.0.1:6379> DEL kungs |
列表最多可存储 $2^{32} - 1$ 元素 (4294967295, 每个列表可存储40多亿)。
3.4 set(集合)
Redis 的 Set 是 string 类型的无序集合。
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。
sadd 命令
添加一个 string 元素到 key 对应的 set 集合中,成功返回 1,如果元素已经在集合中返回 0。
1
sadd key member
实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15127.0.0.1:6379> DEL kungs
(integer) 1
127.0.0.1:6379> sadd kungs redis
(integer) 1
127.0.0.1:6379> sadd kungs mongodb
(integer) 1
127.0.0.1:6379> sadd kungs rabbitmq
(integer) 1
127.0.0.1:6379> sadd kungs rabbitmq
(integer) 0
127.0.0.1:6379> smembers kungs
1) "rabbitmq"
2) "mongodb"
3) "redis"
127.0.0.1:6379>注意:以上实例中 rabbitmq 添加了两次,但根据集合内元素的唯一性,第二次插入的元素将被忽略。
集合中最大的成员数为 $2^{32} - 1$ (4294967295, 每个集合可存储40多亿个成员)。
3.5 zset(sorted set:有序集合)。
Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
zset的成员是唯一的,但分数(score)却可以重复。
zadd 命令
添加元素到集合,元素在集合中存在则更新对应score
1
zadd key score member
实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17127.0.0.1:6379> DEL kungs
Error: Server closed the connection
127.0.0.1:6379> DEL kungs
(integer) 1
127.0.0.1:6379> zadd kungs 0 redis
(integer) 1
127.0.0.1:6379> zadd kungs 0 mongodb
(integer) 1
127.0.0.1:6379> zadd kungs 0 rabbitmq
(integer) 1
127.0.0.1:6379> zadd kungs 0 rabbitmq
(integer) 0
127.0.0.1:6379> zrangebyscore kungs 0 1000
1) "mongodb"
2) "rabbitmq"
3) "redis"
127.0.0.1:6379>
3.6 位图(Bitmaps)
Redis Bitmap 通过类似 map 结构存放 0 或 1 ( bit 位 ) 作为值。
Redis Bitmap 可以用来统计状态,如日活
是否浏览过某个东西。
Redis setbit 命令
1
SETBIT key offset value
实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17127.0.0.1:6379> DEL kungs
(integer) 1
127.0.0.1:6379> setbit kungs:001 10001 1
(integer) 0
127.0.0.1:6379> setbit kungs:001 10002 2
(error) ERR bit is not an integer or out of range
127.0.0.1:6379> setbit kungs:001 10002 0
(integer) 0
127.0.0.1:6379> setbit kungs:001 10003 1
(integer) 0
127.0.0.1:6379> getbit kungs:001 10001
(integer) 1
127.0.0.1:6379> getbit kungs:001 10002
(integer) 0
127.0.0.1:6379> getbit kungs:001 10003
(integer) 1
127.0.0.1:6379>
3.7 基数统计(HyperLogLogs)
Redis HyperLogLog 可以接受多个元素作为输入,并给出输入元素的基数估算值
- 基数
集合中不同元素的数量,比如 {‘apple’, ‘banana’, ‘cherry’, ‘banana’, ‘apple’} 的基数就是 3
- 估算值
算法给出的基数并不是精确的,可能会比实际稍微多一些或者稍微少一些,但会控制在合 理的范围之内
HyperLogLog 的优点是:即使输入元素的数量或者体积非常非常大,计算基数所需的空间总是固定的、并且是很小的。
在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 264个不同元素的基数。
这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。
因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。
Redis PFADD命令
Redis PFADD 命令将元素添加至 HyperLogLog
1
PFADD key element [element ...]
实例
1
2
3
4
5
6
7
8
9127.0.0.1:6379> PFADD unique::ip::counter "192.168.0.1"
(integer) 1
127.0.0.1:6379> PFADD unique::ip::counter "127.0.0.1"
(integer) 1
127.0.0.1:6379> PFADD unique::ip::counter "255.255.255.255"
(integer) 1
127.0.0.1:6379> PFCOUNT unique::ip::counter
(integer) 3
127.0.0.1:6379>
3.8 数据库的数据注意事项
注意:Redis支持多个数据库,并且每个数据库的数据是隔离的不能共享,并且基于单机才有,如果是集群就没有数据库的概念。
Redis是一个字典结构的存储服务器,而实际上一个Redis实例提供了多个用来存储数据的字典,客户端可以指定将数据存储在哪个字典中。这与我们熟知的在一个关系数据库实例中可以创建多个数据库类似,所以可以将其中的每个字典都理解成一个独立的数据库。
每个数据库对外都是一个从0开始的递增数字命名,Redis默认支持16个数据库(可以通过配置文件支持更多,无上限),可以通过配置databases来修改这一数字。客户端与Redis建立连接后会自动选择0号数据库,不过可以随时使用SELECT命令更换数据库,如要选择1号数据库:
1 | 127.0.0.1:6379> set kungs1 "Hello" |
然而这些以数字命名的数据库又与我们理解的数据库有所区别。
- 首先Redis不支持自定义数据库的名字,每个数据库都以编号命名,开发者必须自己记录哪些数据库存储了哪些数据。
- 另外Redis也不支持为每个数据库设置不同的访问密码,所以一个客户端要么可以访问全部数据库,要么连一个数据库也没有权限访问。
- 最重要的一点是多个数据库之间并不是完全隔离的,比如
FLUSHALL
命令可以清空一个Redis实例中所有数据库中的数据。
综上所述,这些数据库更像是一种命名空间,而不适宜存储不同应用程序的数据。
比如可以使用0号数据库存储某个应用生产环境中的数据,使用1号数据库存储测试环境中的数据,但不适宜使用0号数据库存储A应用的数据而使用1号数据库B应用的数据,不同的应用应该使用不同的Redis实例存储数据。
由于Redis非常轻量级,一个空Redis实例占用的内存只有1M左右,所以不用担心多个Redis实例会额外占用很多内存。
4. Redis 命令
4.0 Redis 命令
4.0.1 本地执行命令
Redis 命令用于在 redis 服务上执行操作。
要在 redis 服务上执行命令需要一个 redis 客户端。Redis 客户端在我们之前下载的的 redis 的安装包中。
语法
1
[root@00-0C-29-38-42-90 redis-6.2.6]# ./src/redis-cli -a yanpenggong
实例
以下实例讲解了如何启动 redis 客户端:
启动 redis 服务器,打开终端并输入命令 redis-cli,该命令会连接本地的 redis 服务。
1
2
3
4
5[root@00-0C-29-38-42-90 redis-6.2.6]# ./src/redis-cli -a yanpenggong
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> ping
PONG
127.0.0.1:6379>在以上实例中我们连接到本地的 redis 服务并执行 PING 命令,该命令用于检测 redis 服务是否启动。
4.0.2 在远程服务上执行命令
如果需要在远程 redis 服务上执行命令,同样我们使用的也是 redis-cli 命令。
语法
1
[root@00-0C-29-38-42-90 redis-6.2.6]# ./src/redis-cli -h host -p port -a password
实例
以下实例演示了如何连接到主机为
127.0.0.1
,端口为6379
,密码为yanpengong
的 redis 服务上。1
2
3
4
5[root@00-0C-29-38-42-90 redis-6.2.6]# ./src/redis-cli -h 127.0.0.1 -p 6379 -a "yanpenggong"
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> ping
PONG
127.0.0.1:6379>
4.0.3 中文乱码解决办法
有时候会有中文乱码。要在 redis-cli
后面加上 --raw
1 | [root@00-0C-29-38-42-90 redis-6.2.6]# ./src/redis-cli -a yanpenggong --raw |
4.1 Redis 键(Keys)
Redis 键命令用于管理 redis 的键。
4.1.1 基本操作
语法
1
127.0.0.1:6379> COMMAND KEY_NAME
实例
实例中 DEL 是一个命令, kungs 是一个键。 如果键被删除成功,命令执行后输出 1,否则将输出 0
1
2
3
4
5
6
7
8
9127.0.0.1:6379> SET kungs redis
OK
127.0.0.1:6379> get kungs
redis
127.0.0.1:6379> DEL kungs
1
127.0.0.1:6379> DEL kungs
0
127.0.0.1:6379>
4.1.2 keys 基本命令汇总
序号 | 命令 | 描述 |
---|---|---|
1 | DEL key |
用于在 key 存在时删除 key |
2 | DUMP key |
序列化给定 key ,并返回被序列化的值 |
3 | EXISTS key |
检查给定 key 是否存在 |
4 | EXPIRE key seconds |
为给定 key 设置过期时间,以秒计 |
5 | EXPIREAT key timestamp |
EXPIREAT 的作用和 EXPIRE 类似,都用于为 key 设置过期时间。 不同在于 EXPIREAT 命令接受的时间参数是 UNIX 时间戳(unix timestamp) |
6 | PEXPIRE key milliseconds |
设置 key 的过期时间以毫秒计 |
7 | PEXPIREAT key milliseconds-timestamp |
设置 key 过期时间的时间戳(unix timestamp) 以毫秒计 |
8 | KEYS pattern |
查找所有符合给定模式( pattern)的 key |
9 | MOVE key db |
将当前数据库的 key 移动到给定的数据库 db 当中 |
10 | PERSIST key |
移除 key 的过期时间,key 将持久保持 |
11 | PTTL key |
以毫秒为单位返回 key 的剩余的过期时间 |
12 | TTL key |
以秒为单位,返回给定 key 的剩余生存时间(TTL, time to live) |
13 | RANDOMKEY |
从当前数据库中随机返回一个 key |
14 | RENAME key newkey |
修改 key 的名称 |
15 | RENAMENX key newkey |
仅当 newkey 不存在时,将 key 改名为 newkey |
16 | SCAN cursor [MATCH pattern] [COUNT count] |
迭代数据库中的数据库键 |
17 | TYPE key |
返回 key 所储存的值的类型 |
4.2 String(字符串)
Redis 字符串命令用于管理 Redis 中的字符串值。
4.2.1 基本操作
语法:
1
127.0.0.1:6379> COMMAND KEY_NAME
实例:
1
2
3
4
5127.0.0.1:6379> SET kungs yanpenggong
OK
127.0.0.1:6379> GET kungs
"yanpenggong"
127.0.0.1:6379>这里,SET 和 GET 是命令,”kungs” 是键。
4.2.2 String 基本命令汇总
序号 | 命令 | 描述 |
---|---|---|
1 | SET |
设置指定 key 的值 |
2 | GET |
获取指定 key 的值 |
3 | GETRANGE |
返回 key 中字符串值的子字符 |
4 | GETSET |
将给定 key 的值设为 value ,并返回 key 的旧值 ( old value ) |
5 | GETBIT |
对 key 所储存的字符串值,获取指定偏移量上的位 ( bit ) |
6 | MGET |
获取所有(一个或多个)给定 key 的值 |
7 | SETBIT |
对 key 所储存的字符串值,设置或清除指定偏移量上的位(bit) |
8 | SETEX |
设置 key 的值为 value 同时将过期时间设为 seconds |
9 | SETNX |
只有在 key 不存在时设置 key 的值 |
10 | SETRANGE |
从偏移量 offset 开始用 value 覆写给定 key 所储存的字符串值 |
11 | STRLEN |
返回 key 所储存的字符串值的长度 |
12 | MSET |
同时设置一个或多个 key-value 对 |
13 | MSETNX |
同时设置一个或多个 key-value 对 |
14 | PSETEX |
以毫秒为单位设置 key 的生存时间 |
15 | INCR |
将 key 中储存的数字值增一 |
16 | INCRBY |
将 key 所储存的值加上给定的增量值 ( increment ) |
17 | INCRBYFLOAT |
将 key 所储存的值加上给定的浮点增量值 ( increment ) |
18 | DECR |
将 key 中储存的数字值减一 |
19 | DECRBY |
将 key 所储存的值减去给定的减量值 ( decrement ) |
20 | APPEND |
将 value 追加到 key 原来的值的末尾 |
4.3 Hashes(哈希)
Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。
Redis 中每个 hash 可以存储 $2^{32} - 1$ 键值对(40多亿)。
4.3.1 基本操作
实例:
在例子中,rediscomcn
是 Redis 哈希,它包含详细信息(name,url,rank,visitors)属性。
1 | 127.0.0.1:6379> HMSET rediscomcn name "yanpenggong" url "https://blog.csdn.net/yanpenggong" rank 1 visitors 2888 |
4.3.2 Hashes 基本命令汇总
序号 | 命令 | 描述 |
---|---|---|
1 | HDEL |
删除一个或多个哈希表字段 |
2 | HEXISTS |
查看哈希表 key 中,指定的字段是否存在 |
3 | HGET |
获取存储在哈希表中指定字段的值 |
4 | HGETALL |
获取在哈希表中指定 key 的所有字段和值 |
5 | HINCRBY |
为哈希表 key 中的指定字段的整数值加上增量 increment |
6 | HINCRBYFLOAT |
为哈希表 key 中的指定字段的浮点数值加上增量 increment |
7 | HKEYS |
获取所有哈希表中的字段 |
8 | HLEN |
获取哈希表中字段的数量 |
9 | HMGET |
获取所有给定字段的值 |
10 | HMSET |
同时将多个 field-value (域-值)对设置到哈希表 key 中 |
11 | HSET |
将哈希表 key 中的字段 field 的值设为 value |
12 | HSETNX |
只有在字段 field 不存在时,设置哈希表字段的值 |
13 | HVALS |
获取哈希表中所有值 |
14 | HSCAN |
迭代哈希表中的键值对 |
15 | HSTRLEN |
返回哈希表 key 中, 与给定域 field 相关联的值的字符串长度 |
4.4 List(列表)
Redis 列表是按插入顺序排序的字符串列表。可以在列表的头部(左边)或尾部(右边)添加元素。
列表可以包含超过 40 亿 个元素 ( $2^{32} - 1$ )。
4.4.1 基本操作
用 LPUSH 命令将三个值插入了名为 language 的列表当中:
1 | 127.0.0.1:6379> LPUSH dbs sql |
4.4.2 List 基本命令汇总
序号 | 命令 | 描述 |
---|---|---|
1 | BLPOP |
移出并获取列表的第一个元素 |
2 | BRPOP |
移出并获取列表的最后一个元素 |
3 | BRPOPLPUSH |
从列表中弹出一个值,并将该值插入到另外一个列表中并返回它 |
4 | LINDEX |
通过索引获取列表中的元素 |
5 | LINSERT |
在列表的元素前或者后插入元素 |
6 | LLEN |
获取列表长度 |
7 | LPOP |
移出并获取列表的第一个元素 |
8 | LPUSH |
将一个或多个值插入到列表头部 |
9 | LPUSHX |
将一个值插入到已存在的列表头部 |
10 | LRANGE |
获取列表指定范围内的元素 |
11 | LREM |
移除列表元素 |
12 | LSET |
通过索引设置列表元素的值 |
13 | LTRIM |
对一个列表进行修剪(trim) |
14 | RPOP |
移除并获取列表最后一个元素 |
15 | RPOPLPUSH |
移除列表的最后一个元素,并将该元素添加到另一个列表并返回 |
16 | RPUSH |
在列表中添加一个或多个值 |
17 | RPUSHX |
为已存在的列表添加值 |
4.5 Set(集合)
Redis 的 Set 是 string 类型的无序集合。
集合成员是唯一的,这就意味着集合中没有重复的数据。
在 Redis 中,添加、删除和查找的时间复杂都是 O(1)(不管 Set 中包含多少元素)。
集合中最大的成员数为 $2^{32} – 1$ (4294967295), 每个集合可存储 40 多亿个成员。
4.5.1 基本操作
通过 SADD 命令向名为 rediscomcn 的集合插入的三个元素:
1 | 127.0.0.1:6379> SADD rediscomcn db2 |
在上面的示例中,我们使用 SADD 命令在集合中添加了 4 个元素。但是,使用 SMEMBERS 命令只检索了 3 个元素,因为有一个元素是重复的,Redis 只集合只含唯一元素。
4.5.2 基本命令汇总
序号 | 命令 | 描述 |
---|---|---|
1 | SADD |
向集合添加一个或多个成员 |
2 | SCARD |
获取集合的成员数 |
3 | SDIFF |
返回给定所有集合的差集 |
4 | SDIFFSTORE |
返回给定所有集合的差集并存储在 destination 中 |
5 | SINTER |
返回给定所有集合的交集 |
6 | SINTERSTORE |
返回给定所有集合的交集并存储在 destination 中 |
7 | SISMEMBER |
判断 member 元素是否是集合 key 的成员 |
8 | SMEMBERS |
返回集合中的所有成员 |
9 | SMOVE |
将 member 元素从 source 集合移动到 destination 集合 |
10 | SPOP |
移除并返回集合中的一个随机元素 |
11 | SRANDMEMBER |
返回集合中一个或多个随机数 |
12 | SREM |
移除集合中一个或多个成员 |
13 | SUNION |
返回所有给定集合的并集 |
14 | SUNIONSTORE |
所有给定集合的并集存储在 destination 集合中 |
15 | SSCAN |
迭代集合中的元素 |
4.6 Sorted Sets(有序集合)
Redis 有序集合和集合一样也是 string 类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个 double 类型的分数。Redis 正是通过分数来为集合中的成员进行从小到大的排序。
有序集合的成员是唯一的,但分数 ( score ) 却可以重复。
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。
集合中最大的成员数为 $2^{32} – 1$ ( 4294967295 ) , 每个集合可存储 40 多亿个成员。
4.6.1 基本操作
通过 ZADD 命令向 Redis 的有序集合中添加了三个值并关联分数:
1 | 127.0.0.1:6379> ZADD rediscomcn 1 redis |
4.6.2 基本命令汇总
序号 | 命令 | 描述 |
---|---|---|
1 | ZADD |
向有序集合添加一个或多个成员,或者更新已存在成员的分数 |
2 | ZCARD |
获取有序集合的成员数 |
3 | ZCOUNT |
计算在有序集合中指定区间分数的成员数 |
4 | ZINCRBY |
有序集合中对指定成员的分数加上增量 increment |
5 | ZINTERSTORE |
计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 key 中 |
6 | ZLEXCOUNT |
在有序集合中计算指定字典区间内成员数量 |
7 | ZRANGE |
通过索引区间返回有序集合成指定区间内的成员 |
8 | ZRANGEBYLEX |
通过字典区间返回有序集合的成员 |
9 | ZRANGEBYSCORE |
通过分数返回有序集合指定区间内的成员 |
10 | ZRANK |
返回有序集合中指定成员的索引 |
11 | ZREM |
移除有序集合中的一个或多个成员 |
12 | ZREMRANGEBYLEX |
移除有序集合中给定的字典区间的所有成员 |
13 | ZREMRANGEBYRANK |
移除有序集合中给定的排名区间的所有成员 |
14 | ZREMRANGEBYSCORE |
移除有序集合中给定的分数区间的所有成员 |
15 | ZREVRANGE |
返回有序集中指定区间内的成员,通过索引,分数从高到底 |
16 | ZREVRANGEBYSCORE |
返回有序集中指定分数区间内的成员,分数从高到低排序 |
17 | ZREVRANK |
返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序 |
18 | ZSCORE |
返回有序集中,成员的分数值 |
19 | ZUNIONSTORE |
计算一个或多个有序集的并集,并存储在新的 key 中 |
20 | ZSCAN |
迭代有序集合中的元素(包括元素成员和元素分值) |
4.7 Pub/Sub(发布订阅)
Redis 发布/订阅是一种消息传模式,其中发送者(在Redis术语中称为发布者)发送消息,而接收者(订阅者)接收消息。传递消息的通道称为channel。
在Redis中,客户端可以订阅任意数量的频道。
下图展示了频道 channel1 , 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1 之间的关系:
1 | graph BT; |
当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端:
1 | graph TB; |
4.7.1 基本操作
以下实例演示了发布订阅是如何工作的,需要开启两个 redis-cli 客户端。
在我们实例中我们创建了订阅频道名为 rediscomcnChat:
第一个 redis-cli 客户端
1
2
3
4
5
6127.0.0.1:6379> SUBSCRIBE rediscomcnChat
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "rediscomcnChat"
3) (integer) 1现在,我们先重新开启个 redis 客户端(第二个redis-cli 客户端),然后在同一个频道 rediscomcnChat 发布两次消息,订阅者就能接收到消息。
第二个 redis-cli 客户端
1
2
3
4
5127.0.0.1:6379> PUBLISH rediscomcnChat "Redis PUBLISH test"
(integer) 1
127.0.0.1:6379> PUBLISH rediscomcnChat "Learn redis with python"
(integer) 1
127.0.0.1:6379>
第一个redis-cli 客户端的最新接受信息
1
2
3
4
5
6
7
8
9
10
11
12127.0.0.1:6379> SUBSCRIBE rediscomcnChat
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "rediscomcnChat"
3) (integer) 1
1) "message"
2) "rediscomcnChat"
3) "Redis PUBLISH test"
1) "message"
2) "rediscomcnChat"
3) "Learn redis with python"
4.7.2 基本命令汇总
序号 | 命令 | 描述 |
---|---|---|
1 | PSUBSCRIBE |
订阅一个或多个符合给定模式的频道。 |
2 | PUBSUB |
查看订阅与发布系统状态。 |
3 | PUBLISH |
将信息发送到指定的频道。 |
4 | PUNSUBSCRIBE |
退订所有给定模式的频道。 |
5 | SUBSCRIBE |
订阅给定的一个或多个频道的信息。 |
6 | UNSUBSCRIBE |
指退订给定的频道。 |
4.8 Transaction(事务)
事务是指一个完整的动作,要么全部执行,要么什么也没有做。
Redis 事务不是严格意义上的事务,只是用于帮助用户在一个步骤中执行多个命令。单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的。
Redis 事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做。
Redis 事务可以一次执行多个命令, 并且带有以下三个重要的保证:
- 批量操作在发送 EXEC 命令前被放入队列缓存。
- 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。
- 在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。
一个事务从开始到执行会经历以下三个阶段:
- 开始事务。
- 命令入队。
- 执行事务。
MULTI、EXEC、DISCARD、WATCH 这四个指令构成了 redis 事务处理的基础。
- MULTI 用来组装一个事务;
- EXEC 用来执行一个事务;
- DISCARD 用来取消一个事务;
- WATCH 用来监视一些 key,一旦这些 key 在事务执行之前被改变,则取消事务的执行。
在 Redis 中,通过使用MULTI命令启动事务,然后需要传递应在事务中执行的命令列表,之后整个事务由EXEC命令执行。
1 | 127.0.0.1:6379> MULTI |
4.8.1 基本操作
1 | 127.0.0.1:6379> MULTI |
在上面的例子中,我们看到了 QUEUED 的字样,这表示我们在用 MULTI 组装事务时,每一个命令都会进入到内存队列中缓存起来,如果出现 QUEUED 则表示我们这个命令成功插入了缓存队列,在将来执行 EXEC 时,这些被 QUEUED 的命令都会被组装成一个事务来执行。
对于事务的执行来说,如果 redis 开启了 AOF 持久化的话,那么一旦事务被成功执行,事务中的命令就会通过 write 命令一次性写到磁盘中去,如果在向磁盘中写的过程中恰好出现断电、硬件故障等问题,那么就可能出现只有部分命令进行了 AOF 持久化,这时 AOF 文件就会出现不完整的情况,这时,我们可以使用 redis-check-aof 工具来修复这一问题,这个工具会将 AOF 文件中不完整的信息移除,确保 AOF 文件完整可用。
Redis 事务错误
有关事务,大家经常会遇到的是两类错误:
- 调用 EXEC 之前的错误
- 调用 EXEC 之后的错误
调用 EXEC 之前的错误,有可能是由于语法有误导致的,也可能时由于内存不足导致的。只要出现某个命令无法成功写入缓冲队列的情况,redis 都会进行记录,在客户端调用 EXEC 时,redis 会拒绝执行这一事务。(这是 2.6.5 版本之后的策略。在 2.6.5 之前的版本中,redis 会忽略那些入队失败的命令,只执行那些入队成功的命令)。我们来看一个这样的例子:
1
2
3
4
5
6
7
8
9 127.0.0.1:6379> multi
OK
127.0.0.1:6379> haha //一个明显错误的指令
(error) ERR unknown command 'haha'
127.0.0.1:6379> ping
QUEUED
127.0.0.1:6379> exec
//redis无情的拒绝了事务的执行,原因是“之前出现了错误”
(error) EXECABORT Transaction discarded because of previous errors.而对于调用 EXEC 之后的错误,redis 则采取了完全不同的策略,即 redis 不会理睬这些错误,而是继续向下执行事务中的其他命令。这是因为,对于应用层面的错误,并不是 redis 自身需要考虑和处理的问题,所以一个事务中如果某一条命令执行失败,并不会影响接下来的其他命令的执行。我们也来看一个例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 127.0.0.1:6379> multi
OK
127.0.0.1:6379> set age 23
QUEUED
//age不是集合,所以如下是一条明显错误的指令
127.0.0.1:6379> sadd age 15
QUEUED
127.0.0.1:6379> set age 29
QUEUED
127.0.0.1:6379> exec //执行事务时,redis不会理睬第2条指令执行错误
1) OK
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
3) OK
127.0.0.1:6379> get age
"29" //可以看出第3条指令被成功执行了最后,我们来说说最后一个指令WATCH,这是一个很好用的指令,它可以帮我们实现类似于“乐观锁”的效果,即
CAS(check and set)
。WATCH 本身的作用是监视 key 是否被改动过,而且支持同时监视多个 key,只要还没真正触发事务,WATCH 都会尽职尽责的监视,一旦发现某个 key 被修改了,在执行 EXEC 时就会返回 nil,表示事务无法触发。
1
2
3
4
5
6
7
8
9
10
11
12
13
14 127.0.0.1:6379> set age 23
OK
127.0.0.1:6379> watch age //开始监视age
OK
127.0.0.1:6379> set age 24 //在EXEC之前,age的值被修改了
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set age 25
QUEUED
127.0.0.1:6379> get age
QUEUED
127.0.0.1:6379> exec //触发EXEC
(nil) //事务无法被执行
4.8.2 基本命令汇总
序号 | 命令 | 描述 |
---|---|---|
1 | DISCARD |
取消事务,放弃执行事务块内的所有命令 |
2 | EXEC |
执行所有事务块内的命令 |
3 | MULTI |
标记一个事务块的开始 |
4 | UNWATCH |
取消 WATCH 命令对所有 key 的监视 |
5 | WATCH |
监视一个(或多个) key |
4.9 Script(脚本)
Redis 脚本使用 Lua 解释器来执行脚本。
自版本 2.6.0 开始内嵌于 Redis 中。
用于编写脚本的命令是 EVAL。
4.9.1 基本操作
语法:
1
127.0.0.1:6379> EVAL script numkeys key [key ...] arg [arg ...]
实例:
1
2
3
4
5
6127.0.0.1:6379> EVAL "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second
1) "key1"
2) "key2"
3) "first"
4) "second"
127.0.0.1:6379>
4.9.2 基本命令汇总
序号 | 命令 | 描述 |
---|---|---|
1 | EVAL script numkeys key [key ...] arg [arg ...] |
执行 Lua 脚本。 |
2 | EVALSHA sha1 numkeys key [key ...] arg [arg ...] |
执行 Lua 脚本。 |
3 | SCRIPT EXISTS sha1 [sha1 ...] |
查看指定的脚本是否已经被保存在缓存当中。 |
4 | SCRIPT FLUSH |
从脚本缓存中移除所有脚本。 |
5 | SCRIPT KILL |
杀死当前正在运行的 Lua 脚本。 |
6 | SCRIPT LOAD script |
将脚本 script 添加到脚本缓存中,但并不立即执行这个脚本。 |
4.10 Connection(连接)
Redis 连接命令用于控制和管理到 Redis Server 的客户端连接。
4.10.1 基本操作
示例说明客户端如何向 Redis 服务器验证自身并检查服务器是否正在运行。
1 | [root@localhost redis-6.2.6]# src/redis-cli |
注意:在这里您可以看到未设置“密码”,因此您可以直接访问任何命令。
4.10.2 基本命令汇总
序号 | 命令 | 描述 |
---|---|---|
1 | AUTH password |
验证密码是否正确 |
2 | ECHO message |
打印字符串 |
3 | PING |
查看服务是否运行 |
4 | QUIT |
关闭当前连接 |
5 | SELECT index |
切换到指定的数据库 |
4.11 Server(服务器)
Redis Server 命令用于管理 Redis 服务器。
有不同的服务器命令可用于获取服务器信息,统计信息和其他特征。
4.11.1 基本操作
如何获取有关服务器的所有统计信息和信息。
1 | 127.0.0.1:6379> PING |
4.11.2 基本命令汇总
序号 | 命令 | 描述 |
---|---|---|
1 | BGREWRITEAOF |
异步执行一个 AOF(AppendOnly File) 文件重写操作 |
2 | BGSAVE |
在后台异步保存当前数据库的数据到磁盘 |
3 | CLIENT KILL |
关闭客户端连接 |
4 | CLIENT LIST |
获取连接到服务器的客户端连接列表 |
5 | CLIENT GETNAME |
获取连接的名称 |
6 | CLIENT PAUSE |
在指定时间内终止运行来自客户端的命令 |
7 | CLIENT STNAME |
设置当前连接的名称 |
8 | CLUSTER SLOTS |
获取集群节点的映射数组 |
9 | COMMAND |
获取 Redis 命令总数 |
10 | COMMAND COUNT |
获取 Redis 命令总数 |
11 | COMMAND GETKEYS |
获取给定命令的所有键 |
12 | TIME |
返回当前服务器时间 |
13 | COMMAND INFO |
获取指定 Redis 命令描述的数组 |
14 | CONFIG GET |
获取指定配置参数的值 |
15 | CONFIG REWRITE |
修改 redis.conf 配置文件 |
16 | CONFIG SET |
修改 redis 配置参数,无需重启 |
17 | CONFIG RESETSTAT |
重置 INFO 命令中的某些统计数据 |
18 | DBSIZE |
返回当前数据库的 key 的数量 |
19 | DEBUG OBJECT |
获取 key 的调试信息 |
20 | DEBUG SEGFAULT |
让 Redis 服务崩溃 |
21 | FLUSHALL |
删除所有数据库的所有 key |
22 | FLUSHDB |
删除当前数据库的所有 key |
23 | INFO |
获取 Redis 服务器的各种信息和统计数值 |
24 | LASTSAVE |
返回最近一次 Redis 成功将数据保存到磁盘上的时间 |
25 | MONITOR |
实时打印出 Redis 服务器接收到的命令,调试用 |
26 | ROLE |
返回主从实例所属的角色 |
27 | SAVE |
异步保存数据到硬盘 |
28 | SHUTDOWN |
异步保存数据到硬盘,并关闭服务器 |
29 | SLAVEOF |
将当前服务器转变从属服务器(slave server) |
30 | SLOWLOG |
管理 redis 的慢日志 |
31 | SYNC |
用于复制功能 ( replication ) 的内部命令 |
4.12 HyperLogLog
Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。
在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 264个不同元素的基 数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。
但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。
4.12.1 基本操作
什么是基数?
比如数据集 {1, 3, 5, 7, 5, 7, 8}, 那么这个数据集的基数集为 {1, 3, 5 ,7, 8}, 基数(不重复元素)为5。 基数估计就是在误差可接受的范围内,快速计算基数。
实例
以下实例演示了 HyperLogLog 的工作过程:
1
2
3
4
5
6
7
8
9127.0.0.1:6379> PFADD rediscomcn "redis"
(integer) 1
127.0.0.1:6379> PFADD rediscomcn "mongodb"
(integer) 1
127.0.0.1:6379> PFADD rediscomcn "mysql"
(integer) 1
127.0.0.1:6379> PFCOUNT rediscomcn
(integer) 3
127.0.0.1:6379>
4.12.2 基本命令汇总
序号 | 命令 | 描述 |
---|---|---|
1 | PFADD |
添加指定元素到 HyperLogLog 中。 |
2 | PFCOUNT |
返回给定 HyperLogLog 的基数估算值。 |
3 | PFMERGE |
将多个 HyperLogLog 合并为一个 HyperLogLog |
4.13 地理信息
Redis GEO 主要用于存储地理位置信息,并对存储的信息进行操作,该功能在 Redis 3.2 版本新增。
Redis GEO 操作方法有:
- geoadd:添加地理位置的坐标。
- geopos:获取地理位置的坐标。
- geodist:计算两个位置之间的距离。
- georadius:根据用户给定的经纬度坐标来获取指定范围内的地理位置集合。
- georadiusbymember:根据储存在位置集合里面的某个地点获取指定范围内的地理位置集合。
- geohash:返回一个或多个位置对象的 geohash 值。
4.13.1 geoadd
geoadd 用于存储指定的地理空间位置,可以将一个或多个经度(longitude)、纬度(latitude)、位置名称(member)添加到指定的 key 中。
geoadd 语法格式如下:
1 | 127.0.0.1:6379> GEOADD key longitude latitude member [longitude latitude member ...] |
以下实例中 key 为 Sicily、Catania 为位置名称 :
实例:
1 | 127.0.0.1:6379> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania" |
4.13.2 geopos
geopos 用于从给定的 key 里返回所有指定名称(member)的位置(经度和纬度),不存在的返回 nil。
geopos 语法格式如下:
1 | 127.0.0.1:6379> GEOPOS key member [member ...] |
实例
1 | 127.0.0.1:6379> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania" |
4.13.3 geodist
geodist 用于返回两个给定位置之间的距离。
geodist 语法格式如下:
1 | 127.0.0.1:6379> GEODIST key member1 member2 [m|km|ft|mi] |
member1 member2 为两个地理位置。
最后一个距离单位参数说明:
- m :米,默认单位。
- km :千米。
- mi :英里。
- ft :英尺。
实例: 计算 Palermo 与 Catania 之间的距离实例
1 | 127.0.0.1:6379> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania" |
4.13.4 georadius、georadiusbymember
georadius 以给定的经纬度为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。
georadiusbymember 和 GEORADIUS 命令一样, 都可以找出位于指定范围内的元素, 但是 georadiusbymember 的中心点是由给定的位置元素决定的, 而不是使用经度和纬度来决定中心点。
georadius 与 georadiusbymember 语法格式如下:
1 | GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key] |
参数说明:
- m :米,默认单位。
- km :千米。
- mi :英里。
- ft :英尺。
- WITHDIST: 在返回位置元素的同时, 将位置元素与中心之间的距离也一并返回。
- WITHCOORD: 将位置元素的经度和维度也一并返回。
- WITHHASH: 以 52 位有符号整数的形式, 返回位置元素经过原始 geohash 编码的有序集合分值。 这个选项主要用于底层应用或者调试, 实际中的作用并不大。
- COUNT 限定返回的记录数。
- ASC: 查找结果根据距离从近到远排序。
DESC: 查找结果根据从远到近排序。
georadius实例:
1 | 127.0.0.1:6379> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania" |
georadiusbymember实例:
1 | 127.0.0.1:6379> GEOADD Sicily 13.583333 37.316667 "Agrigento" |
4.13.5 geohash
Redis GEO 使用 geohash 来保存地理位置的坐标。
geohash 用于获取一个或多个位置元素的 geohash 值。
geohash 语法格式如下:
1 | 127.0.0.1:6379> GEOHASH key member [member ...] |
geohash实例:
1 | 127.0.0.1:6379> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania" |
4.14 Stream
Redis Stream 是 Redis 5.0 版本新增加的数据结构。
Redis Stream 主要用于消息队列(MQ,Message Queue),Redis 本身是有一个 Redis 发布订阅 (pub/sub) 来实现消息队列的功能,但它有个缺点就是消息无法持久化,如果出现网络断开、Redis 宕机等,消息就会被丢弃。
简单来说发布订阅 (pub/sub) 可以分发消息,但无法记录历史消息。
而 Redis Stream 提供了消息的持久化和主备复制功能,可以让任何客户端访问任何时刻的数据,并且能记住每一个客户端的访问位置,还能保证消息不丢失。
Redis Stream 的结构如下所示,它有一个消息链表,将所有加入的消息都串起来,每个消息都有一个唯一的 ID 和对应的内容:
每个 Stream 都有唯一的名称,它就是 Redis 的 key,在我们首次使用 xadd 指令追加消息时自动创建。
上图解析:
- Consumer Group :消费组,使用 XGROUP CREATE 命令创建,一个消费组有多个消费者(Consumer)。
- lastdeliveredid :游标,每个消费组会有个游标 lastdeliveredid,任意一个消费者读取了消息都会使游标 lastdeliveredid 往前移动。
- pendingids :消费者(Consumer)的状态变量,作用是维护消费者的未确认的 id。 pendingids 记录了当前已经被客户端读取的消息,但是还没有 ack (Acknowledge character:确认字符)。
消息队列相关命令:
- XADD - 添加消息到末尾
- XTRIM - 对流进行修剪,限制长度
- XDEL - 删除消息
- XLEN - 获取流包含的元素数量,即消息长度
- XRANGE - 获取消息列表,会自动过滤已经删除的消息
- XREVRANGE - 反向获取消息列表,ID 从大到小
- XREAD - 以阻塞或非阻塞方式获取消息列表
消费者组相关命令:
- XGROUP CREATE - 创建消费者组
- XREADGROUP GROUP - 读取消费者组中的消息
- XACK - 将消息标记为”已处理”
- XGROUP SETID - 为消费者组设置新的最后递送消息ID
- XGROUP DELCONSUMER - 删除消费者
- XGROUP DESTROY - 删除消费者组
- XPENDING - 显示待处理消息的相关信息
- XCLAIM - 转移消息的归属权
- XINFO - 查看流和消费者组的相关信息;
- XINFO GROUPS - 打印消费者组的信息;
- XINFO STREAM - 打印流信息
4.14.1 XADD
使用 XADD
向队列添加消息,如果指定的队列不存在,则创建一个队列,XADD 语法格式:
1 | 127.0.0.1:6379> XADD key ID field value [field value ...] |
- key :队列名称,如果不存在就创建
- ID :消息 id,我们使用 * 表示由 redis 生成,可以自定义,但是要自己保证递增性。
- field value : 记录。
XADD实例:
1 | 127.0.0.1:6379> XADD mystream * name Sara surname OConnor |
4.14.2 XTRIM
使用 XTRIM
对流进行修剪,限制长度, 语法格式:
1 | XTRIM key MAXLEN [~] count |
- key :队列名称
- MAXLEN :长度
- count :数量
XTRIM实例:
1 | 127.0.0.1:6379> XADD mystream * field1 A field2 B field3 C field4 D |
4.14.3 XDEL
使用 XDEL
删除消息,语法格式:
1 | 127.0.0.1:6379> XDEL key ID [ID ...] |
- key:队列名称
- ID :消息 ID
XDEL实例:
1 | 127.0.0.1:6379> XADD mystream * a 1 |
4.14.4 XLEN
使用 XLEN
获取流包含的元素数量,即消息长度,语法格式:
1 | 127.0.0.1:6379> XLEN key |
- key:队列名称
XLEN实例:
1 | 127.0.0.1:6379> XADD mystream * item 1 |
4.14.5 XRANGE
使用 XRANGE 获取消息列表,会自动过滤已经删除的消息 ,语法格式:
1 | 127.0.0.1:6379> XRANGE key start end [COUNT count] |
- key :队列名
- start :开始值, - 表示最小值
- end :结束值, + 表示最大值
- count :数量
实例:
1 | 127.0.0.1:6379> XADD writers * name Virginia surname Woolf |
4.14.6 XREVRANGE
使用 XREVRANGE
获取消息列表,会自动过滤已经删除的消息 ,语法格式:
1 | 127.0.0.1:6379> XREVRANGE key end start [COUNT count] |
- key :队列名
- end :结束值, + 表示最大值
- start :开始值, - 表示最小值
- count :数量
XREVRANGE实例:
1 | 127.0.0.1:6379> XADD writers * name Virginia surname Woolf |
4.14.7 XREAD
使用 XREAD 以阻塞或非阻塞方式获取消息列表 ,语法格式:
1 | 127.0.0.1:6379> XREAD [COUNT count] [BLOCK milliseconds] STREAMS key [key ...] id [id ...] |
- count :数量
- milliseconds :可选,阻塞毫秒数,没有设置就是非阻塞模式
- key :队列名
- id :消息 ID
实例: 从 Stream 头部读取两条消息
1 | 127.0.0.1:6379> XREAD COUNT 2 STREAMS mystream writers 0-0 0-0 |
4.14.8 XGROUP CREATE
使用 XGROUP CREATE 创建消费者组,语法格式:
1 | 127.0.0.1:6379> XGROUP [CREATE key groupname id-or-$] [SETID key groupname id-or-$] [DESTROY key groupname] [DELCONSUMER key groupname consumername] |
- key :队列名称,如果不存在就创建
- groupname :组名。
- $ : 表示从尾部开始消费,只接受新消息,当前 Stream 消息会全部忽略。
从头开始消费:
1 | 127.0.0.1:6379> XGROUP CREATE mystream consumer-group-name 0-0 |
从尾部开始消费:
1 | 127.0.0.1:6379> XGROUP CREATE mystream consumer-group-name $ |
4.14.9 XREADGROUP GROUP
使用 XREADGROUP GROUP 读取消费组中的消息,语法格式:
1 | 127.0.0.1:6379> XREADGROUP GROUP group consumer [COUNT count] [BLOCK milliseconds] [NOACK] STREAMS key [key ...] ID [ID ...] |
- group :消费组名
- consumer :消费者名。
- count : 读取数量。
- milliseconds : 阻塞毫秒数。
- key : 队列名。
- ID : 消息 ID。
1 | 127.0.0.1:6379> XREADGROUP GROUP consumer-group-name consumer-name COUNT 1 STREAMS mystream > |
5. Redis 高级功能
5.1 redis备份和恢复
SAVE 命令用于创建当前 Redis 数据库的备份。此命令将通过执行同步 SAVE 在 Redis 目录中创建 dump.rdb 文件。
语法:
1
127.0.0.1:6379> SAVE
返回值:
执行成功后,SAVE 命令返回 OK。
5.1.1 Redis备份示例
使用 SAVE 命令创建当前数据库的备份。
1 | 127.0.0.1:6379> SAVE |
它将在 Redis 目录中创建 dump.rdb 文件。
可以看到 dump.rdb 文件已创建。
1 | [root@192 redis-6.2.6]# ls |
5.1.2 还原Redis数据
将 Redis 备份文件(dump.rdb)移动到 Redis 目录中并启动服务器以恢复 Redis 数据。
查找 Redis 的安装目录,使用 Redis 的 CONFIG 命令,如下所示。
1 | 127.0.0.1:6379> CONFIG get dir |
Redis 服务器安装在/opt/software/redis-6.2.6
目录中。
5.1.3 BGSAVE命令
BGSAVE 是创建 Redis 备份的备用命令。
此命令将启动备份过程并在后台运行。
语法:
1
127.0.0.1:6379> BGSAVE
实例:
1
2
3
4
5
6
7
8[root@192 redis-6.2.6]# src/redis-cli -a yanpenggong
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> CONFIG get dir
1) "dir"
2) "/opt/software/redis-6.2.6"
127.0.0.1:6379> BGSAVE
Background saving started
127.0.0.1:6379>
5.2 Redis 持久化
redis 提供了两种持久化的方式,分别是RDB(Redis DataBase)和AOF(Append Only File)。
RDB,简而言之,就是在不同的时间点,将 redis 存储的数据生成快照并存储到磁盘等介质上;
AOF,则是换了一个角度来实现持久化,那就是将 redis 执行过的所有写指令记录下来,在下次 redis 重新启动时,只要把这些写指令从前到后再重复执行一遍,就可以实现数据恢复了。
其实 RDB 和 AOF 两种方式也可以同时使用,在这种情况下,如果 redis 重启的话,则会优先采用 AOF 方式来进行数据恢复,这是因为 AOF 方式的数据恢复完整度更高。
如果你没有数据持久化的需求,也完全可以关闭 RDB 和 AOF 方式,这样的话,redis 将变成一个纯内存数据库,就像 memcache 一样。
5.2.1 redis持久化RDB
RDB 方式,是将 redis 某一时刻的数据持久化到磁盘中,是一种快照式的持久化方法。
redis 在进行数据持久化的过程中,会先将数据写入到一个临时文件中,待持久化过程都结束了,才会用这个临时文件替换上次持久化好的文件。正是这种特性,让我们可以随时来进行备份,因为快照文件总是完整可用的。
对于 RDB 方式,redis 会单独创建(fork)一个子进程来进行持久化,而主进程是不会进行任何 IO 操作的,这样就确保了 redis 极高的性能。
如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那 RDB 方式要比 AOF 方式更加的高效。
虽然 RDB 有不少优点,但它的缺点也是不容忽视的。如果你对数据的完整性非常敏感,那么 RDB 方式就不太适合你,因为即使你每 5 分钟都持久化一次,当 redis 故障时,仍然会有近 5 分钟的数据丢失。所以,redis 还提供了另一种持久化方式,那就是 AOF。
5.2.2 redis持久化 AOF
AOF,英文是 Append Only File,即只允许追加不允许改写的文件。
如前面介绍的,AOF 方式是将执行过的写指令记录下来,在数据恢复时按照从前到后的顺序再将指令都执行一遍,就这么简单。
我们通过配置 redis.conf 中的 appendonly yes 就可以打开 AOF 功能。如果有写操作(如 SET 等),redis 就会被追加到 AOF 文件的末尾。
默认的 AOF 持久化策略是每秒钟 fsync 一次(fsync 是指把缓存中的写指令记录到磁盘中),因为在这种情况下,redis 仍然可以保持很好的处理性能,即使 redis 故障,也只会丢失最近 1 秒钟的数据。
如果在追加日志时,恰好遇到磁盘空间满、inode 满或断电等情况导致日志写入不完整,也没有关系,redis 提供了 redis-check-aof 工具,可以用来进行日志修复。
因为采用了追加方式,如果不做任何处理的话,AOF 文件会变得越来越大,为此,redis 提供了 AOF 文件重写(rewrite)机制,即当 AOF 文件的大小超过所设定的阈值时,redis 就会启动 AOF 文件的内容压缩,只保留可以恢复数据的最小指令集。举个例子或许更形象,假如我们调用了 100 次 INCR 指令,在 AOF 文件中就要存储 100 条指令,但这明显是很低效的,完全可以把这 100 条指令合并成一条 SET 指令,这就是重写机制的原理。
在进行 AOF 重写时,仍然是采用先写临时文件,全部完成后再替换的流程,所以断电、磁盘满等问题都不会影响 AOF 文件的可用性,这点大家可以放心。
AOF 方式的另一个好处,我们通过一个“场景再现”来说明。某同学在操作 redis 时,不小心执行了 FLUSHALL,导致 redis 内存中的数据全部被清空了,这是很悲剧的事情。不过这也不是世界末日,只要 redis 配置了 AOF 持久化方式,且 AOF 文件还没有被重写(rewrite),我们就可以用最快的速度暂停 redis 并编辑 AOF 文件,将最后一行的 FLUSHALL 命令删除,然后重启 redis,就可以恢复 redis 的所有数据到 FLUSHALL 之前的状态了。是不是很神奇,这就是 AOF 持久化方式的好处之一。但是如果 AOF 文件已经被重写了,那就无法通过这种方法来恢复数据了。
虽然优点多多,但 AOF 方式也同样存在缺陷,比如在同样数据规模的情况下,AOF 文件要比 RDB 文件的体积大。而且,AOF 方式的恢复速度也要慢于 RDB 方式。
如果你直接执行 BGREWRITEAOF 命令,那么 redis 会生成一个全新的 AOF 文件,其中便包括了可以恢复现有数据的最少的命令集。
如果运气比较差,AOF 文件出现了被写坏的情况,也不必过分担忧,redis 并不会贸然加载这个有问题的 AOF 文件,而是报错退出。这时可以通过以下步骤来修复出错的文件:
- 备份被写坏的 AOF 文件
- 运行 redis-check-aof –fix 进行修复
- 用 diff -u 来看下两个文件的差异,确认问题点
- 重启 redis,加载修复后的 AOF 文件
5.2.3 redis持久化 – AOF重写
AOF 重写的内部运行原理,我们有必要了解一下。
在重写即将开始之际,redis 会创建(fork)一个“重写子进程”,这个子进程会首先读取现有的 AOF 文件,并将其包含的指令进行分析压缩并写入到一个临时文件中。
与此同时,主工作进程会将新接收到的写指令一边累积到内存缓冲区中,一边继续写入到原有的 AOF 文件中,这样做是保证原有的 AOF 文件的可用性,避免在重写过程中出现意外。
当“重写子进程”完成重写工作后,它会给父进程发一个信号,父进程收到信号后就会将内存中缓存的写指令追加到新 AOF 文件中。
当追加结束后,redis 就会用新 AOF 文件来代替旧 AOF 文件,之后再有新的写指令,就都会追加到新的 AOF 文件中了。
5.2.4 redis持久化 – 如何选择RDB和AOF
对于我们应该选择 RDB 还是 AOF,官方的建议是两个同时使用。这样可以提供更可靠的持久化方案。
5.3 redis安全
对于数据库来说,安全性是非常必要的,以确保数据的安全性。它提供身份验证,因此如果客户端想要建立连接,则需要在执行命令之前进行身份验证。
需要在配置文件中设置密码以保护 Redis 数据库。
实例:
1 | 127.0.0.1:6379> CONFIG get requirepass |
可以看到上面的属性为空,表示没有此实例的任何密码。
可以通过执行以下命令来更改此属性并为此实例设置密码。
1 | 127.0.0.1:6379> CONFIG set requirepass "yanpenggong" |
设置此密码时,如果客户端在未经身份验证的情况下运行该命令,则会收到错误“NOAUTH Authentication required。”。因此,客户端需要使用 AUTH 命令来验证自己。
5.3.1 AUTH命令的用法
1 | 127.0.0.1:6379> AUTH "yanpenggong" |
5.4 Redis 基准
Redis 基准测试 redis-benchmark 是一种实用工具,用于通过同时使用 multiple(n) 命令来检查 Redis 的性能。
语法:
1
redis-benchmark [option] [option value]
实例:
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111[root@192 redis-6.2.6]# src/redis-benchmark -n 100000 -a yanpenggong
====== PING_INLINE ======
100000 requests completed in 15.49 seconds
50 parallel clients
3 bytes payload
keep alive: 1
host configuration "save": 900 1 300 10 60 10000
host configuration "appendonly": no
multi-thread: no
Latency by percentile distribution:
0.000% <= 2.807 milliseconds (cumulative count 1)
50.000% <= 5.791 milliseconds (cumulative count 50175)
75.000% <= 6.711 milliseconds (cumulative count 75143)
87.500% <= 7.351 milliseconds (cumulative count 87511)
93.750% <= 8.007 milliseconds (cumulative count 93796)
96.875% <= 8.671 milliseconds (cumulative count 96890)
98.438% <= 9.351 milliseconds (cumulative count 98442)
99.219% <= 10.039 milliseconds (cumulative count 99219)
99.609% <= 10.783 milliseconds (cumulative count 99613)
99.805% <= 11.319 milliseconds (cumulative count 99807)
99.902% <= 11.999 milliseconds (cumulative count 99903)
99.951% <= 13.351 milliseconds (cumulative count 99952)
99.976% <= 16.463 milliseconds (cumulative count 99976)
99.988% <= 29.823 milliseconds (cumulative count 99988)
99.994% <= 30.511 milliseconds (cumulative count 99994)
99.997% <= 30.735 milliseconds (cumulative count 99997)
99.998% <= 30.911 milliseconds (cumulative count 99999)
99.999% <= 31.023 milliseconds (cumulative count 100000)
100.000% <= 31.023 milliseconds (cumulative count 100000)
Cumulative distribution of latencies:
0.000% <= 0.103 milliseconds (cumulative count 0)
0.007% <= 3.103 milliseconds (cumulative count 7)
8.508% <= 4.103 milliseconds (cumulative count 8508)
32.111% <= 5.103 milliseconds (cumulative count 32111)
58.966% <= 6.103 milliseconds (cumulative count 58966)
83.729% <= 7.103 milliseconds (cumulative count 83729)
94.418% <= 8.103 milliseconds (cumulative count 94418)
98.012% <= 9.103 milliseconds (cumulative count 98012)
99.266% <= 10.103 milliseconds (cumulative count 99266)
99.737% <= 11.103 milliseconds (cumulative count 99737)
99.915% <= 12.103 milliseconds (cumulative count 99915)
99.948% <= 13.103 milliseconds (cumulative count 99948)
99.956% <= 14.103 milliseconds (cumulative count 99956)
99.962% <= 15.103 milliseconds (cumulative count 99962)
99.970% <= 16.103 milliseconds (cumulative count 99970)
99.979% <= 17.103 milliseconds (cumulative count 99979)
99.980% <= 29.103 milliseconds (cumulative count 99980)
99.991% <= 30.111 milliseconds (cumulative count 99991)
100.000% <= 31.103 milliseconds (cumulative count 100000)
Summary:
throughput summary: 6454.53 requests per second
latency summary (msec):
avg min p50 p95 p99 max
5.870 2.800 5.791 8.207 9.807 31.023
====== PING_MBULK ======
100000 requests completed in 15.45 seconds
50 parallel clients
3 bytes payload
keep alive: 1
host configuration "save": 900 1 300 10 60 10000
host configuration "appendonly": no
multi-thread: no
Latency by percentile distribution:
0.000% <= 2.351 milliseconds (cumulative count 1)
50.000% <= 5.727 milliseconds (cumulative count 50067)
75.000% <= 6.671 milliseconds (cumulative count 75131)
87.500% <= 7.415 milliseconds (cumulative count 87505)
93.750% <= 8.263 milliseconds (cumulative count 93781)
96.875% <= 9.119 milliseconds (cumulative count 96886)
98.438% <= 9.871 milliseconds (cumulative count 98438)
99.219% <= 10.567 milliseconds (cumulative count 99221)
99.609% <= 11.207 milliseconds (cumulative count 99611)
99.805% <= 11.863 milliseconds (cumulative count 99805)
99.902% <= 12.575 milliseconds (cumulative count 99904)
99.951% <= 13.471 milliseconds (cumulative count 99952)
99.976% <= 14.479 milliseconds (cumulative count 99976)
99.988% <= 15.255 milliseconds (cumulative count 99988)
99.994% <= 15.703 milliseconds (cumulative count 99994)
99.997% <= 16.303 milliseconds (cumulative count 99997)
99.998% <= 16.479 milliseconds (cumulative count 99999)
99.999% <= 16.607 milliseconds (cumulative count 100000)
100.000% <= 16.607 milliseconds (cumulative count 100000)
Cumulative distribution of latencies:
0.000% <= 0.103 milliseconds (cumulative count 0)
0.014% <= 3.103 milliseconds (cumulative count 14)
9.664% <= 4.103 milliseconds (cumulative count 9664)
33.922% <= 5.103 milliseconds (cumulative count 33922)
60.409% <= 6.103 milliseconds (cumulative count 60409)
83.670% <= 7.103 milliseconds (cumulative count 83670)
92.958% <= 8.103 milliseconds (cumulative count 92958)
96.842% <= 9.103 milliseconds (cumulative count 96842)
98.776% <= 10.103 milliseconds (cumulative count 98776)
99.566% <= 11.103 milliseconds (cumulative count 99566)
99.843% <= 12.103 milliseconds (cumulative count 99843)
99.937% <= 13.103 milliseconds (cumulative count 99937)
99.968% <= 14.103 milliseconds (cumulative count 99968)
99.985% <= 15.103 milliseconds (cumulative count 99985)
99.996% <= 16.103 milliseconds (cumulative count 99996)
100.000% <= 17.103 milliseconds (cumulative count 100000)
Summary:
throughput summary: 6472.91 requests per second
latency summary (msec):
avg min p50 p95 p99 max
5.858 2.344 5.727 8.551 10.319 16.607
SET: rps=7171.3 (overall: 5609.2) avg_msec=5.378 (overall: 6.777)redis 性能测试工具可选参数
| 序号 | 选项 | 描述 | 默认值 |
| —— | ——- | ————————————————————— | ————- |
| 1 | -h | 指定服务器主机名 | 127.0.0.1 |
| 2 | -p | 指定服务器端口 | 6379 |
| 3 | -s | 指定服务器 socket | |
| 4 | -c | 指定并发连接数 | 50 |
| 5 | -n | 指定请求数 | 10000 |
| 6 | -d | 以字节的形式指定 SET/GET 值的数据大小 | 2 |
| 7 | -k | 1=keep alive 0=reconnect | 1 |
| 8 | -r | SET/GET/INCR 使用随机 key, SADD 使用随机值 | |
| 9 | -P | 通过管道传输请求 | 1 |
| 10 | -q | 强制退出 redis。仅显示 query/sec 值 | |
| 11 | —csv | 以 CSV 格式输出 | |
| 12 | -l | 生成循环,永久执行测试 | |
| 13 | -t | 仅运行以逗号分隔的测试命令列表 | |
| 14 | -I | Idle 模式。仅打开 N 个 idle 连接并等待 | |实例:
以下实例使用了多个参数来测试 redis 性能:主机为 127.0.0.1,端口号为 6379,执行的命令为 set,lpush,请求数为 10000,通过 -q 参数让结果只显示每秒执行的请求数。
1
2
3
4
5[root@192 redis-6.2.6]# src/redis-benchmark -h 127.0.0.1 -p 6379 -t set,lpush -n 100000 -q -a yanpenggong
SET: 6676.46 requests per second, p50=5.639 msec
LPUSH: 6538.51 requests per second, p50=5.775 msec
[root@192 redis-6.2.6]#
5.5 Redis客户端连接
Redis 可以在配置的监听 TCP 端口和 Unix 套接字上接受不同类型的客户端连接。
接受新客户端连接时,它将执行以下操作:
- 由于 Redis 使用多路复用和非阻塞 I/O,因此客户端套接字处于非阻塞状态。
- 设置 TCP_NODELAY 选项是为了确保我们的连接没有延迟。
- 创建可读文件事件,以便一旦可以在套接字上读取新数据,Redis 就能够收集客户端查询。
5.5.1 最大客户端数
在 Redis config(redis.conf)中,有一个名为 maxclients
的属性,它指定可以连接到 Redis 的客户端数量。
1 | [root@192 redis-6.2.6]# src/redis-cli -a yanpenggong |
最大客户端数取决于 OS 的最大文件描述符数限制。它的默认值为 10000,但您可以更改此属性。
实例: 在启动服务器时将最大客户端数设置为 100000。
1 | [root@192 redis-6.2.6]# src/redis-server --maxclients 100000 |
5.5.2 Redis 客户端命令
序号 | 命令 | 描述 |
---|---|---|
1 | CLIENT LIST |
返回连接到 redis 服务的客户端列表 |
2 | CLIENT SETNAME |
设置当前连接的名称 |
3 | CLIENT GETNAME |
获取通过 CLIENT SETNAME 命令设置的服务名称 |
4 | CLIENT PAUSE |
挂起客户端连接,指定挂起的时间以毫秒计 |
5 | CLIENT KILL |
关闭客户端连接 |
5.6 Redis Pipelining 流水线
在了解流水线之前,首先要了解 Redis 的概念:
Redis 是一个支持请求/响应协议的 TCP 服务器。在 Redis 中,请求分两步完成:
- 客户端通常以阻塞方式向服务器发送命令。
- 服务器处理该命令并将响应发送回客户端。
5.6.1 什么是流水线
流水线操作有助于客户端向服务器发送多个请求,而无需等待回复,最后只需一步即可读取回复。
例: 向 Redis 提交一次命令,Redis 将在一个步骤中提供所有命令的输出。
1 | [root@192 redis-6.2.6]# (echo -en “PING\r\n SET sssit javatraining\r\n GET sssit\r\n INCR visitor\r\n INCR visitor\r\n INCR visitor\r\n” ; sleep 10 ) | nc localhost 6379 |
这里:
- PING 命令用于检查 Redis 连接。
- 设置名为“sssit”的字符串,其值为“javatraining”。
- 获得了 key 值并将访问者数量增加了三倍。
每次增加值时都可以看到。
5.6.2 流水线的优势
Redis 流水线操作的主要优点是提高了 Redis 的性能。由于多个命令同时执行,它极大地提高了协议性能。
5.6.3 Pipelining vs Scripting
Redis Scripting 可在 Redis 2.6 或更高版本中使用。
脚本的主要优点是它可以以最小的延迟同时读取和写入数据。它使读取,计算,写入等操作变得非常快。
在流水线操作中,客户端在调用 write 命令之前需要 read 命令的回复。
5.7 redis分区
分区用于将 Redis 数据拆分为多个 Redis 实例,以便每个实例仅包含一部分 key。
它通常用于大型数据库。
5.7.1 分区类型
redis 中有两种类型的分区:
- 范围分区
- 哈希分区
5.7.2 范围分区
范围分区是执行分区的最简单方法之一。它通过将对象的范围映射到特定的 Redis 实例来完成。
例如:
假设您有 3000 个用户。因此,您可以说从 ID 0 到 ID 1000 的用户将进入实例 R0,而用户表单 ID 1001 到 ID 2000 将进入实例 R1,用户表单 ID 2001 到 ID 3000 将进入实例 R2,依此类推。
5.7.3 哈希分区
散列分区是 Range 分区的替代方法。在散列分区中,散列函数用于将 key 转换为数字,然后将数据存储在不同的 Redis 实例中。
5.7.4 Redis分区的优点
- 分区有助于您使用多台计算机的集体内存。例如:对于较大的数据库,您需要大量内存,因此分区可以提供来自不同计算机的内存总和。如果不进行分区,则只能使用单台计算机可以支持的有限内存量。
- 分区还用于将计算能力扩展到多个核心和多个计算机,以及网络带宽扩展到多个计算机和网络适配器。
5.7.5 Redis分区的缺点
分区存在一些缺点,因为 Redis 的某些功能受到分区的阻碍。
- 分区通常不支持具有多个键的操作。例如,如果两个集合存储在映射到不同 Redis 实例的键中,则无法执行它们之间的交集。
- 分区不支持具有多个 key 的事务。
- 分区粒度是关键,因此不可能使用单个巨大的 key(如非常大的有序集)对数据集进行分片。
- 使用分区时,数据处理更复杂,例如,您必须处理多个 RDB / AOF 文件,并且需要从多个实例和主机聚合持久性文件来备份数据。
- 添加和删除容量可能很复杂。例如,Redis Cluster 支持大多数透明的数据重新平衡,能够在运行时添加和删除节点,但客户端分区和代理等其他系统不支持此功能。然而,一种称为预分片的技术在这方面有所帮助。
Redis命令手册
1. 命令集合
1.1 Key(键)
1.1.1 DEL key
Redis DEL 命令用于删除给定的一个或多个 key
。不存在的 key
会被忽略。
语法:
1
127.0.0.1:6379> DEL KEY_NAME
返回值:
整数: 被删除 key 的数量。
实例:
1
2
3
4
5
6
7
8
9127.0.0.1:6379> set kungs1 "Hello"
OK
127.0.0.1:6379> set kungs2 "World"
OK
127.0.0.1:6379> set kungs3 "redis"
OK
127.0.0.1:6379> DEL kungs1 kungs2 kungs3 kungs4
3
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(N) where N is the number of keys that will be removed. When a key to remove holds a value other than a string, the individual complexity for this key is O(M) where M is the number of elements in the list, set, sorted set or hash. Removing a single key that holds a string value is O(1).
1.1.2 DUMP key
Redis DUMP 用于序列化给定 key
,并返回被序列化的值,使用 restore
命令可以将DUMP
的结果反序列化回 Redis 。
序列化格式有以下几个特点:
- 它带有 64 位的校验和,用于检测错误,
restore
在进行反序列化之前会先检查校验和。.- 值的编码格式和 RDB 文件保持一致。
- RDB 版本会被编码在序列化值当中,如果因为 Redis 的版本造成 RDB 格式不兼容,那么 Redis 会拒绝对这个值进行反序列化操作。
序列化的值不包括任何过期(expire)信息。
如果想获得 key 的剩余过期时间,需要使用 PTTL 命令。
如果 key
不存在,那么返回 nil
语法:
1
127.0.0.1:6379> DUMP KEY_NAME
返回值:
多行字符串: 如果 key 不存在,那么返回 nil 。 否则,返回序列化之后的值。
实例:
1
2
3
4
5127.0.0.1:6379> set kungskey 10
OK
127.0.0.1:6379> DUMP kungskey
"\x00\xc0\n\t\x00\xbem\x06\x89Z(\x00\n"
127.0.0.1:6379>
可用版本>= 2.6.0.
时间复杂度: O(1) to access the key and additional O(NM) to serialize it, where N is the number of Redis objects composing the value and M their average size. For small string values the time complexity is thus O(1)+O(1M) where M is small, so simply O(1).
1.1.3 EXISTS key [key …]
Redis EXISTS 命令用于检查给定 key
是否存在。
从 Redis 3.0.3 起可以一次检查多个 key 是否存在。这种情况下,返回待检查 key 中存在的 key 的个数。检查单个 key 返回 1 或 0 。
注意:如果相同的 key 在参数列表中出现了多次,它会被计算多次。所以,如果somekey
存在, EXISTS somekey somekey
命令返回 2。
语法:
1
127.0.0.1:6379> EXISTS KEY_NAME
返回值:
整数:
1
: key存在0
: key不存在
实例:
1
2
3
4
5
6
7
8
9
10
11127.0.0.1:6379> SET key1 "Hello"
OK
127.0.0.1:6379> EXISTS key1
(integer) 1
127.0.0.1:6379> EXISTS nosuchkey
(integer) 0
127.0.0.1:6379> SET key2 "World"
OK
127.0.0.1:6379> EXISTS key1 key2 nosuchkey
(integer) 2
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(1)
1.1.4 EXPIRE key seconds
Redis Expire
命令设置 key
的过期时间(seconds)。 设置的时间过期后,key 会被自动删除。带有超时时间的 key 通常被称为易失的(volatile)。
超时时间只能使用删除 key 或者覆盖 key 的命令清除,包括 DEL, SET, GETSET 和所有的 *STORE
命令。 对于修改 key 中存储的值,而不是用新值替换旧值的命令,不会修改超时时间。例如,自增 key 中存储的值的 INCR, 向list中新增一个值 LPUSH, 或者修改 hash 域的值 HSET ,这些都不会修改 key 的过期时间。
通过使用 PERSIST 命令把 key 改回持久的(persistent) key,这样 key 的过期时间也可以被清除。
key使用 RENAME 改名后,过期时间被转移到新 key 上。
已存在的旧 key 使用 RENAME 改名,那么新 key 会继承所有旧 key 的属性。例如,一个名为 Key_A 的 key 使用命令 RENAME Key_B Key_A
改名,新的 Key_A 会继承包括超时时间在内的所有 Key_B 的属性。
特别注意,使用负值调用 EXPIRE/PEXPIRE 或使用过去的时间调用 EXPIREAT/PEXPIREAT ,那么 key 会被删除 deleted 而不是过期。 (因为, 触发的key event 将是 del
, 而不是 expired
).
1.1.5 EXPIREAT key timestamp
EXPIREAT 与 EXPIRE 有相同的作用和语义, 不同的是 EXPIREAT 使用绝对 Unix 时间戳 (自1970年1月1日以来的秒数)代替表示过期时间的秒数。使用过去的时间戳将会立即删除该 key。
详细语义功能说明可以参考 EXPIRE。
语法:
1
127.0.0.1:6379> Expireat KEY_NAME TIME_IN_UNIX_TIMESTAMP
背景:
EXPIREAT 引入的目的是为了把 AOF 持久化模式的相对时间转换为绝对时间。当然,也可以直接指明某个 key 在未来某个时间过期。
返回值:
整数:
1
: 设置超时成功0
: key不存在
实例:
1
2
3
4
5
6
7
8
9127.0.0.1:6379> SET mykey "Hello"
OK
127.0.0.1:6379> EXISTS mykey
(integer) 1
127.0.0.1:6379> EXPIREAT mykey 1293840000
(integer) 1
127.0.0.1:6379> EXISTS mykey
(integer) 0
127.0.0.1:6379>
可用版本>= 1.2.0.
时间复杂度: O(1)
1.1.6 PEXPIRE key milliseconds
PEXPIRE 跟 EXPIRE 基本一样,只是过期时间单位是毫秒。
语法:
1
127.0.0.1:6379> PEXPIRE key milliseconds
返回值:
整数:
1
: 过期设置成功0
: key不存在 或设置失败
实例:
1
2
3
4
5
6
7
8
9127.0.0.1:6379> SET mykey "Hello"
OK
127.0.0.1:6379> PEXPIRE mykey 15000
(integer) 1
127.0.0.1:6379> TTL mykey
(integer) 11
127.0.0.1:6379> PTTL mykey
(integer) 7039
127.0.0.1:6379>
可用版本>= 2.6.0.
时间复杂度: O(1)
1.1.7 PEXPIREAT key milliseconds-timestamp
Redis PEXPIREAT 命令用于设置 key 的过期时间,时间的格式是uinx时间戳并精确到毫秒。
语法:
1
127.0.0.1:6379> PEXPIREAT KEY_NAME TIME_IN_MILLISECONDS_IN_UNIX_TIMESTAMP
返回值:
整数:
1
: 设置成功返回0
: key不存在
实例:
1
2
3
4
5
6
7
8
9127.0.0.1:6379> SET mykey "Hello"
OK
127.0.0.1:6379> PEXPIREAT mykey 150000000000
(integer) 1
127.0.0.1:6379> TTL mykey
(integer) -2
127.0.0.1:6379> PTTL mykey
(integer) -2
127.0.0.1:6379>
可用版本>= 2.6.0.
时间复杂度: O(1)
1.1.8 KEYS pattern
Redis KEYS 命令用于查找所有匹配给定模式 pattern 的 key 。
尽管这个操作的时间复杂度是 O(N),但是常量时间相当小。
例如,在一个普通笔记本上跑 Redis,扫描 100 万个 key 只要40毫秒。
Warning: 生产环境使用 KEYS 命令需要非常小心。在大的数据库上执行命令会影响性能。
这个命令适合用来调试和特殊操作,像改变键空间布局。
不要在你的代码中使用 KEYS 。如果你需要一个寻找键空间中的key子集,考虑使用 SCAN 或 Sets。
匹配模式:
h?llo
匹配hello
,hallo
和hxllo
h*llo
匹配hllo
和heeeello
h[ae]llo
匹配hello
andhallo,
不匹配hillo
h[^e]llo
匹配hallo
,hbllo
, … 不匹配hello
h[a-b]llo
匹配hallo
和hbllo
使用 \
转义你想匹配的特殊字符。
1.1.9 MOVE key db
Redis MOVE 命令用于将当前数据库的 key 移动到选定的数据库 db 当中。
如果 key
在目标数据库中已存在,或者 key
在源数据库中不存,则key
不会被移动。
语法:
1
127.0.0.1:6379> MOVE KEY_NAME DESTINATION_DATABASE
返回值:
整数:
1
:key
被移动0
:key
没有被移动
实例:
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58key 存在于当前数据库
redis默认使用数据库 0,为了清晰起见,这里再显式指定一次。
127.0.0.1:6379> select 0
OK
127.0.0.1:6379> set kungs "yanpenggong base -Zone"
OK
将 kungs 移动到数据库 1
127.0.0.1:6379> move kungs 1
(integer) 1
kungs 已经被移走
127.0.0.1:6379> exists kungs
(integer) 0
使用数据库 1
127.0.0.1:6379> select 1
OK
证实 kungs 被移到了数据库 1
(注意命令提示符变成了"127.0.0.1:6379[1]",表明正在使用数据库 1)
127.0.0.1:6379[1]> exists kungs
(integer) 1
当 key 不存在的时候
127.0.0.1:6379[1]> exists fake_key
(integer) 0
试图从数据库 1 移动一个不存在的 key 到数据库 0,失败
127.0.0.1:6379[1]> move fake_key 0
(integer) 0
使用数据库0
127.0.0.1:6379[1]> select 0
OK
证实 fake_key 不存在
127.0.0.1:6379> exists fake_key
(integer) 0
当源数据库和目标数据库有相同的 key 时
使用数据库0
127.0.0.1:6379> select 0
OK
127.0.0.1:6379> set fruit "apple"
OK
使用数据库1
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> set fruit "pineappleC"
OK
使用数据库0,并试图将 fruit 移动到数据库 1
127.0.0.1:6379[1]> select 0
OK
因为两个数据库有相同的 key,MOVE 失败
127.0.0.1:6379> move fruit 1
(integer) 0
数据库 0 的 fruit 没变
127.0.0.1:6379> get fruit
"apple"
数据库 1 的 fruit 也是
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> get fruit
"pineappleC"
127.0.0.1:6379[1]>
可用版本>= 1.0.0.
时间复杂度: O(1)
1.1.10 PERSIST key
Redis PERSIST 命令用于删除给定 key 的过期时间,使得 key 永不过期。
语法:
1
127.0.0.1:6379> PERSIST KEY_NAME
返回值:
整数:
1
: 当过期时间移除成功时0
: key不存在或 key 没有设置过期时间
实例:
1
2
3
4
5
6
7
8
9
10
11
12
13127.0.0.1:6379> SET mykey "Hello"
OK
为 key 设置生存时间
127.0.0.1:6379> EXPIRE mykey 10
(integer) 1
127.0.0.1:6379> TTL mykey
(integer) 8
移除 key 的生存时间
127.0.0.1:6379> PERSIST mykey
(integer) 1
127.0.0.1:6379> TTL mykey
(integer) -1
127.0.0.1:6379>
可用版本>= 2.2.0.
时间复杂度: O(1)
1.1.11 PTTL key
Redis PTTL 命令以毫秒为单位返回 key 的剩余过期时间。
语法:
1
127.0.0.1:6379> PTTL KEY_NAME
返回值:
Redis 2.6 之前的版本如果 key 不存在或者 key 没有关联超时时间则返回
-1
。Redis 2.8 起:
- key 不存在返回
-2
- key 存在但是没有关联超时时间返回
-1
整数:
-1
: key 存在但没有设置剩余生存时间-2
: key 不存在其它
: 以毫秒为单位,返回 key 的剩余生存时间
- key 不存在返回
实例:
1
2
3
4
5
6
7
8
9
10
11127.0.0.1:6379> set mykey "Hello"
OK
key 存在,但没有设置剩余生存时间
127.0.0.1:6379> PTTL mykey
(integer) -1
127.0.0.1:6379> EXPIRE mykey 1000
(integer) 1
有剩余生存时间的 key
127.0.0.1:6379> PTTL mykey
(integer) 998591
127.0.0.1:6379>
可用版本>= 2.6.0.
时间复杂度: O(1)
1.1.12 TTL key
Redis TTL 命令以秒为单位返回 key 的剩余过期时间。用户客户端检查 key 还可以存在多久。
- Redis 2.6 之前的版本如果 key 不存在或者 key 没有关联超时时间则返回 -1 。
- Redis 2.8 起:
- key 不存在返回 -2
- key 存在但是没有关联超时时间返回 -1
- PTTL 返回以毫秒为单位的剩余超时时间。
返回值:
整数: 剩余超时秒数,失败返回负数如上。
实例:
1
2
3
4
5
6
7
8
9
10
11127.0.0.1:6379> set mykey "Hello"
OK
key 存在,但没有设置剩余生存时间
127.0.0.1:6379> TTL mykey
(integer) -1
127.0.0.1:6379> EXPIRE mykey 1000
(integer) 1
有剩余生存时间的 key
127.0.0.1:6379> TTL mykey
(integer) 998
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(1)
1.1.13 RANDOMKEY
Redis RANDOMKEY 命令从当前数据库中随机返回一个 key 。
语法:
1
127.0.0.1:6379> RANDOMKEY
返回值:
多行字符串: 当数据库不为空时,返回一个 key 。 当数据库为空时,返回 nil 。
实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15127.0.0.1:6379> MSET fruit "apple" drink "beer" food "cookies"
OK
127.0.0.1:6379> KEYS *
1) "food"
2) "drink"
3) "fruit"
127.0.0.1:6379> RANDOMKEY
"food"
127.0.0.1:6379> RANDOMKEY
"fruit"
127.0.0.1:6379> FLUSHDB
OK
127.0.0.1:6379> RANDOMKEY
(nil)
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(1)
1.1.14 RENAME key newkey
Redis RENAME 命令用于修改 key 的名字为 newkey 。若key 不存在返回错误。
在集群模式下,key 和newkey 需要在同一个 hash slot。key 和newkey有相同的 hash tag 才能重命名。
如果 newkey 存在则会被覆盖,此种情况隐式执行了 DEL 操作,所以如果要删除的key的值很大会有一定的延时,即使RENAME 本身是常量时间复杂度的操作。
在集群模式下,key 和newkey 需要在同一个 hash slot。key 和newkey有相同的 hash tag 才能重命名。
历史:
<= 3.2.0
: 源 key 和目的 key 相同返回错误。返回值:
字符串
实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23key 存在且 newkey 不存在
127.0.0.1:6379> set mykey "Hello"
OK
127.0.0.1:6379> RENAME mykey mykey1
OK
127.0.0.1:6379> get mykey1
"Hello"
当 key 不存在时,返回错误
127.0.0.1:6379> RENAME mykey2 mykey22
(error) ERR no such key
newkey 已存在时, RENAME 会覆盖旧 newkey
127.0.0.1:6379> set pc "macpro"
OK
127.0.0.1:6379> set personal_computer "thinkpad"
OK
127.0.0.1:6379> RENAME pc personal_computer
OK
127.0.0.1:6379> get pc
(nil)
原来的值 thinkpad 被覆盖了
127.0.0.1:6379> get personal_computer
"macpro"
127.0.0.1:6379>可用版本>= 1.0.0.
时间复杂度: O(1)
1.1.15 RENAMENX key newkey
Redis Renamenx 命令用于在新的 key 不存在时修改 key 的名称 。若 key 不存在返回错误。
在集群模式下,key
和newkey
需要在同一个 hash slot。key
和newkey
有相同的 hash tag 才能重命名。
语法:
1
127.0.0.1:6379> RENAMENX OLD_KEY_NAME NEW_KEY_NAME
历史:
返回值:
整数:
1
: rename 成功0
:newkey
已经存在
实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19newkey 不存在,改名成功
127.0.0.1:6379> set mykey "Hello"
OK
127.0.0.1:6379> RENAMENX mykey myotherkey
(integer) 1
127.0.0.1:6379> GET myotherkey
"Hello"
newkey存在时,失败
127.0.0.1:6379> SET animal "bear"
OK
127.0.0.1:6379> SET favorite_animal "butterfly"
OK
127.0.0.1:6379> RENAMENX animal favorite_animal
(integer) 0
127.0.0.1:6379> get animal
"bear"
127.0.0.1:6379> get favorite_animal
"butterfly"
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(1)
1.1.16 SCAN cursor [MATCH pattern] [COUNT count]
Redis SCAN 命令及其相关命令 SSCAN, HSCAN, ZSCAN 命令都是用于增量遍历集合中的元素。
以上列出的四个命令都支持增量式迭代, 它们每次执行都只会返回少量元素, 所以这些命令可以用于生产环境, 而不会出现像 KEYS 命令、 SMEMBERS 命令带来的问题 —— 当 KEYS 命令被用于处理一个大的数据库时, 又或者 SMEMBERS 命令被用于处理一个大的集合键时, 它们可能会阻塞服务器达数秒之久。
不过, 增量式迭代命令也不是没有缺点的: 举个例子, 使用 SMEMBERS 命令可以返回集合键某一时刻包含的所有元素, 但是对于 SCAN 这类增量式迭代命令来说, 因为在对键进行增量式迭代的过程中, 键可能会被修改, 所以增量式迭代命令不能完全保证返回所有元素。
因为 SCAN 、 SSCAN 、 HSCAN 和 ZSCAN 四个命令的工作方式都非常相似, 所以这个文档会一并介绍这四个命令, 但是要记住:SSCAN 命令、 HSCAN 命令和 ZSCAN 命令的第一个参数总是一个存储集合的键名。而 SCAN 命令则不需要在第一个参数提供任何数据库键 —— 因为它迭代的是当前数据库中的所包含的键。
SCAN 命令的基本用法
SCAN 命令是一个基于游标的迭代器,每次被调用之后, 都会向用户返回一个新的游标, 用户在下次迭代时需要使用这个新游标作为 SCAN 命令的游标参数, 以此来延续之前的迭代过程。
SCAN 返回一个包含两个元素的数组, 第一个元素是用于进行下一次迭代的新游标, 而第二个元素则是一个数组, 这个数组中包含了所有被迭代的元素。当 SCAN 命令的游标参数被设置为
0
时, 服务器将开始一次新的迭代,而当服务器向用户返回值为0
的游标时, 表示迭代已结束。例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 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"
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"在上面这个例子中, 第一次迭代使用
0
作为游标, 表示开始一次新的迭代。第二次迭代使用的是第一次迭代时返回的游标, 也就是命令回复第一个元素的值 ——17
。
SCAN 命令的保证
- 如果有一个元素, 它从遍历开始直到遍历结束期间都存在于被遍历的数据集当中, 那么 SCAN 命令总会在某次迭代中将这个元素返回给用户。
- 如果有一个元素, 它从遍历开始就已经被删除,且直到遍历结束也没有被添加回来, 那么 SCAN 命令确保不会返回这个元素。
然而因为 SCAN 命令仅仅使用游标来记录迭代状态, 所以这些命令带有以下缺点:
- 同一个元素可能会被返回多次。 处理重复元素的工作交由应用程序负责, 比如说, 可以考虑将迭代返回的元素仅仅用于可以安全地重复执行多次的操作上。
- 如果一个元素是在迭代过程中被添加到数据集的, 又或者是在迭代过程中从数据集中被删除的, 那么这个元素可能会被返回, 也可能不会, 这是未定义的(undefined)。
SCAN 命令每次执行返回的元素数量
SCAN 命令族并不保证每次执行都返回某个给定数量的元素。增量式命令甚至可能会返回零个元素, 但只要命令返回的游标不是
0
, 应用程序就不应该将迭代视作结束。不过命令返回的元素数量总是符合一定规则的, 在实际中:对于一个大数据集来说, 增量式迭代命令每次最多可能会返回数十个元素;而对于一个足够小的数据集来说, 小集合键、小哈希键和小有序集合键, 那么增量迭代命令将在一次调用中返回数据集中的所有元素。
最后, 用户可以通过增量式迭代命令提供的 COUNT 选项来指定每次迭代返回元素的最大值。
COUNT 选项
虽然 SCAN 命令不保证每次迭代所返回的元素数量, 但我们可以使用 COUNT选项, 对命令的行为进行一定程度上的调整。 COUNT 选项的作用就是让用户告知迭代命令, 在每次迭代中应该从数据集里返回多少元素。虽然这个选项只是对增量式迭代命令的一种提示(hint), 但是在大多数情况下, 这种提示都是有效的。
- COUNT 参数的默认值为
10
。- 在迭代一个足够大的、由哈希表实现的数据库、集合键、哈希键或者有序集合键时, 如果用户没有使用
MATCH
选项, 那么命令返回的元素数量通常和COUNT
选项指定的一样, 或者比COUNT
选项指定的数量稍多一些。- 在迭代一个编码为整数集合(intset,一个只由整数值构成的小集合)、 或者编码为压缩列表(ziplist,由不同值构成的一个小哈希或者一个小有序集合)时, 增量式迭代命令通常会无视
COUNT
选项指定的值, 在第一次迭代就将数据集包含的所有元素都返回给用户。Important: 并非每次迭代都要使用相同的
COUNT
**值。用户可以在每次迭代中按自己的需要随意改变COUNT
值, 只要记得将上次迭代返回的游标用到下次迭代里面就可以了。
MATCH 选项
和 KEYS 命令一样,
SCAN
命令族也可以通过提供一个 glob 风格的模式参数, 让命令只返回和给定模式相匹配的元素, 这一点可以通过在执行增量式迭代命令时, 通过给定MATCH <pattern>
参数来实现。例如:
1
2
3
4
5
6
7
8 127.0.0.1:6379> sadd myset 1 2 3 foo foobar feelsgood
(integer) 6
127.0.0.1:6379> sscan myset 0 match f*
1) "0"
2) 1) "foo"
2) "feelsgood"
3) "foobar"
127.0.0.1:6379>对元素的模式匹配工作是在命令从数据集中取出元素之后, 向客户端返回元素之前的这段时间内进行的, 所以如果被迭代的数据集中只有少量元素和模式相匹配, 那么迭代命令或许会在多次执行中都不返回任何元素。例如:
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 127.0.0.1:6379> scan 0 MATCH *11*
1) "288"
2) 1) "key:911"
127.0.0.1:6379> scan 288 MATCH *11*
1) "224"
2) (empty list or set)
127.0.0.1:6379> scan 224 MATCH *11*
1) "80"
2) (empty list or set)
127.0.0.1:6379> scan 80 MATCH *11*
1) "176"
2) (empty list or set)
127.0.0.1:6379> scan 176 MATCH *11* COUNT 1000
1) "0"
2) 1) "key:611"
2) "key:711"
3) "key:118"
4) "key:117"
5) "key:311"
6) "key:112"
7) "key:111"
8) "key:110"
9) "key:113"
10) "key:211"
11) "key:411"
12) "key:115"
13) "key:116"
14) "key:114"
15) "key:119"
16) "key:811"
17) "key:511"
18) "key:11"
127.0.0.1:6379>我们可以看到, 以上的大部分迭代都不返回任何元素。
在最后一次迭代, 我们通过将
COUNT
选项的参数设置为1000
, 强制命令为本次迭代扫描更多元素, 从而使得命令返回的元素也变多了
语法:
1
SCAN cursor [MATCH pattern] [COUNT count]
参数说明:
- cursor - 游标。
- pattern - 匹配的模式。
- count - 指定从数据集里返回多少元素,默认值为 10 。
返回值:
数组列表
实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23使用 0 作为游标,开始新的迭代
127.0.0.1:6379> scan 0
1) "0"
2) 1) "favorite_animal"
2) "personal_computer"
3) "myotherkey"
4) "mykey1"
5) "animal"
使用的是第一次迭代时返回的游标 12 开始新的迭代
127.0.0.1:6379> scan 12
1) "0"
2) 1) "favorite_animal"
2) "personal_computer"
3) "myotherkey"
4) "mykey1"
5) "animal"
使用的是第一次迭代时返回的游标 3 开始新的迭代
127.0.0.1:6379> scan 3
1) "0"
2) 1) "myotherkey"
2) "mykey1"
3) "animal"
127.0.0.1:6379>
可用版本>= 2.8.0.
时间复杂度: O(1) for every call. O(N) for a complete iteration, including enough command calls for the cursor to return back to 0. N is the number of elements inside the collection.
1.1.17 TYPE key
Redis Type 命令用于返回 key 所储存的值的类型。
语法:
1
127.0.0.1:6379> TYPE KEY_NAME
返回值:
返回 key 的数据类型,数据类型有:
- none (key不存在)
- string (字符串)
- list (列表)
- set (集合)
- zset (有序集)
- hash (哈希表)
实例:
1
2
3
4
5
6
7
8
9
10
11
12
13127.0.0.1:6379> SET key1 "value"
OK
127.0.0.1:6379> LPUSH key2 "value"
(integer) 1
127.0.0.1:6379> SADD key3 "value"
(integer) 1
127.0.0.1:6379> TYPE key1
string
127.0.0.1:6379> TYPE key2
list
127.0.0.1:6379> TYPE key3
set
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(1)
1.1.18 MIGRATE host port key|\”\” destination-db timeout [COPY] [REPLACE] [AUTH password] [AUTH2 username password] [KEYS key [key …]]
将 key 原子性地从当前实例传送到目标实例的指定数据库上,一旦传送成功, key 会出现在目标实例上,而当前实例上的 key 会被删除。
MIGRATE 命令是一个原子操作,它在执行的时候会阻塞进行迁移的两个实例,直到以下任意结果发生:迁移成功,迁移失败,等待超时。
一次迁移多个 key:
Redis 3.0.6 起
MIGRATE
支持批量迁移。需要使用KEYS
选项,使用空字符串替换 key,要迁移的 key 列在KEYS
命令之后:1
MIGRATE 192.168.1.34 6379 "" 0 5000 KEYS key1 key2 key3
当所有 key 都不存在时返回
NOKEY
,即使只有一个key存在也执行成功。Options:
COPY
— 复制,不删除源实例中的 key。REPLACE
— 替换,替换目标实例中的存在的 key。KEYS
— 如果 key 参数是一个空字符串,会迁移 KEYS 命令后所有的 key 。AUTH
— 使用密码访问目标数据库。AUTH2
— 使用用户名和密码对访问数据库。 (Redis 6 以上 ACL auth )。
返回值:
字符串: 迁移成功时返回 OK ,如果在源实例中找不到 key 返回 NOKEY 。
可用版本>= 2.6.0.
时间复杂度: This command actually executes a DUMP+DEL in the source instance, and a RESTORE in the target instance. See the pages of these commands for time complexity. Also an O(N) data transfer between the two instances is performed.
1.2 String(字符串)
1.2.1 SET key value [EX seconds|PX milliseconds|KEEPTTL] [NX|XX] [GET]
Redis SET 命令用于设置给定 key 的值。如果 key 已经存储其他值, SET 就覆写旧值,且无视类型。
语法:
1
127.0.0.1:6379> SET KEY_NAME VALUE
返回值:
字符串: 如果
SET
命令正常执行那么回返回OK
多行字符串: 使用 GET 选项,返回 key 存储的值
空: key 不存在,否则如果加了
NX
或者XX
选项,SET
没执行,那么会返回nil。
实例:
1
2
3
4
5
6
7
8
9127.0.0.1:6379> SET mykey "Hello"
OK
127.0.0.1:6379> GET mykey
"Hello"
127.0.0.1:6379> SET anotherkey "will expire in a minute" EX 60
OK
127.0.0.1:6379> get anotherkey
"will expire in a minute"
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(1)
1.2.2 GET key
返回与键 key
相关联的字符串值,用于获取指定 key
的值。
如果键 key
不存在, 那么返回特殊值 nil
; 否则, 返回键 key
的值。
如果键 key
的值不是字符串类型, 那么返回一个错误, 因为 GET
命令只能用于字符串值。
返回值:
多行字符串: 返回key中存储的值,key 不存在是返回
nil
。实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14对不存在的 key 进行 GET
127.0.0.1:6379> GET nonexisting
(nil)
127.0.0.1:6379> SET mykey "Hello"
"OK"
对字符串类型 key 进行 GET
127.0.0.1:6379> GET mykey
"Hello"
对不是字符串类型的 key 进行 GET
127.0.0.1:6379> HSET myhash field1 "Hello"
(integer) 1
127.0.0.1:6379> GET myhash
ERR WRONGTYPE Operation against a key holding the wrong kind of value
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(1)
1.2.3 GETRANGE key start end
GETRANGE 命令返回存储在 key 中的字符串的子串,由 start 和 end 偏移决定(都包括在内)。负数偏移提供相对字符串结尾的偏移。所以, -1 表示最后一个字符, -2 表示倒数第二个字符,以此类推。
GETRANGE 通过将结果范围限制为字符串的实际长度来处理超出范围的请求。
Warning: GETRANGE 是改名而来,在 Redis2.0 以前版本叫做 SUBSTR 。
语法:
1
127.0.0.1:6379> GETRANGE KEY_NAME start end
返回值:
多行字符串:截取得到的子字符串。
实例:
1
2
3
4
5
6
7
8
9
10
11127.0.0.1:6379> SET mykey "This is a string yanpenggong"
OK
127.0.0.1:6379> GETRANGE mykey 0 3
"This"
127.0.0.1:6379> GETRANGE mykey -3 -1
"ong"
127.0.0.1:6379> GETRANGE mykey 0 -1
"This is a string yanpenggong"
127.0.0.1:6379> GETRANGE mykey 10 100
"string yanpenggong"
127.0.0.1:6379>
可用版本>= 2.4.0.
时间复杂度: O(N) where N is the length of the returned string. The complexity is ultimately determined by the returned length, but because creating a substring from an existing string is very cheap, it can be considered O(1) for small strings.
1.2.4 GETSET key value
将键 key
的值设为 value
, 并返回键 key
在被设置之前的旧值。
返回给定键 key
的旧值。
如果键 key
没有旧值, 也即是说, 键 key
在被设置之前并不存在, 那么命令返回 nil
。
当键 key
存在但不是字符串类型时, 命令返回一个错误。
语法:
1
127.0.0.1:6379> GETSET KEY_NAME VALUE
返回值:
返回给定 key 的旧值。 当 key 没有旧值时,即 key 不存在时,返回 nil 。
当 key 存在但不是字符串类型时,返回一个错误。
实例:
1
2
3
4
5
6
7
8
9
10
11没有旧值,返回 nil
127.0.0.1:6379> GETSET db redis
(nil)
127.0.0.1:6379> GET db
"redis"
返回旧值 redis
127.0.0.1:6379> GETSET db mongodb
"redis"
127.0.0.1:6379> GET db
"mongodb"
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(1)
1.2.5 GETBIT key offset
对 key
所储存的字符串值,获取指定偏移量上的位(bit)。
当 offset
比字符串值的长度大,或者 key
不存在时,返回 0
。
1.2.6 MGET key [key …]
Redis MGET 命令返回所有(一个或多个)给定 key 的值,值的类型是字符串。 如果给定的 key 里面,有某个 key 不存在或者值不是字符串,那么这个 key 返回特殊值 nil
。
语法:
1
127.0.0.1:6379> MGET KEY1 KEY2 .. KEYN
返回值:
数组: MGET 命令将返回一个列表, 列表中包含了所有给定键的值。
实例:
1
2
3
4
5
6
7
8
9127.0.0.1:6379> SET key1 "Hello"
OK
127.0.0.1:6379> SET key2 "World"
OK
127.0.0.1:6379> MGET key1 key2 nonexisting
1) "Hello"
2) "World"
3) (nil)
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(N) where N is the number of keys to retrieve.
1.2.7 SETBIT key offset value
Redis Setbit 命令用于对 key 所储存的字符串值,设置或清除指定偏移量上的位(bit)。
根据值 value 是 1 或 0 来决定设置或清除位 bit。当 key 不存在时会创建一个新的字符串。
当字符串不够长时,字符串的长度将增大,以确保它可以在offset位置存储值。
offset 参数需要大于等于0,并且小于 $2^{32}$ (bitmaps 最大 512MB)。
当值字符串变长时,添加的 bit 会被设置为 0。
注意: 当设置的是最后一位 bit (offset 等于 $2^{32} -1$),并且存储在 key 中的字符串还没有存储一个字符串值,或者存储的是一个短的字符串值时,Redis 需要分配所有的中间内存,这会阻塞 Redis 服务器一段时间。
在 2010 年的 MacBook Pro上:
- 设置 $2^{32} -1$ 位 (分配512MB内存) 需花费 300ms,
- 设置 $2^{30} -1$ 位 (分配 128MB 内存) 需花费 80m,
- 设置 $2^{28} -1$ 位 (分配 32MB 内存) 需花费 30ms,
- 设置 $2^{26} -1$ 位 (分配 8MB 内存) 需花费 8ms。
需要注意的是,一旦上面第一步内存分配被完成,对于同一个 key 接下来调用
SETBIT
将不会有分配内存开销。
语法:
1
127.0.0.1:6379> SETBIT key offset value
返回值:
整数: 存储在 offset 偏移位的原始值。
实例:
1
2
3
4
5
6
7
8127.0.0.1:6379> SETBIT bit 10086 1
(integer) 0
127.0.0.1:6379> GETBIT bit 10086
(integer) 1
bit 默认被初始化为 0
127.0.0.1:6379> GETBIT bit 100
(integer) 0
127.0.0.1:6379>
可用版本>= 2.2.0.
时间复杂度: O(1)
1.2.8 SETEX key seconds value
SETEX
命令将键 key
的值设置为 value
, 并将键 key
的生存时间设置为 seconds
秒钟。
如果键 key
已经存在, 那么 SETEX
命令将覆盖已有的值。
SETEX
命令的效果和以下两个命令的效果类似:
1 | 127.0.0.1:6379> SET mykey value |
SETEX
和这两个命令的不同之处在于 SETEX
是一个原子(atomic)操作, 它可以在同一时间内完成设置值和设置过期时间这两个操作, 因此 SETEX
命令在Redis用做缓存的时候非常实用。
语法:
1
127.0.0.1:6379> SETEX KEY_NAME TIMEOUT VALUE
返回值:
字符串:命令在设置成功时返回
OK
。 当seconds
参数不合法时, 命令将返回ERR ERR value is not an integer or out of range错误。实例:
1
2
3
4
5
6
7
8
9
10
11
12127.0.0.1:6379> SETEX mykey 10 "Hello"
OK
127.0.0.1:6379> TTL mykey
(integer) 9
127.0.0.1:6379> GET mykey
"Hello"
等几秒再看看输出
127.0.0.1:6379> TTL mykey
(integer) -2
127.0.0.1:6379> GET mykey
(nil)
127.0.0.1:6379>
可用版本>= 2.0.0.
时间复杂度: O(1)
1.2.9 SETNX key value
Redis Setnx( SET if Not exists )命令在指定的 key 不存在时,为 key 设置指定的值,这种情况下等同 SET
命令。当 key
存在时,什么也不做。
语法:
1
127.0.0.1:6379> SETNX KEY_NAME VALUE
返回值:
整数:
1
: 如果key被设置了0
: 如果key没有被设置
实例:
1
2
3
4
5
6
7
8
9
10
11
12
13mykey 不存在
127.0.0.1:6379> EXISTS mykey
(integer) 0
mykey 设置成功
127.0.0.1:6379> SETNX mykey "Hello"
(integer) 1
尝试覆盖,但是失败
127.0.0.1:6379> SETNX mykey "World"
(integer) 0
没有被覆盖
127.0.0.1:6379> GET mykey
"Hello"
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(1)
1.2.10 SETRANGE key offset value
SETRANGE
命令从偏移量 offset
开始, 用 value
参数覆盖键 key
储存的字符串值。
不存在的键 key
当作空白字符串处理。
SETRANGE
命令会确保字符串足够长以便将 value
设置到指定的偏移量上, 如果键 key
原来储存的字符串长度比偏移量小(比如字符串只有 5
个字符长,但你设置的 offset
是 10
), 那么原字符和偏移量之间的空白将用零字节(zerobytes, "\x00"
)进行填充。
因为 Redis 字符串的大小被限制在 512 兆(megabytes)以内, 所以用户能够使用的最大偏移量为 $2^{29}-1$(536870911) , 如果你需要使用比这更大的空间, 请使用多个 key
。
Warning: 当生成一个很长的字符串时, Redis 需要分配内存空间, 该操作有时候可能会造成服务器阻塞(block)。 在2010年出产的Macbook Pro上, 设置偏移量为 536870911(512MB 内存分配)将耗费约 300 毫秒, 设置偏移量为 134217728(128MB 内存分配)将耗费约 80 毫秒, 设置偏移量 33554432(32MB 内存分配)将耗费约 30 毫秒, 设置偏移量为 8388608(8MB 内存分配)将耗费约 8 毫秒。
语法:
1
127.0.0.1:6379>
返回值:
整数:
SETRANGE
命令会返回被修改之后, 字符串值的长度。实例:
1
2
3
4
5
6
7
8
9
10
11127.0.0.1:6379> SET key1 "Hello world"
OK
127.0.0.1:6379> SETRANGE key1 6 "Redis"
(integer) 11
127.0.0.1:6379> GET key1
"Hello Redis"
127.0.0.1:6379> SETRANGE key2 6 "Redis"
(integer) 11
127.0.0.1:6379> GET key2
"\x00\x00\x00\x00\x00\x00Redis"
127.0.0.1:6379>
可用版本>= 2.2.0.
时间复杂度: O(1), not counting the time taken to copy the new string in place. Usually, this string is very small so the amortized complexity is O(1). Otherwise, complexity is O(M) with M being the length of the value argument.
1.2.11 STRLEN key
Redis Strlen 命令用于获取指定 key 所储存的字符串值的长度。当 key 储存的不是字符串类型时,返回错误。
语法:
1
127.0.0.1:6379> STRLEN KEY_NAME
返回值:
整数: 字符串的长度,key 不存在时,返回 0 。
实例:
1
2
3
4
5
6
7
8
9获取字符串的长度
127.0.0.1:6379> SET mykey "Hello World"
OK
127.0.0.1:6379> STRLEN mykey
(integer) 11
不存在的 key 长度为 0
127.0.0.1:6379> STRLEN nonexisting
(integer) 0
127.0.0.1:6379>
可用版本>= 2.2.0.
时间复杂度: O(1)
1.2.12 MSET key value [key value …]
Redis MSET
命令设置多个 key
的值为各自对应的 value。
MSET
像 SET
一样,会用新值替换旧值。如果你不想覆盖旧值,可以使用 MSETNX
。
MSET
是原子操作,所有 key 的值同时设置。客户端不会看到有些 key
值被修改,而另一些 key
值没变。
语法:
1
127.0.0.1:6379> MSET key1 value1 key2 value2 .. keyN valueN
返回值:
字符串: 总是返回”OK”,因为
MSET
不会失败。实例:
1
2
3
4
5
6
7127.0.0.1:6379> MSET key1 "Hello" key2 "World"
OK
127.0.0.1:6379> GET key1
"Hello"
127.0.0.1:6379> GET key2
"World"
127.0.0.1:6379>
可用版本>= 1.0.1.
时间复杂度: O(N) where N is the number of keys to set.
1.2.13 MSETNX key value [key value …]
当且仅当所有给定键都不存在时, 为所有给定键设置值。
即使只有一个给定键已经存在, MSETNX 命令也会拒绝执行对所有键的设置操作。
MSETNX 是一个原子性(atomic)操作, 所有给定键要么就全部都被设置, 要么就全部都不设置。
MSETNX 可以用来设置逻辑对象的属性,来确保要么都设置,要么都不设置。
语法:
1
127.0.0.1:6379>
返回值:
整数:
1
: 当所有给定键都设置成功时0
: 某个给定键已经存在而导致设置未能成功
实例:
1
2
3
4
5
6
7
8
9127.0.0.1:6379> MSETNX key1 "Hello" key2 "there"
(integer) 1
127.0.0.1:6379> MSETNX key2 "new" key3 "world"
(integer) 0
127.0.0.1:6379> MGET key1 key2 key3
1) "Hello"
2) "there"
3) (nil)
127.0.0.1:6379>
可用版本>= 1.0.1.
时间复杂度: O(N) where N is the number of keys to set.
1.2.14 PSETEX key milliseconds value
PSETEX
命令和 SETEX
命令相似, 但它以毫秒为单位设置 key
的生存时间, 而不是像 SETEX 命令那样以秒为单位进行设置。
语法:
1
127.0.0.1:6379> PSETEX key milliseconds value
返回值:
设置成功时返回”OK”
实例:
1
2
3
4
5
6
7127.0.0.1:6379> PSETEX mykey 10000 "Hello"
OK
127.0.0.1:6379> PTTL mykey
(integer) 8171
127.0.0.1:6379> GET mykey
"Hello"
127.0.0.1:6379>
可用版本>= 2.6.0.
时间复杂度: O(1)
1.2.15 INCR key
Redis INCR
命令将 key 中储存的数字值增一。
如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR
操作。
如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误 ERR ERR hash value is not an integer。
本操作的值限制在 64 位(bit)有符号数字表示之内。
Note: 本质上这是一个字符串操作,因为Redis没有专门的整数类型。存储在 key 中的字符串被转换为十进制有符号整数,在此基础上加1。
语法:
1
127.0.0.1:6379> INCR KEY_NAME
返回值:
整数: 执行 INCR 命令之后 key 的值。
实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14127.0.0.1:6379> SET mykey "10"
OK
127.0.0.1:6379> INCR mykey
(integer) 11
127.0.0.1:6379> GET mykey
"11"
数字值在 Redis 中以字符串的形式保存
127.0.0.1:6379> SET mykey 20
OK
127.0.0.1:6379> INCR mykey
(integer) 21
127.0.0.1:6379> GET mykey
"21"
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(1)
1.2.16 INCRBY key increment
Redis INCRBY
命令将 key 中储存的数字加上指定的增量值。
如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCRBY 命令。
如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误 ERR ERR hash value is not an integer。
本操作的值限制在 64 位(bit)有符号数字表示之内。
关于递增(increment) / 递减(decrement)操作的更多信息, 请参见 INCR
命令的文档。
语法:
1
127.0.0.1:6379> INCRBY key increment
返回值:
整数: 命令执行之后 key 中 存储的值。
实例:
1
2
3
4
5127.0.0.1:6379> SET mykey "10"
OK
127.0.0.1:6379> INCRBY mykey 5
(integer) 15
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(1)
1.2.17 INCRBYFLOAT key increment
为键 key
中储存的值加上浮点数增量 increment
,key 中的浮点数是以字符串形式存储的。
如果键 key
不存在, 那么 INCRBYFLOAT
会先将键 key
的值设为 0
, 然后再执行加法操作。
如果命令执行成功, 那么键 key
的值会被更新为执行加法计算之后的新值, 并且新值会以字符串的形式返回给调用者。
无论是键 key
的值还是增量 increment
, 都可以使用像 2.0e7
、 3e5
、 90e-2
那样的指数符号(exponential notation)来表示, 但是, 执行 INCRBYFLOAT 命令之后的值总是以同样的形式储存, 也即是, 它们总是由一个数字, 一个(可选的)小数点和一个任意长度的小数部分组成(比如 3.14
、 69.768
,诸如此类), 小数部分尾随的 0
会被移除, 如果可能的话, 命令还会将浮点数转换为整数(比如 3.0
会被保存成 3
)。
此外, 无论加法计算所得的浮点数的实际精度有多长, INCRBYFLOAT
命令的计算结果最多只保留小数点的后十七位。
当以下任意一个条件发生时, 命令返回一个错误:
- 键
key
的值不是字符串类型(因为 Redis 中的数字和浮点数都以字符串的形式保存,所以它们都属于字符串类型); 键
key
当前的值或者给定的增量increment
不能被解释(parse)为双精度浮点数。语法:
1
127.0.0.1:6379> INCRBYFLOAT key increment
返回值:
多行字符串: 在加上增量 increment 之后, 键 key 的值。
实例:
1
2
3
4
5
6
7
8
9
10
11127.0.0.1:6379> SET mykey 10.50
OK
127.0.0.1:6379> INCRBYFLOAT mykey 0.1
"10.6"
127.0.0.1:6379> INCRBYFLOAT mykey -5
"5.6"
127.0.0.1:6379> SET mykey 5.0e3
OK
127.0.0.1:6379> INCRBYFLOAT mykey 2.0e2
"5200"
127.0.0.1:6379>实现细节
INCR 命令族主要用在复制和 AOF 文件中,用来当做 SET,减少源 SET 命令个数,浮点的实现差异不会是不一致的来源。
可用版本>= 2.6.0.
时间复杂度: O(1)
1.2.18 DECR key
为键 key
储存的数字值减去一。
如果键 key
不存在, 那么键 key
的值会先被初始化为 0
, 然后再执行 DECR
操作。
如果键 key
储存的值不能被解释为数字, 那么 DECR
命令将返回一个错误。
本操作的值限制在 64 位(bit)有符号数字表示之内。
语法:
1
127.0.0.1:6379> DECR key
返回值:
整数: 执行操作之后key中的值
实例:
1
2
3
4
5
6
7
8
9127.0.0.1:6379> SET mykey "10"
OK
127.0.0.1:6379> DECR mykey
(integer) 9
127.0.0.1:6379> SET mykey "13621873621786345326"
OK
127.0.0.1:6379> DECR mykey
(error) ERR value is not an integer or out of range
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(1)
1.2.19 DECRBY key decrement
将键 key 储存的整数值减去减量 decrement 。
如果键 key 不存在, 那么键 key 的值会先被初始化为 0 , 然后再执行 DECRBY
命令。
如果键 key 储存的值不能被解释为数字, 那么 DECRBY
命令将返回一个错误。
本操作的值限制在 64 位(bit)有符号数字表示之内。
关于更多递增(increment) / 递减(decrement)操作的更多信息, 请参见 INCR
命令的文档。
语法:
1
127.0.0.1:6379>
返回值:
整数:
DECRBY
命令会返回键在执行减法操作之后的值。实例:
1
2
3
4
5127.0.0.1:6379> SET mykey "10"
OK
127.0.0.1:6379> DECRBY mykey 3
(integer) 7
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(1)
1.2.20 APPEND key value
Redis APPEND 命令用于为指定的 key 追加值。
如果 key 已经存在并且是一个字符串, APPEND
命令将 value 追加到 key 原来的值的末尾。
如果 key 不存在, APPEND
就简单地将给定 key 设为 value ,就像执行 SET key value
一样。
语法:
1
127.0.0.1:6379> APPEND KEY_NAME NEW_VALUE
返回值:
整数: 追加指定值之后, key 中字符串的长度。
实例:
1
2
3
4
5
6
7
8
9
10
11
12确保 myphone 不存在
127.0.0.1:6379> EXISTS myphone
(integer) 0
对不存在的key 进行APPEND,等同于 SET myphone "nokia"
127.0.0.1:6379> APPEND myphone "nokia"
(integer) 5
对已存在的字符串进行 APPEND。长度从5个字符串增加到11个字符串
127.0.0.1:6379> APPEND myphone " - 222"
(integer) 11
127.0.0.1:6379> GET myphone
"nokia - 222"
127.0.0.1:6379>
可用版本>= 2.0.0.
时间复杂度: O(1). The amortized time complexity is O(1) assuming the appended value is small and the already present value is of any size, since the dynamic string library used by Redis will double the free space available on every reallocation.
1.3 Hash(哈希表)
1.3.1 HDEL key field [field …]
Redis HDEL
命令用于删除哈希表 key 中的一个或多个指定字段,不存在的字段将被忽略。 如果 key
粗存在,会被当作空哈希表处理并返回 0
。
语法:
1
127.0.0.1:6379> HDEL KEY_NAME FIELD1.. FIELDN
返回值:
整数: 被成功删除字段的数量,不包括被忽略的字段。
实例:
1
2
3
4
5
6
7127.0.0.1:6379> HSET myhash field1 "foo"
(integer) 1
127.0.0.1:6379> HDEL myhash field1
(integer) 1
127.0.0.1:6379> HDEL myhash field2
(integer) 0
127.0.0.1:6379>
可用版本>= 2.0.0.
时间复杂度: O(N) where N is the number of fields to be removed.
1.3.2 HEXISTS key field
Redis Hexists 命令用于查看哈希表的指定字段field
是否存在。
语法:
1
127.0.0.1:6379> HEXISTS KEY_NAME FIELD_NAME
返回值:
整数, specifically:
1
哈希表含有给定字段field
。0
哈希表不含有给定字段,或 key 不存在。
实例:
1
2
3
4
5
6
7127.0.0.1:6379> HSET myhash field1 "foo"
(integer) 1
127.0.0.1:6379> HEXISTS myhash field1
(integer) 1
127.0.0.1:6379> HEXISTS myhash field2
(integer) 0
127.0.0.1:6379>
可用版本>= 2.0.0.
时间复杂度: O(1)
1.3.3 HGET key field
Redis HGET 命令用于返回哈希表中指定字段 field 的值。
语法:
1
127.0.0.1:6379> HGET KEY_NAME FIELD_NAME
返回值:
多行字符串: 返回给定字段的值。如果给定的字段或 key 不存在时,返回 nil 。
实例:
1
2
3
4
5
6
7
8
9127.0.0.1:6379> HSET myhash field1 "foo"
(integer) 1
字段存在
127.0.0.1:6379> HGET myhash field1
"foo"
字段不存在
127.0.0.1:6379> HGET myhash field2
(nil)
127.0.0.1:6379>
可用版本>= 2.0.0.
时间复杂度: O(1)
1.3.4 HGETALL key
Redis HGETALL
命令用于返回存储在 key
中的哈希表中所有的域和值。
在返回值里,紧跟每个域(field name)之后是域的值(value),所以返回值的长度是哈希表大小的两倍。
语法:
1
127.0.0.1:6379> HGETALL KEY_NAME
返回值:
数组: 以列表形式返回哈希表的字段及字段值。 若 key 不存在,返回空列表。
实例:
1
2
3
4
5
6
7
8
9
10127.0.0.1:6379> HSET myhash field1 "Hello"
(integer) 1
127.0.0.1:6379> HSET myhash field2 "World"
(integer) 1
127.0.0.1:6379> HGETALL myhash
1) "field1"
2) "Hello"
3) "field2"
4) "World"
127.0.0.1:6379>
可用版本>= 2.0.0.
时间复杂度: O(N) where N is the size of the hash.
1.3.5 HINCRBY key field increment
为哈希表 key
中的域 field
的值加上增量 increment
。
增量也可以为负数,相当于对给定域进行减法操作。
如果 key
不存在,一个新的哈希表被创建并执行 HINCRBY
命令。
如果域 field
不存在,那么在执行命令前,域的值被初始化为 0
。
对一个储存字符串值的域 field
执行 HINCRBY
命令将造成一个错误 ERR ERR hash value is not an integer。
本操作的值被限制在 64 位(bit)有符号数字表示之内。
语法:
1
127.0.0.1:6379> HINCRBY KEY_NAME FIELD_NAME INCR_BY_NUMBER
返回值:
整数: 执行 HINCRBY 命令之后,哈希表 key 中域 field 的值。
实例:
1
2
3
4
5
6
7
8
9127.0.0.1:6379> HSET myhash field 5
(integer) 1
127.0.0.1:6379> HINCRBY myhash field 1
(integer) 6
127.0.0.1:6379> HINCRBY myhash field -1
(integer) 5
127.0.0.1:6379> HINCRBY myhash field -10
(integer) -5
127.0.0.1:6379>
可用版本>= 2.0.0.
时间复杂度: O(1)
1.3.6 HINCRBYFLOAT key field increment
为哈希表 key
中的域 field
加上浮点数增量 increment
。
如果哈希表中没有域 field
,那么 INCRBYFLOAT 会先将域 field
的值设为 0
,然后再执行加法操作。
如果键 key
不存在,那么 INCRBYFLOAT 会先创建一个哈希表,再创建域 field
,最后再执行加法操作。
当以下任意一个条件发生时,返回一个错误:
- 域
field
的值不是字符串类型(因为 redis 中的数字和浮点数都以字符串的形式保存,所以它们都属于字符串类型)- 域
field
当前的值或给定的增量increment
不能解释(parse)为双精度浮点数(double precision floating point number)命令的详细功能和
INCRBYFLOAT
命令类似,请查看INCRBYFLOAT
命令获取更多相关信息。
语法:
1
127.0.0.1:6379> HINCRBYFLOAT key field increment
返回值:
多行字符串: 执行加法操作之后 field 域的值
实例:
1
2
3
4
5
6
7
8
9
10
11127.0.0.1:6379> HSET myhash field 10.50
(integer) 1
127.0.0.1:6379> HINCRBYFLOAT myhash field 0.1
"10.6"
127.0.0.1:6379> HINCRBYFLOAT myhash field -5
"5.6"
127.0.0.1:6379> HSET myhash field 5.0e3
(integer) 0
127.0.0.1:6379> HINCRBYFLOAT myhash field 2.0e2
"5200"
127.0.0.1:6379>
可用版本>= 2.6.0.
时间复杂度: O(1)
1.3.7 HKEYS key
HKEYS 返回存储在 key 中哈希表的所有域。
语法:
1
127.0.0.1:6379> HKEYS key
返回值:
数组: 包含哈希表中所有域的表。当 key 不存在时,返回空表。
实例:
1
2
3
4
5
6
7
8127.0.0.1:6379> HSET myhash field1 "Hello"
(integer) 1
127.0.0.1:6379> HSET myhash field2 "World"
(integer) 1
127.0.0.1:6379> HKEYS myhash
1) "field1"
2) "field2"
127.0.0.1:6379>
可用版本>= 2.0.0.
时间复杂度: O(N) where N is the size of the hash.
1.3.8 HLEN key
Redis HLEN 命令用于获取哈希表中字段(fields)的数量。
语法:
1
127.0.0.1:6379> HLEN key
返回值:
整数: 哈希表中字段的数量。 当 key 不存在时,返回 0 。
实例:
1
2
3
4
5
6
7127.0.0.1:6379> HSET myhash field1 "Hello"
(integer) 1
127.0.0.1:6379> HSET myhash field2 "World"
(integer) 1
127.0.0.1:6379> HLEN myhash
(integer) 2
127.0.0.1:6379>
可用版本>= 2.0.0.
时间复杂度: O(1)
1.3.9 HMGET key field [field …]
Redis HMGET 命令用于返回哈希表中,一个或多个给定字段(field)的值。
如果指定的字段(field)不存在于哈希表或者 key 不存在,那么返回一个 nil 值。
语法:
1
127.0.0.1:6379> HMGET key field [field ...]
返回值:
数组: 返回要查询的field对应值的列表,值的顺序field在命令中出现的顺序排列。
实例:
1
2
3
4
5
6
7
8
9127.0.0.1:6379> HSET myhash field1 "Hello"
(integer) 1
127.0.0.1:6379> HSET myhash field2 "World"
(integer) 1
127.0.0.1:6379> HMGET myhash field1 field2 nofield
1) "Hello"
2) "World"
3) (nil)
127.0.0.1:6379>
可用版本>= 2.0.0.
时间复杂度: O(N) where N is the number of fields being requested.
1.3.10 HMSET key field value [field value …]
Redis HMSET 命令用于同时将多个 field-value (字段-值)对设置到哈希表中。
此命令会覆盖哈希表中已存在的字段。
如果哈希表不存在,会创建一个空哈希表,并执行 HMSET 操作。
Redis 4.0.0起,HMSET 被废弃,请使用 HSET 代替。
语法:
1
127.0.0.1:6379> HMSET key field value [field value ...]
返回值:
字符串
实例:
1
2
3
4
5
6
7127.0.0.1:6379> HMSET myhash field1 "Hello" field2 "World"
OK
127.0.0.1:6379> HGET myhash field1
"Hello"
127.0.0.1:6379> HGET myhash field2
"World"
127.0.0.1:6379>
可用版本>= 2.0.0.
时间复杂度: O(N) where N is the number of fields being set.
1.3.11 HSET key field value [field value …]
语法:
1
127.0.0.1:6379> HSET key field value [field value ...]
返回值:
整数: 被修改或增加的
field
个数。实例:
1
2
3
4
5127.0.0.1:6379> HSET myhash field1 "Hello"
(integer) 1
127.0.0.1:6379> HGET myhash field1
"Hello"
127.0.0.1:6379>
可用版本>= 2.0.0.
时间复杂度: O(1) for each field/value pair added, so O(N) to add N field/value pairs when the command is called with multiple field/value pairs.
1.3.12 HSETNX key field value
Redis HSETNX 命令用于为哈希表中不存在的字段赋值 。
如果字段已经存在于哈希表中,操作无效。
如果 key 不存在,一个新哈希表被创建并执行 HSETNX 命令。
语法:
1
127.0.0.1:6379> HSETNX key field value
返回值:
整数:
1
field
设置成功。0
field
已存在,设置失败。
实例:
1
2
3
4
5
6
7127.0.0.1:6379> HSETNX myhash field "Hello"
(integer) 1
127.0.0.1:6379> HSETNX myhash field "World"
(integer) 0
127.0.0.1:6379> HGET myhash field
"Hello"
127.0.0.1:6379>
可用版本>= 2.0.0.
时间复杂度: O(1)
1.3.13 HVALS key
Redis HVALS 命令返回哈希表所有域(field)的值。
语法:
1
127.0.0.1:6379> HVALS key
返回值:
数组: 返回哈希表中所有域(field)值的列表。 当 key 不存在时,返回空表。 not exist.
实例:
1
2
3
4
5
6
7127.0.0.1:6379> HSET myhash field1 "Hello"
(integer) 1
127.0.0.1:6379> HSET myhash field2 "World"
(integer) 1
127.0.0.1:6379> HVALS myhash
1) "Hello"
2) "World"
可用版本>= 2.0.0.
时间复杂度: O(N) where N is the size of the hash.
1.3.14 HSCAN key cursor [MATCH pattern] [COUNT count]
Redis HSCAN 命令用于遍历哈希表中的键值对。
语法:
1
127.0.0.1:6379> HSCAN key cursor [MATCH pattern] [COUNT count]
参数说明:
- cursor: 游标。
- pattern: 匹配的模式。
- count: 指定从数据集里返回多少元素,默认值为 10 。
返回值:
返回的每个元素都是一个元组,每一个元组元素由一个字段(field) 和值(value)组成。
实例:
1
2
3
4
5
6
7127.0.0.1:6379> HMSET sites google "google.com" kungs "yanpenggong" weibo "weibo.com" 8 "alibaba.com"
OK
127.0.0.1:6379> HSCAN sites 0 match "goog*"
1) "0"
2) 1) "google"
2) "google.com"
127.0.0.1:6379>
可用版本>= 2.8.0.
时间复杂度: O(1) for every call. O(N) for a complete iteration, including enough command calls for the cursor to return back to 0. N is the number of elements inside the collection..
1.3.15 HSTRLEN key field
Redis HSTRLEN 命令返回存储在 key
中的哈希表里, 与给定域 field
相关联的值的字符串长度(string length)。
如果给定的键或者域不存在, 那么命令返回 0
。
语法:
1
127.0.0.1:6379> HSTRLEN key field
返回值:
整数: 值的字符串长度,key 或 field 不存在时返回 0。
实例:
1
2
3
4
5
6
7
8
9127.0.0.1:6379> HMSET myhash f1 HelloWorld f2 88 f3 -516
OK
127.0.0.1:6379> HSTRLEN myhash f1
(integer) 10
127.0.0.1:6379> HSTRLEN myhash f2
(integer) 2
127.0.0.1:6379> HSTRLEN myhash f3
(integer) 4
127.0.0.1:6379>
可用版本>= 3.2.0.
时间复杂度: O(1)
1.4 List(列表)
1.4.1 BLPOP key [key …] timeout
Redis BLPOP 命令移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。它是 LPOP 的阻塞版本。
当给定多个 key 参数时,按参数 key 的先后顺序依次检查各个列表,弹出第一个非空列表的头元素。
语法:
1
127.0.0.1:6379> BLPOP LIST1 LIST2 .. LISTN TIMEOUT
返回值:
数组:
- 如果列表为空或超时,返回一个
nil
。 - 返回一个含有两个元素的列表,第一个元素是被弹出元素所属的 key ,第二个元素是被弹出元素的值。
- 如果列表为空或超时,返回一个
实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20127.0.0.1:6379> DEL list1 list2
(integer) 1
127.0.0.1:6379> RPUSH list1 a b c
(integer) 3
127.0.0.1:6379> BLPOP list1 list2 0
1) "list1"
2) "a"
127.0.0.1:6379> BLPOP list1 10
1) "list1"
2) "b"
127.0.0.1:6379> BLPOP list1 10
1) "list1"
2) "c"
127.0.0.1:6379> BLPOP list1 10
(nil)
(10.08s)
127.0.0.1:6379> BLPOP list2 10
(nil)
(10.07s)
127.0.0.1:6379>在实例中,操作会被阻塞,如果指定的列表 key list2 存在数据则会返回第一个元素,否则在等待10秒后会返回 nil 。
可用版本>= 2.0.0.
时间复杂度: O(1)
1.4.2 BRPOP key [key …] timeout
BRPOP 是阻塞列表的移除原语。从给的列表参数中按顺序检查第一个不空的列表,然后从该列表的尾部移除元素。 BRPOP 是 RPOP 的阻塞版本,因为当没有元素从给定的列表中移除的时候,BRPOP 阻塞连接。
参考 BLPOP documentation 了解更多信息,因为 BRPOP 和 BLPOP 的功能是相同的,除了他们一个是从列表头部(左边),另一个是从列表尾部(右边)移除元素。
语法:
1
127.0.0.1:6379> BRPOP LIST1 LIST2 .. LISTN TIMEOUT
返回值:
数组:
- 所有列表为空并且超时时,返回
nil
。 - 一个两个成员的数组,第一个元素是被移除元素的key的名字,第二个元素是被移除元素的值。
- 所有列表为空并且超时时,返回
实例:
1
2
3
4
5
6
7
8127.0.0.1:6379> DEL list1 list2
Error: Broken pipe
127.0.0.1:6379> RPUSH list1 a b c
(integer) 3
127.0.0.1:6379> BRPOP list1 list2 0
1) "list1"
2) "c"
127.0.0.1:6379>
可用版本>= 2.0.0.
时间复杂度: O(1)
1.4.3 BRPOPLPUSH source destination timeout
Redis BRPOPLPUSH 命令从列表中取出最后一个元素,并插入到另外一个列表的头部; 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
BRPOPLPUSH 是 RPOPLPUSH
的阻塞版本,当给定列表 source
不为空时, BRPOPLPUSH
的表现和 RPOPLPUSH 一样。
超时参数 timeout
接受一个以秒为单位的数字作为值。超时参数设为 0 表示阻塞时间可以无限期延长(block indefinitely) 。
从 Redis 6.2.0 起,建议使用 BLMOVE
替代 BRPOPLPUSH
。
语法:
1
127.0.0.1:6379> BRPOPLPUSH LIST1 ANOTHER_LIST TIMEOUT
返回值:
多行字符串: 假如在指定时间内没有任何元素被弹出,则返回一个 nil 和等待时长。 反之,返回一个含有两个元素的列表,第一个元素是被弹出元素的值,第二个元素是等待时长。
实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15127.0.0.1:6379> RPUSH msg "hello yanpenggong"
(integer) 1
127.0.0.1:6379> BRPOPLPUSH msg reciver 10
"hello yanpenggong"
127.0.0.1:6379> LLEN reciver
(integer) 1
127.0.0.1:6379> LRANGE reciver 0 0
1) "hello yanpenggong"
空列表
127.0.0.1:6379> RPOP msg
(nil)
127.0.0.1:6379> BRPOPLPUSH msg reciver 10
(nil)
(10.05s)
127.0.0.1:6379>
可用版本>= 2.2.0.
时间复杂度: O(1)
1.4.4 LINDEX key index
LINDEX 返回列表 key 里索引 index 位置存储的元素。
index 下标是从 0 开始索引的,所以 0 是表示第一个元素, 1 表示第二个元素,并以此类推。
负数索引用于指定从列表尾部开始索引的元素,在这种方法下,-1 表示最后一个元素,-2 表示倒数第二个元素,并以此往前推。
当 key 值不是列表的时候,会返回错误。
语法:
1
127.0.0.1:6379> LINDEX key index
返回值:
多行字符串: 查询的元素,
index
超出索引范围时返回nil
。实例:
1
2
3
4
5
6
7
8
9
10
11127.0.0.1:6379> LPUSH mylist "World"
(integer) 1
127.0.0.1:6379> LPUSH mylist "Hello"
(integer) 2
127.0.0.1:6379> LINDEX mylist 0
"Hello"
127.0.0.1:6379> LINDEX mylist -1
"World"
127.0.0.1:6379> LINDEX mylist 3
(nil)
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(N) where N is the number of elements to traverse to get to the element at index. This makes asking for the first or the last element of the list O(1).
1.4.5 LINSERT key BEFORE|AFTER pivot element
Redis LINSERT 用于把 element
插入到列表 key
中,参考值 pivot 的前面或后面。
当 key
不存在时,这个list会被看作是空list,什么都不执行。
当 key
存在,值不是列表类型时,返回错误。
语法:
1
127.0.0.1:6379> LINSERT key BEFORE|AFTER pivot element
返回值:
整数: 执行操作后的列表长度,列表中
pivot
参考值不存在的时候返回-1
。实例:
1
2
3
4
5
6
7
8
9
10
11127.0.0.1:6379> RPUSH mylist "Hello"
(integer) 1
127.0.0.1:6379> RPUSH mylist "World"
(integer) 2
127.0.0.1:6379> LINSERT mylist BEFORE "World" "There"
(integer) 3
127.0.0.1:6379> LRANGE mylist 0 -1
1) "Hello"
2) "There"
3) "World"
127.0.0.1:6379>
可用版本>= 2.2.0.
时间复杂度: O(N) where N is the number of elements to traverse before seeing the value pivot. This means that inserting somewhere on the left end on the list (head) can be considered O(1) and inserting somewhere on the right end (tail) is O(N).
1.4.6 LLEN key
Redis LLEN 用于返回存储在 key
中的列表长度。 如果 key
不存在,则 key
被解释为一个空列表,返回 0
。 如果 key
不是列表类型,返回一个错误。
语法:
1
127.0.0.1:6379> LLEN KEY_NAME
返回值:
整数: 列表的长度。
实例:
1
2
3
4
5
6
7
8
9
10
11127.0.0.1:6379> LRANGE mylist 0 -1
(empty array)
127.0.0.1:6379> LPUSH mylist "World"
(integer) 1
127.0.0.1:6379> LPUSH mylist "Hello"
(integer) 2
127.0.0.1:6379> LPUSH mylist "yanpenggong"
(integer) 3
127.0.0.1:6379> LLEN mylist
(integer) 3
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(1)
1.4.7 LPOP key
Redis LPOP 命令用于删除并返回存储在 key
中的列表的第一个元素。
语法:
1
127.0.0.1:6379> LPOP key
返回值:
多行字符串: 列表的首元素,
key
不存在的时候返回nil
。实例:
1
2
3
4
5
6
7
8
9
10
11
12127.0.0.1:6379> RPUSH mylist "one"
(integer) 1
127.0.0.1:6379> RPUSH mylist "two"
(integer) 2
127.0.0.1:6379> RPUSH mylist "three"
(integer) 3
127.0.0.1:6379> LPOP mylist
"one"
127.0.0.1:6379> LRANGE mylist 0 -1
1) "two"
2) "three"
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(1)
1.4.8 LPUSH key element [element …]
redis LPUSH 用于将一个或多个值插入到列表key
的头部。
如果 key 不存在,那么在进行 push 操作前会创建一个空列表。
如果 key 对应的值不是 list 类型,那么会返回一个错误。
可以使用一个命令把多个元素 push 进入列表,只需在命令末尾加上多个指定的参数。
元素按在参数中出现的顺序,从左到右依次插入到 list 的头部。
所以对于这个命令例子 LPUSH mylist a b c
,返回的列表是 c 为第一个元素, b 为第二个元素, a 为第三个元素。
语法:
1
127.0.0.1:6379> LPUSH KEY_NAME VALUE1.. VALUEN
返回值:
整数: 执行push操作后列表的长度。
实例:
1
2
3
4
5
6
7
8127.0.0.1:6379> LPUSH mylist "world"
(integer) 1
127.0.0.1:6379> LPUSH mylist "Hello"
(integer) 2
127.0.0.1:6379> LRANGE mylist 0 -1
1) "Hello"
2) "world"
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(1) for each element added, so O(N) to add N elements when the command is called with multiple arguments.
1.4.9 LPUSHX key element [element …]
Redis LPUSHX 在当 key 存在并且存储着一个 list 类型值的时候,向值 list 的头部插入 value。 与 LPUSH 相反,当 key 不存在的时候不会进行任何操作。
语法:
1
127.0.0.1:6379> LPUSHX KEY_NAME VALUE1.. VALUEN
返回值:
整数: 执行push操作后列表list的长度。
实例:
1
2
3
4
5
6
7
8
9
10
11
12
13127.0.0.1:6379> LPUSH mylist "world" "Hello"
(integer) 2
127.0.0.1:6379> LPUSHX mylist "kungs"
(integer) 3
127.0.0.1:6379> LPUSHX mylist1 "kungs"
(integer) 0
127.0.0.1:6379> LRANGE mylist 0 -1
1) "kungs"
2) "Hello"
3) "world"
127.0.0.1:6379> LRANGE mylist1 0 -1
(empty array)
127.0.0.1:6379>
可用版本>= 2.2.0.
时间复杂度: O(1) for each element added, so O(N) to add N elements when the command is called with multiple arguments.
1.4.10 LRANGE key start stop
Redis LRANGE 用于返回列表中指定区间内的元素,区间以偏移量 START 和 END 指定。
其中 0 表示列表的第一个元素, 1 表示列表的第二个元素,以此类推。
你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。
语法:
1
127.0.0.1:6379> LRANGE KEY_NAME START END
返回值:
数组: 一个列表,包含指定区间内的元素。
实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19127.0.0.1:6379> RPUSH mylist "one"
(integer) 1
127.0.0.1:6379> RPUSH mylist "two"
(integer) 2
127.0.0.1:6379> RPUSH mylist "three"
(integer) 3
127.0.0.1:6379> LRANGE mylist 0 0
1) "one"
127.0.0.1:6379> LRANGE mylist -3 2
1) "one"
2) "two"
3) "three"
127.0.0.1:6379> LRANGE mylist -100 100
1) "one"
2) "two"
3) "three"
127.0.0.1:6379> LRANGE mylist 5 10
(empty array)
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(S+N) where S is the distance of start offset from HEAD for small lists, from nearest end (HEAD or TAIL) for large lists; and N is the number of elements in the specified range.
1.4.11 LREM key count element
Redis LREM 用于从列表 key 中删除前 count 个值等于 element 的元素。 这个 count 参数通过下面几种方式影响这个操作:
1 | count > 0: 从头到尾删除值为 value 的元素。 |
比如, LREM list -2 "hello"
会从列表key中删除最后两个出现的 “hello”。
需要注意的是,不存在key会被当作空list处理,所以当 key 不存在的时候,这个命令会返回 0。
语法:
1
127.0.0.1:6379> LREM key count VALUE
返回值:
整数: 删除元素个数。
实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14127.0.0.1:6379> RPUSH mylist "Hello"
(integer) 1
127.0.0.1:6379> RPUSH mylist "Hello"
(integer) 2
127.0.0.1:6379> RPUSH mylist "World"
(integer) 3
127.0.0.1:6379> RPUSH mylist "Hello"
(integer) 4
127.0.0.1:6379> LREM mylist -2 "Hello"
(integer) 2
127.0.0.1:6379> LRANGE mylist 0 -1
1) "Hello"
2) "World"
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(N+M) where N is the length of the list and M is the number of elements removed.
1.4.12 LSET key index element
Redis LSET 用于设置列表 key 中 index 位置的元素值为 element
。 更多关于 index 参数的信息,详见 LINDEX。
当 index 超出列表索引范围时会返回错误ERR ERR index out of range
。
语法:
1
127.0.0.1:6379> LSET KEY_NAME INDEX VALUE
返回值:
字符串: 操作成功返回 ok ,否则返回错误信息。
实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15127.0.0.1:6379> RPUSH mylist "one"
(integer) 1
127.0.0.1:6379> RPUSH mylist "two"
(integer) 2
127.0.0.1:6379> RPUSH mylist "three"
(integer) 3
127.0.0.1:6379> LSET mylist 0 "four"
OK
127.0.0.1:6379> LSET mylist -2 "five"
OK
127.0.0.1:6379> LRANGE mylist 0 -1
1) "four"
2) "five"
3) "three"
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(N) where N is the length of the list. Setting either the first or the last element of the list is O(1).
1.4.13 LTRIM key start stop
Redis Ltrim 对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。
start 和 stop 都是由0开始计数的, 这里的 0 是列表里的第一个元素(表头),1 是第二个元素,以此类推。
start 和 end 也可以用负数来表示与表尾的偏移量,比如 -1 表示列表里的最后一个元素, -2 表示倒数第二个,等等。
超过范围的下标并不会产生错误:如果 start 超过列表尾部,或者 start > end,结果会是列表变成空表(即该 key 会被移除)。 如果 end 超过列表尾部,Redis 会将其当作列表的最后一个元素。
语法:
1
127.0.0.1:6379> LTRIM KEY_NAME START STOP
返回值:
字符串: 命令执行成功时,返回 ok 。
实例:
1
2
3
4
5
6
7
8
9
10
11
12127.0.0.1:6379> RPUSH mylist "one"
(integer) 1
127.0.0.1:6379> RPUSH mylist "two"
(integer) 2
127.0.0.1:6379> RPUSH mylist "three"
(integer) 3
127.0.0.1:6379> LTRIM mylist 1 -1
OK
127.0.0.1:6379> LRANGE mylist 0 -1
1) "two"
2) "three"
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(N) where N is the number of elements to be removed by the operation.
1.4.14 RPOP key
Redis RPOP 用于移除并返回列表 key
的最后一个元素。
语法:
1
127.0.0.1:6379> RPOP KEY_NAME
返回值:
多行字符串: 最后一个元素的值,
key
不存在时返回nil
。实例:
1
2
3
4
5
6
7
8
9
10
11
12127.0.0.1:6379> RPUSH mylist "one"
(integer) 1
127.0.0.1:6379> RPUSH mylist "two"
(integer) 2
127.0.0.1:6379> RPUSH mylist "three"
(integer) 3
127.0.0.1:6379> RPOP mylist
"three"
127.0.0.1:6379> LRANGE mylist 0 -1
1) "one"
2) "two"
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(1)
1.4.15 RPOPLPUSH source destination
用于原子地从列表 source
中移除并返回最后一个元素,然后把这个元素插入为列表destination
的第一个元素。
例如: 假设 source
列表成员为 a,b,c
,列表 destination
成员为 x,y,z
。
执行 RPOPLPUSH source destination
的结果是列表 source
成员为a,b
,列表 destination
成员为c,x,y,z
。
如果列表 source
不存在,返回 nil
,什么也不执行。
如果列表 source
和destination
相同,相当于从列表的一端删除元素,在放入列表的另一端,所以可以当做一个列表循环命令。
LMOVE
用来替换废弃的指令 RPOPLPUSH
,相当于执行LMOVE RIGHT LEFT
。
从 Redis 6.2.0起, RPOPLPUSH 被废弃,使用 LMOVE替代。
语法:
1
127.0.0.1:6379> RPOPLPUSH SOURCE_KEY_NAME DESTINATION_KEY_NAME
返回值:
多行字符串: 移除并又插入的元素。
实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14127.0.0.1:6379> RPUSH mylist "one"
(integer) 1
127.0.0.1:6379> RPUSH mylist "two"
(integer) 2
127.0.0.1:6379> RPUSH mylist "three"
(integer) 3
127.0.0.1:6379> RPOPLPUSH mylist myotherlist
"three"
127.0.0.1:6379> LRANGE mylist 0 -1
1) "one"
2) "two"
127.0.0.1:6379> LRANGE myotherlist 0 -1
1) "three"
127.0.0.1:6379>
可用版本>= 1.2.0.
时间复杂度: O(1)
1.4.16 RPUSH key element [element …]
RPUSH 向存存储在 key 中的列表的尾部插入所有指定的值。如果 key 不存在,那么会创建一个空的列表然后再进行 push 操作。 当 key 保存的不是列表,那么会返回一个错误。
可以使用RPUSH
命令把多个元素插入队列,只需要在命令后面指定多个参数。元素是从左到右按序从列表尾部插入。 比如命令 RPUSH mylist a b c
会返回一个列表,其第一个元素是 a ,第二个元素是 b ,第三个元素是 c。
语法:
1
127.0.0.1:6379> RPUSH KEY_NAME VALUE1..VALUEN
返回值:
整数: 执行 push 操作后的列表长度。
实例:
1
2
3
4
5
6
7
8127.0.0.1:6379> RPUSH mylist "Hello"
(integer) 1
127.0.0.1:6379> RPUSH mylist "World"
(integer) 2
127.0.0.1:6379> LRANGE mylist 0 -1
1) "Hello"
2) "World"
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(1) for each element added, so O(N) to add N elements when the command is called with multiple arguments.
1.4.17 RPUSHX key element [element …]
RPUSHX
将值 value 插入到列表 key
的表尾, 当且仅当 key
存在并且是一个列表。 和 RPUSH
命令相反, 当 key 不存在时,RPUSHX 命令什么也不做。
语法:
1
127.0.0.1:6379> RPUSHX KEY_NAME VALUE1..VALUEN
返回值:
整数: RPUSHX 命令执行之后列表的长度。
实例:
1
2
3
4
5
6
7
8
9
10
11
12127.0.0.1:6379> RPUSH mylist "Hello"
(integer) 1
127.0.0.1:6379> RPUSH mylist "World"
(integer) 2
127.0.0.1:6379> RPUSHX myotherlist "World"
(integer) 0
127.0.0.1:6379> LRANGE mylist 0 -1
1) "Hello"
2) "World"
127.0.0.1:6379> LRANGE myotherlist 0 -1
(empty array)
127.0.0.1:6379>
可用版本>= 2.2.0.
时间复杂度: O(1) for each element added, so O(N) to add N elements when the command is called with multiple arguments.
1.5 Sets(集合)
1.5.1 SADD key member [member …]
Redis Sadd 命令将一个或多个成员元素加入到集合中,已经存在于集合的成员元素将被忽略。
假如集合 key 不存在,则创建一个只包含被添加的元素作为成员的集合。
当集合 key 不是集合类型时,返回一个错误。
注意:在 Redis2.4 版本以前, SADD 只接受单个成员值。
语法:
1
127.0.0.1:6379> SADD KEY_NAME VALUE1..VALUEN
返回值:
整数: 返回新成功添加到集合里元素的数量,不包括已经存在于集合中的元素。
实例:
1
2
3
4
5
6
7
8127.0.0.1:6379> SADD myset "Hello"
(integer) 1
127.0.0.1:6379> SADD myset "World"
(integer) 1
127.0.0.1:6379> SMEMBERS myset
1) "World"
2) "Hello"
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(1) for each element added, so O(N) to add N elements when the command is called with multiple arguments.
1.5.2 SCARD key
Redis SCARD 命令返回集合中元素的数量。
语法:
1
127.0.0.1:6379> SCARD KEY_NAME
返回值:
整数: 集合中成员的数量。 当集合 key 不存在时,返回 0 。
实例:
1
2
3
4
5
6
7127.0.0.1:6379> SADD myset "Hello"
(integer) 1
127.0.0.1:6379> SADD myset "World"
(integer) 1
127.0.0.1:6379> SCARD myset
(integer) 2
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(1)
1.5.3 SDIFF key [key …]
Redis SDIFF 命令返回第一个集合与其他集合之间的差异,也可以认为说第一个集合中独有的元素。不存在的集合 key 将视为空集。
语法:
1
127.0.0.1:6379> SDIFF FIRST_KEY OTHER_KEY1..OTHER_KEYN
返回值:
数组: 包含差集成员的列表。
实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15127.0.0.1:6379> SADD key1 a b c d
(integer) 4
127.0.0.1:6379> SADD key2 c
(integer) 1
127.0.0.1:6379> SADD key3 a c e
(integer) 3
127.0.0.1:6379> SDIFF key1 key2 key3
1) "b"
2) "d"
127.0.0.1:6379> SDIFF key1 key2
1) "a"
2) "b"
3) "d"
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(N) where N is the total number of elements in all given sets.
1.5.4 SDIFFSTORE destination key [key …]
SDIFFSTORE
命令的作用和SDIFF
类似,不同的是它将结果保存到 destination
集合,而把结果集返回给客户端。
如果 destination
集合已经存在,则将其覆盖。
语法:
1
127.0.0.1:6379> SDIFFSTORE DESTINATION_KEY KEY1..KEYN
返回值:
整数: 结果集中成员数量。
实例:
1
2
3
4
5
6
7
8
9
10127.0.0.1:6379> SADD key1 a b c d
(integer) 4
127.0.0.1:6379> SADD key2 c d e
(integer) 3
127.0.0.1:6379> SDIFFSTORE key key1 key2
(integer) 2
127.0.0.1:6379> SMEMBERS key
1) "a"
2) "b"
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(N) where N is the total number of elements in all given sets.
1.5.5 SINTER key [key …]
对于不存在的 key
可以认为是空集合。
如果给定的key
中有一个空集合,那么结果集一定是空集合。
语法:
1
127.0.0.1:6379> SINTER KEY KEY1..KEYN
返回值:
数组: 结果集成员个数。
实例:
1
2
3
4
5
6
7
8127.0.0.1:6379> SADD key1 a b c d
(integer) 4
127.0.0.1:6379> SADD key2 c d e
(integer) 3
127.0.0.1:6379> SINTER key1 key2
1) "d"
2) "c"
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(N*M) worst case where N is the cardinality of the smallest set and M is the number of sets.
1.5.6 SINTERSTORE destination key [key …]
SINTERSTORE 命令与 SINTER 命令类似,不同的是它并不是直接返回结果集,而是将结果保存在 destination 集合中。
如果 destination 集合存在, 则会被覆盖。
语法:
1
127.0.0.1:6379> SINTERSTORE DESTINATION_KEY KEY KEY1..KEYN
返回值:
整数: 结果集中成员数量。
实例:
1
2
3
4
5
6
7
8
9
10
11
12
13127.0.0.1:6379> DEL key key1key2 key3
(integer) 1
127.0.0.1:6379> DEL key key1 key2 key3
(integer) 2
127.0.0.1:6379> SADD key1 a b c
(integer) 3
127.0.0.1:6379> SADD key2 c d e
(integer) 3
127.0.0.1:6379> SINTERSTORE key key1 key2
(integer) 1
127.0.0.1:6379> SMEMBERS key
1) "c"
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(N*M) worst case where N is the cardinality of the smallest set and M is the number of sets.
1.5.7 SISMEMBER key member
Redis SISMEMBER 用于判断元素 member 是否集合 key 的成员。
语法:
1
127.0.0.1:6379> SISMEMBER KEY MEMBER
返回值:
整数:
1
: 如果成员元素是集合的成员,返回 1 。0
: 如果成员元素不是集合的成员,或key
不存在,返回 0 。
实例:
1
2
3
4
5
6
7127.0.0.1:6379> SADD myset "one"
(integer) 1
127.0.0.1:6379> SISMEMBER myset "one"
(integer) 1
127.0.0.1:6379> SISMEMBER myset "two"
(integer) 0
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(1)
1.5.8 SMEMBERS key
Redis SISMEMBER 命令返回存储在 key
中的集合的所有的成员。 不存在的集合被视为空集合。
SISMEMBER 与运行带有一个参数 key
的 SINTER 有同样的效果。
语法:
1
127.0.0.1:6379> SMEMBERS key
返回值:
数组: 集合中的所有成员。
实例:
1
2
3
4
5
6127.0.0.1:6379> SADD myset "Hello" "World"
(integer) 2
127.0.0.1:6379> SMEMBERS myset
1) "World"
2) "Hello"
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(N) where N is the set cardinality.
1.5.9 SMOVE source destination member
Redis SMOVE 命令用于从集合source
中移动成员member
到集合 destination
。 这个操作是原子操作。 在任何时刻,member
只会存在于source
和destination
其中之一。
如果集合source
不存在,或者要移动的成员不是集合source
的成员,什么也不执行并返回 0
。
否则,其它情况下,从集合source
中删除成员并添加到集合 destination
。
如果要移动的元素在集合 destination
中已经存在,那么只是从集合source
中删除该成员。
如果 source
或destination
不是集合类型则返回错误。
语法:
1
127.0.0.1:6379> SMOVE SOURCE DESTINATION MEMBER
返回值:
整数:
1
: 移动元素成功。0
: 如果要移动的 element 不是source
的成员,什么也不执行。
实例:
1
2
3
4
5
6
7
8
9
10
11
12127.0.0.1:6379> SADD myset "one" "two"
(integer) 2
127.0.0.1:6379> SADD myotherset "three"
(integer) 1
127.0.0.1:6379> SMOVE myset myotherset "two"
(integer) 1
127.0.0.1:6379> SMEMBERS myset
1) "one"
127.0.0.1:6379> SMEMBERS myotherset
1) "two"
2) "three"
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(1)
1.5.10 SPOP key [count]
Redis SPOP 命令用于从集合 key
中删除并返回一个或多个随机元素。
这个命令和 SRANDMEMBER 相似, SRANDMEMBER 只返回随机成员但是不删除这些返回的成员。
参数 count
从 Redis 3.2 起可用
语法:
1
127.0.0.1:6379> SPOP key [count]
返回值:
多行字符串: 被删除的元素,当
key
不存在时返回nil
。实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16127.0.0.1:6379> SADD myset "one" "two" "three"
(integer) 3
127.0.0.1:6379> SPOP myset
"one"
127.0.0.1:6379> SMEMBERS myset
1) "two"
2) "three"
127.0.0.1:6379> SADD myset "four" "five"
(integer) 2
127.0.0.1:6379> SPOP myset 3
1) "four"
2) "three"
3) "two"
127.0.0.1:6379> SMEMBERS myset
1) "five"
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(1)
1.5.11 SRANDMEMBER key [count]
Redis SRANDMEMBER 命令仅使用key
参数,那么随机返回集合key
中的一个随机元素。
Redis 2.6开始,可以接受 count 参数,如果count是整数且小于元素的个数,返回含有 count 个不同的元素的数组,如果count是个整数且大于集合中元素的个数时,返回整个集合的所有元素,当count是负数,则会返回一个包含count的绝对值的个数元素的数组,如果count的绝对值大于元素的个数,则返回的结果集里会出现一个元素出现多次的情况.
仅提供key参数时,该命令作用类似于SPOP
命令,不同的是SPOP
命令会将被选择的随机元素从集合中移除,而SRANDMEMBER
仅仅是返回该随记元素,而不对原集合做任何操作。
传递count参数时的行为规范
当传递了一个值为正数的count参数,返回的元素就好像从集合中移除了每个选中的元素一样(就像在宾果游戏中提取数字一样)。但是元素不会从集合中移除。所以基本上:
- 不会返回重复的元素。
- 如果count参数的值大于集合内的元素数量,此命令将会仅返回整个集合,没有额外的元素。
相反,当count参数的值为负数时,此命令的行为将发生改变,并且提取操作就像在每次提取后,重新将取出的元素放回包里一样,因此,可能返回重复的元素,以及总是会返回我们请求的数量的元素,因为我们可以一次又一次地重复相同的元素,除了当集合为空(或者不存在key)的时候,将总是会返回一个空数组。
返回元素的分布
当集合中的元素数量很少时,返回元素分布远不够完美,这是因为我们使用了一个近似随机元素函数,它并不能保证良好的分布。
所使用的算法(在dict.c中实现)对哈希表桶进行采样以找到非空桶。一旦找到非空桶,由于我们在哈希表的实现中使用了链接法,因此会检查桶中的元素数量,并且选出一个随机元素。
这意味着,如果你在整个哈希表中有两个非空桶,其中一个有三个元素,另一个只有一个元素,那么其桶中单独存在的元素将以更高的概率返回。
语法:
1
127.0.0.1:6379> SRANDMEMBER KEY [count]
返回值:
多行字符串: 不使用count 参数的情况下该命令返回随机的元素,如果key不存在则返回nil。
数组: 使用count参数,则返回一个随机的元素数组,如果key不存在则返回一个空的数组。
实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14127.0.0.1:6379> SADD myset one two three
(integer) 3
127.0.0.1:6379> SRANDMEMBER myset
"three"
127.0.0.1:6379> SRANDMEMBER myset 2
1) "one"
2) "two"
127.0.0.1:6379> SRANDMEMBER myset -5
1) "three"
2) "one"
3) "two"
4) "three"
5) "three"
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: Without the count argument O(1), otherwise O(N) where N is the absolute value of the passed count.
1.5.12 SREM key member [member …]
SREM 用于在集合中删除指定的元素。如果指定的元素不是集合成员则被忽略。
如果集合 key
不存在则被视为一个空的集合,该命令返回0。
如果key的类型不是一个集合,则返回 ERR WRONGTYPE Operation against a key holding the wrong kind of value 错误
语法:
1
127.0.0.1:6379> SREM KEY MEMBER1..MEMBERN
返回值:
整数: 被删除元素个数,不含不存在的元素。
实例:
1
2
3
4
5
6
7
8
9
10127.0.0.1:6379> SADD myset "one" "two" "three"
(integer) 3
127.0.0.1:6379> SREM myset "one"
(integer) 1
127.0.0.1:6379> SREM myset "four"
(integer) 0
127.0.0.1:6379> SMEMBERS myset
1) "two"
2) "three"
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(N) where N is the number of members to be removed.
1.5.13 SUNION key [key …]
SUNION 命令用于返回所有给定集合的并集。例如:
对于不存在 key 被当做空集合处理。
语法:
1
127.0.0.1:6379> SUNION KEY KEY1..KEYN
返回值:
数组: 结果集中成员数量。
实例:
1
2
3
4
5
6
7
8
9
10
11127.0.0.1:6379> SADD key1 "a" "b" "c"
(integer) 3
127.0.0.1:6379> SADD key2 "c" "d" "e"
(integer) 3
127.0.0.1:6379> SUNION key1 key2
1) "e"
2) "b"
3) "c"
4) "a"
5) "d"
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(N) where N is the total number of elements in all given sets.
1.5.14 SUNIONSTORE destination key [key …]
SUNIONSTORE 命令的功能类似于 SUNION,不同的是不反回结果集,而是存储在 destination
中。
如果 destination
已经存在,则被覆盖。
语法:
1
127.0.0.1:6379>
返回值:
整数: 结果集中的成员数量。
实例:
1
2
3
4
5
6
7
8
9
10
11
12
13127.0.0.1:6379> SADD key1 "a" "b" "c"
(integer) 3
127.0.0.1:6379> SADD key2 "c" "d" "e"
(integer) 3
127.0.0.1:6379> SUNIONSTORE key key1 key2
(integer) 5
127.0.0.1:6379> SMEMBERS key
1) "e"
2) "b"
3) "c"
4) "a"
5) "d"
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度: O(N) where N is the total number of elements in all given sets.
1.5.15 SSCAN key cursor [MATCH pattern] [COUNT count]
Redis SSCAN 命令用于遍历集合中键的元素,SSCAN 继承自SCAN。
语法:
1
127.0.0.1:6379> SSCAN key cursor [MATCH pattern] [COUNT count]
参数说明:
- cursor - 游标。
- pattern - 匹配的模式。
- count - 指定从数据集里返回多少元素,默认值为 10
返回值:
数组列表。
实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15127.0.0.1:6379> SADD myset "Mongodb" "Redis" "hive"
(integer) 3
127.0.0.1:6379> SSCAN myset 0 match "R*"
1) "0"
2) 1) "Redis"
127.0.0.1:6379> SSCAN myset 2 match "R*"
1) "0"
2) (empty array)
127.0.0.1:6379> SSCAN myset -4 match R*
1) "0"
2) 1) "Redis"
127.0.0.1:6379> SSCAN myset 2 match *o*
1) "0"
2) 1) "Mongodb"
127.0.0.1:6379>
可用版本>= 2.8.0.
时间复杂度: O(1) for every call. O(N) for a complete iteration, including enough command calls for the cursor to return back to 0. N is the number of elements inside the collection..
1.6 Sorted Sets(有序集合)
1.6.1 ZADD key [NX|XX] [GT|LT] [CH] [INCR]score member [score member …]
Redis ZADD 命令用于将一个或多个 member
元素及其 score
值加入到有序集 key
当中。
如果某个 member
已经是有序集的成员,那么更新这个 member
的 score
值,并通过重新插入这个 member
元素,来保证该 member
在正确的位置上。
如果有序集合 key
不存在,则创建一个空的有序集并执行 ZADD 操作。
当 key
存在但不是有序集类型时,返回一个错误。
score
值可以是整数值或双精度浮点数,score
可为正也可以为负。
注意: 在 Redis 2.4 版本以前, ZADD 每次只能添加一个元素。
语法:
1
127.0.0.1:6379> ZADD key [NX|XX] [GT|LT] [CH] [INCR]score member [score member ...]
参数说明:
- XX: 仅更新存在的成员,不添加新成员。
NX: 不更新存在的成员。只添加新成员。
LT: 更新新的分值比当前分值小的成员,不存在则新增。
GT: 更新新的分值比当前分值大的成员,不存在则新增。
CH: 返回变更成员的数量。变更的成员是指 新增成员 和 score值更新的成员,命令指明的和之前score值相同的成员不计在内。 注意: 在通常情况下,ZADD返回值只计算新添加成员的数量。
INCR: ZADD 使用该参数与 ZINCRBY 功能一样。一次只能操作一个score-element对。
注意: GT, LT 和 NX 三者互斥不能同时使用。
scores 有效值范围
Redis 有序集合的分数使用双精度64位浮点数表示。在Redis所支持的平台上,称为IEEE 754 floating point number,它能包括的整数范围是
-(2^53)
到+(2^53)
。或者说是-9007199254740992 到 9007199254740992。更大的整数在内部用指数形式表示,所以,如果为分数设置一个非常大的整数,你得到的是一个近似的十进制数。Sorted sets 101
有序集合按照分数以递增的方式进行排序。相同的成员(member)只存在一次,有序集合不允许存在重复的成员。 分数可以通过
ZADD
命令进行更新或者也可以通过ZINCRBY
命令递增来修改之前的值,相应的他们的排序位置也会随着分数变化而改变。获取一个成员当前的分数可以使用 ZSCORE 命令,也可以用它来验证成员是否存在。
相同分数的成员
有序集合里面的成员是不能重复的都是唯一的,但是,不同成员间有可能有相同的分数。当多个成员有相同的分数时,他们将是按字典排序(ordered lexicographically)(仍由分数作为第一排序条件,然后,相同分数的成员按照字典序排序)。
字典顺序排序用的是二进制,它比较的是字符串的字节数组。
如果用户将所有元素设置相同分数(例如0),有序集合里面的所有元素将按照字典顺序进行排序,范围查询元素可以使用 ZRANGEBYLEX 命令(注:范围查询分数可以使用 ZRANGEBYSCORE 命令)。
返回值:
整数:
- 被成功添加的新成员的数量,不包括那些被更新分数的、已经存在的成员。
如果使用 INCR 选项,则返回 多行字符串:
- 以字符串形式表示的
member
的 score 值(双精度浮点数)。(双精度浮点数) , 执行失败返回nil
(当使用XX
或NX
选项)。
实例:
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添加单个元素
127.0.0.1:6379> ZADD page_rank 10 google.com
(integer) 1
添加多个元素
127.0.0.1:6379> ZADD page_rank 9 baidu.com 8 github.com
(integer) 2
127.0.0.1:6379> ZRANGE page_rank 0 -1 WITHSCORES
1) "github.com"
2) "8"
3) "baidu.com"
4) "9"
5) "google.com"
6) "10"
添加已存在元素,且 score 值不变,发现没有改变
127.0.0.1:6379> ZADD page_rank 10 google.com
(integer) 0
127.0.0.1:6379> ZRANGE page_rank 0 -1 WITHSCORES
1) "github.com"
2) "8"
3) "baidu.com"
4) "9"
5) "google.com"
6) "10"
添加已存在元素,但是改变 score 值
127.0.0.1:6379> ZADD page_rank 6 github.com
(integer) 0
"github.com"的值被改变
127.0.0.1:6379> ZRANGE page_rank 0 -1 WITHSCORES
1) "github.com"
2) "6"
3) "baidu.com"
4) "9"
5) "google.com"
6) "10"
127.0.0.1:6379>
可用版本>= 1.2.0.
时间复杂度: O(log(N)) for each item added, where N is the number of elements in the sorted set.
1.6.2 ZCARD key
Redis ZCARD 命令用于返回有序集的成员个数。
语法:
1
127.0.0.1:6379> ZCARD KEY_NAME
返回值:
整数: 返回有序集的成员个数,当
key
不存在时,返回0
。实例:
1
2
3
4
5
6
7127.0.0.1:6379> ZADD myset 1 "one"
(integer) 1
127.0.0.1:6379> ZADD myset 2 "two"
(integer) 1
127.0.0.1:6379> ZCARD myset
(integer) 2
127.0.0.1:6379>
可用版本>= 1.2.0.
时间复杂度: O(1)
1.6.3 ZCOUNT key min max
ZCOUNT 返回有序集 key
中, score
值在 min
和 max
之间(默认包括 score
值等于 min
或 max
)的成员的数量。
关于参数 min
和 max
的详细使用方法,请参考ZRANGEBYSCORE
.
注意: ZCOUNT 命令的时间复杂度是 O(log(N)),因为 ZCOUNT 使用有序成员来实现范围查询,不需要遍历整个集合。
语法:
1
127.0.0.1:6379>
返回值:
整数: score 值在 min 和 max 之间的成员的数量。
实例:
1
2
3
4
5
6
7
8
9
10
11127.0.0.1:6379> ZADD myset 1 "one"
(integer) 1
127.0.0.1:6379> ZADD myset 2 "two"
(integer) 1
127.0.0.1:6379> ZADD myset 3 "three"
(integer) 1
127.0.0.1:6379> ZCOUNT myset -inf +inf
(integer) 3
127.0.0.1:6379> ZCOUNT myset (1 3
(integer) 2
127.0.0.1:6379>
可用版本>= 2.0.0.
时间复杂度: O(log(N)) with N being the number of elements in the sorted set.
1.6.4 ZINCRBY key increment member
ZINCRBY
为有序集 key
的成员 member
的 score
值加上增量 increment
。
当 key
不存在,或 member
不是 key
的成员时, ZINCRBY key increment member
等同于 ZADD key increment member
。
当 key
不是有序集类型时,返回”ERR WRONGTYPE Operation against a key holding the wrong kind of value”。
score
值可以是字符串形式表示的整数值或双精度浮点数。
可以通过传递一个负数值 increment
,让 score
减去相应的值,比如 ZINCRBY key -2 member
,就是让 member
的 score
值减去 2
。
语法:
1
127.0.0.1:6379>
返回值:
多行字符串: 以字符串形式表示的
member
成员的新score
值(双精度浮点数)。实例:
1
2
3
4
5
6
7
8
9
10
11
12127.0.0.1:6379> ZADD myset 1 "one"
(integer) 1
127.0.0.1:6379> ZADD myset 2 "two"
(integer) 1
127.0.0.1:6379> ZINCRBY myset 2 "one"
"3"
127.0.0.1:6379> ZRANGE myset 0 -1 WITHSCORES
1) "two"
2) "2"
3) "one"
4) "3"
127.0.0.1:6379>
可用版本>= 1.2.0.
时间复杂度: O(log(N)) where N is the number of elements in the sorted set.
1.6.5 ZINTERSTORE destination numkeys key [key …] [WEIGHTS weight [weight …]] [AGGREGATE SUM|MIN|MAX]
计算 numkeys 个有序集合的交集,并且把结果放到 destination 中。 在给定要计算的 key 和其它参数之前,必须先给定 key 个数(numberkeys)。
默认情况下,结果集中元素的分数是各有序集合中该元素分数之和。
对于WEIGHTS和AGGREGATE参数的描述,参见命令 ZUNIONSTORE。
如果destination存在,会被覆盖。
语法:
1
127.0.0.1:6379> INTERSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]
返回值:
整数:结果集 destination 中元素个数。
实例:
1
2
3
4
5
6
7
8
9
10
11
12
13127.0.0.1:6379> ZADD zset1 1 "one" 2 "two"
(integer) 2
127.0.0.1:6379> ZADD zset2 1 "one" 2 "two" 3 "three"
(integer) 3
zset1 * 2 + zset2 * 3
127.0.0.1:6379> ZINTERSTORE out 2 zset1 zset2 WEIGHTS 2 3
(integer) 2
127.0.0.1:6379> ZRANGE out 0 -1 WITHSCORES
1) "one"
2) "5"
3) "two"
4) "10"
127.0.0.1:6379>
可用版本>= 2.0.0.
时间复杂度: O(NK)+O(Mlog(M)) worst case with N being the smallest input sorted set, K being the number of input sorted sets and M being the number of elements in the resulting sorted set.
1.6.6 ZLEXCOUNT key min max
当有序集中的所有成员都有相同的score
, ZLEXCOUNT 命令返回有序集中值在 min
和max
之间的成员个数。
min
和max
详见ZRANGEBYLEX
。时间复 O(log(N))。
语法:
1
127.0.0.1:6379> ZLEXCOUNT key min max
返回值:
整数: 返回特定分值元素个数。
实例:
1
2
3
4
5
6
7
8
9127.0.0.1:6379> ZADD myset 0 a 0 b 0 c 0 d 0 e
(integer) 5
127.0.0.1:6379> ZADD myset 0 f 0 g
(integer) 2
127.0.0.1:6379> ZLEXCOUNT myset - +
(integer) 7
127.0.0.1:6379> ZLEXCOUNT myset [b [f
(integer) 5
127.0.0.1:6379>
可用版本>= 2.8.9.
时间复杂度: O(log(N)) with N being the number of elements in the sorted set.
1.6.7 ZRANGE key start stop [WITHSCORES]
Redis ZRANGE 命令返回有序集中,指定区间内的成员,其中成员的按分数值递增(从小到大)来排序,具有相同分数值的成员按字典序(lexicographical order )来排列。
如果你需要成员按值递减(从大到小)来排列,请使用 ZREVRANGE
命令。
下标参数 start
和 stop
都以 0
为底,也就是说,以 0
表示有序集第一个成员,以 1
表示有序集第二个成员,以此类推。
你也可以使用负数下标,以 -1
表示最后一个成员, -2
表示倒数第二个成员,以此类推。
start
和 stop
都是包含在内的区间,因此例如 ZRANGE myzset 0 1
将会返回有序集合的第一个和第二个元素。
超出范围的索引不会产生错误。 如果 start
参数的值大于有序集合中的最大索引,或者 start > stop
,将会返回一个空列表。 如果 stop
的值大于有序集合的末尾,Redis 会将其视为有序集合的最后一个元素。
可以传递 WITHSCORES
选项,以便将元素的分数与元素一起返回。这样返回的列表将包含 value1,score1,...,valueN,scoreN
,而不是 value1,...,valueN
。 客户端类库可以自由地返回更合适的数据类型(建议:具有值和得分的数组或元组)。
语法:
1
127.0.0.1:6379> ZRANGE key start stop [WITHSCORES]
返回值:
数组: 给定范围内的元素列表(如果指定了
WITHSCORES
选项,将同时返回它们的得分)。实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24127.0.0.1:6379> ZADD myset 1 "one" 2 "two" 3 "three"
(integer) 3
127.0.0.1:6379> ZRANGE myset 0 -1
1) "one"
2) "two"
3) "three"
127.0.0.1:6379> ZRANGE myset 2 3
1) "three"
127.0.0.1:6379> ZRANGE myset -2 -1
1) "two"
2) "three"
127.0.0.1:6379> ZRANGE myset 0 1 WITHSCORES
1) "one"
2) "1"
3) "two"
4) "2"
127.0.0.1:6379> ZRANGE myset 0 -1 WITHSCORES
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
127.0.0.1:6379>
可用版本>= 1.2.0.
时间复杂度: O(log(N)+M) with N being the number of elements in the sorted set and M the number of elements returned.
1.6.8 ZRANGEBYLEX key min max [LIMIT offset count]
Redis Zrangebylex 通过字典区间返回有序集合的成员。
语法:
1
127.0.0.1:6379> ZRANGEBYLEX key min max [LIMIT offset count]
返回值:
数组: 指定区间内的元素列表。
实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16127.0.0.1:6379> ZADD myset 0 a 0 b 0 c 0 d 0 e 0 f 0 g
(integer) 7
127.0.0.1:6379> ZRANGEBYLEX myset - [c
1) "a"
2) "b"
3) "c"
127.0.0.1:6379> ZRANGEBYLEX myset - (c
1) "a"
2) "b"
127.0.0.1:6379> ZRANGEBYLEX myset [aaa (g
1) "b"
2) "c"
3) "d"
4) "e"
5) "f"
127.0.0.1:6379>
可用版本>= 2.8.9.
时间复杂度: O(log(N)+M) with N being the number of elements in the sorted set and M the number of elements being returned. If M is constant (e.g. always asking for the first 10 elements with LIMIT), you can consider it O(log(N)).
1.6.9 ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
Redis ZRANGEBYSCORE 返回有序集 key
中,所有 score
值介于 min
和 max
之间(包括等于 min
或 max
)的成员。有序集成员按 score
值递增(从小到大)次序排列。
具有相同 score
值的成员按字典序(lexicographical order
)来排列(该属性是有序集提供的,不需要额外的计算)。
可选的 LIMIT
参数指定返回结果的数量及区间(就像SQL中的 SELECT LIMIT offset, count
),注意当 offset
很大时,定位 offset
的操作可能需要遍历整个有序集,此过程最坏复杂度为 O(N) 时间。
可选的 WITHSCORES
参数决定结果集是单单返回有序集的成员,还是将有序集成员及其 score
值一起返回。 该选项自 Redis 2.0 版本起可用。
互斥区间与无穷大:
min
和 max
可以是 -inf
和 +inf
,这样一来,你就可以在不知道有序集的最低和最高 score
值的情况下,获取所有成员。
默认情况下,区间的取值使用闭区间 (小于等于或大于等于),你也可以通过给参数前增加 (
符号来使用可选的开区间 (小于或大于)。
举个例子:
1 | ZRANGEBYSCORE zset (1 5 |
返回所有符合条件 1 < score <= 5
的成员:
1 | ZRANGEBYSCORE zset (5 (10 |
则返回所有符合条件 5 < score < 10
的成员。
语法:
1
127.0.0.1:6379> ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
返回值:
数组: 指定区间内的有序集成员的列表(带有
score
值(可选))。实例:
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
26127.0.0.1:6379> ZADD myset 1 "one" 2 "two" 3 "three"
(integer) 3
显示整个有序集
127.0.0.1:6379> ZRANGEBYSCORE myset -inf +inf
1) "one"
2) "two"
3) "three"
显示整个有序集及成员的 score 值
127.0.0.1:6379> ZRANGEBYSCORE myset -inf +inf WITHSCORES
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
显示大于等于 1 小于等于 2 的成员
127.0.0.1:6379> ZRANGEBYSCORE myset 1 2
1) "one"
2) "two"
显示大于 1 小于等于 2 的成员
127.0.0.1:6379> ZRANGEBYSCORE myset (1 2
1) "two"
显示大于 1 小于 2 的成员
127.0.0.1:6379> ZRANGEBYSCORE myset (1 (2
(empty array)
127.0.0.1:6379>
可用版本>= 1.0.5.
时间复杂度: O(log(N)+M) with N being the number of elements in the sorted set and M the number of elements being returned. If M is constant (e.g. always asking for the first 10 elements with LIMIT), you can consider it O(log(N)).
1.6.10 ZRANK key member
RedisZRANK
命令返回有序集key
中成员member
的排名,其中有序集成员按score值从低到高排列。
排名从0开始,也就是说,score值最低的成员排名为0
。
使用ZREVRANK
命令可以获得成员按score值递增(从高到低)排列的排名。
语法:
1
127.0.0.1:6379>
返回值:
- 如果
member
是有序集key的成员,整数:member
的排名。 - 如果
member
不是有序集key的成员, 或key
不存在,多行字符串:nil
。
- 如果
实例:
1
2
3
4
5
6
7127.0.0.1:6379> ZADD myset 1 "one" 2 "two" 3 "three"
(integer) 3
127.0.0.1:6379> ZRANK myset "three"
(integer) 2
127.0.0.1:6379> ZRANK myset "four"
(nil)
127.0.0.1:6379>
可用版本>= 2.0.0.
时间复杂度: O(log(N))
1.6.11 ZREM key member [member …]
Redis ZREM 命令用于从有序集合key
中删除指定的成员member
。
如果member
不存在则被忽略。
当key存在,但是不是有序集合类型时,返回类型错误。
语法:
1
127.0.0.1:6379> ZREM key member [member ...]
返回值:
整数: 返回的是从有序集合中删除的成员个数,不包括不存在的成员。
实例:
1
2
3
4
5
6
7
8
9
10127.0.0.1:6379> ZADD myset 1 "one" 2 "two" 3 "three"
(integer) 3
127.0.0.1:6379> ZREM myset "two"
(integer) 1
127.0.0.1:6379> ZRANGE myset 0 -1 WITHSCORES
1) "one"
2) "1"
3) "three"
4) "3"
127.0.0.1:6379>
可用版本>= 1.2.0.
时间复杂度: O(M*log(N)) with N being the number of elements in the sorted set and M the number of elements to be removed.
1.6.12 ZREMRANGEBYLEX key min max
Reids ZREMRANGEBYLEX 命令用于删除成员名称按字典由低到高排序介于min
和 max
之间的所有成员(集合中所有成员的分数相同)。 不要在成员分数不同的有序集合中使用此命令,因为它是基于分数一致的有序集合设计的,如果使用,会导致删除的结果不正确。
命令中 min
和 max
的含义与 ZRANGEBYLEX 命令相同。该命令会与使用相同min
和 max
参数的 ZRANGEBYLEX 返回相同的结果。
语法:
1
127.0.0.1:6379> ZREMRANGEBYLEX key min max
返回值:
整数: 删除元素的个数。
实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22127.0.0.1:6379> ZADD myset 0 aaa 0 b 0 c 0 d 0 e 0 f 0 zap 0 zip 0 ALPHA 0 alpha
(integer) 10
127.0.0.1:6379> ZRANGE myset 0 -1
1) "ALPHA"
2) "aaa"
3) "alpha"
4) "b"
5) "c"
6) "d"
7) "e"
8) "f"
9) "zap"
10) "zip"
127.0.0.1:6379> ZREMRANGEBYLEX myset [alpha [omega
(integer) 6
127.0.0.1:6379> ZRANGE myset 0 -1
1) "ALPHA"
2) "aaa"
3) "zap"
4) "zip"
127.0.0.1:6379>
可用版本>= 2.8.9.
时间复杂度: O(log(N)+M) with N being the number of elements in the sorted set and M the number of elements removed by the operation.
1.6.13 ZREMRANGEBYRANK key start stop
Redis ZREMRANGEBYRANK 移除有序集key中,指定排名(rank)区间 start
和 stop
内的所有成员。下标参数start和stop都是从0开始计数,0是分数最小的那个元素。索引也可是负数,表示位移从最高分处开始数。例如,-1是分数最高的元素,-2是分数第二高的,依次类推。
语法:
1
127.0.0.1:6379> ZREMRANGEBYRANK key start stop
返回值:
整数: 删除元素的个数。
实例:
1
2
3
4
5
6
7
8127.0.0.1:6379> ZADD myset 1 "one" 2 "two" 3 "three"
(integer) 3
127.0.0.1:6379> ZREMRANGEBYRANK myset 0 1
(integer) 2
127.0.0.1:6379> ZRANGE myset 0 -1 WITHSCORES
1) "three"
2) "3"
127.0.0.1:6379>
可用版本>= 2.0.0.
时间复杂度: O(log(N)+M) with N being the number of elements in the sorted set and M the number of elements removed by the operation.
1.6.14 ZREMRANGEBYSCORE key min max
Redis ZREMRANGEBYSCORE 命令移除有序集key中,所有score值介于min和max之间(包括等于min或max)的成员。
自版本2.1.6开始,score值等于min或max的成员也可以不包括在内,语法请参见ZRANGEBYSCORE
命令。
语法:
1
127.0.0.1:6379> ZREMRANGEBYSCORE key min max
返回值:
整数: 删除元素的个数。
实例:
1
2
3
4
5
6
7
8
9
10127.0.0.1:6379> ZADD myset 1 "one" 2 "two" 3 "three"
(integer) 3
127.0.0.1:6379> ZREMRANGEBYSCORE myset -inf (2
(integer) 1
127.0.0.1:6379> ZRANGE myset 0 -1 WITHSCORES
1) "two"
2) "2"
3) "three"
4) "3"
127.0.0.1:6379>
可用版本>= 1.2.0.
时间复杂度: O(log(N)+M) with N being the number of elements in the sorted set and M the number of elements removed by the operation.
1.6.15 ZREVRANGE key start stop [WITHSCORES]
Redis ZREVRANGE 命令返回有序集key
中,指定区间内的成员。其中成员的位置按score值递减(从高到低)来排列。
具有相同score值的成员按字典序的反序排列。 除了成员排序相反外,ZREVRANGE
命令的其他方面和ZRANGE
命令一样。
语法:
1
127.0.0.1:6379> ZREVRANGE key start stop [WITHSCORES]
返回值:
数组: 指定范围的元素列表(可选是否含有分数)。
实例:
1
2
3
4
5
6
7
8
9
10
11
12127.0.0.1:6379> ZADD myset 1 "one" 2 "two" 3 "three"
(integer) 3
127.0.0.1:6379> ZREVRANGE myset 0 -1
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> ZREVRANGE myset 2 3
1) "one"
127.0.0.1:6379> ZREVRANGE myset -2 -1
1) "two"
2) "one"
127.0.0.1:6379>
可用版本>= 1.2.0.
时间复杂度: O(log(N)+M) with N being the number of elements in the sorted set and M the number of elements returned.
1.6.16 ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count]
Redis Zrangebyscore 返回有序集合中指定分数区间的成员列表。有序集成员按分数值递增(从小到大)次序排列。
具有相同分数值的成员按字典序来排列(该属性是有序集提供的,不需要额外的计算)。
默认情况下,区间的取值使用闭区间 (小于等于或大于等于),你也可以通过给参数前增加 ( 符号来使用可选的开区间 (小于或大于)。
可选的LIMIT参数指定返回结果的数量及区间(类似SQL中SELECT LIMIT offset, count)。注意,如果offset太大,定位offset就可能遍历整个有序集合,这会增加O(N)的复杂度。
可选参数WITHSCORES会返回元素和其分数,而不只是元素。这个选项在redis2.0之后的版本都可用。
##区间及无限
min和max可以是-inf和+inf,这样一来,你就可以在不知道有序集的最低和最高score值的情况下,使用ZRANGEBYSCORE这类命令。
默认情况下,区间的取值使用闭区间(小于等于或大于等于),你也可以通过给参数前增加(符号来使用可选的开区间(小于或大于)。
语法:
1
127.0.0.1:6379> ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count]
返回值:
数组: 指定分数范围的元素列表(也可以返回他们的分数)。
实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14127.0.0.1:6379> ZADD myset 1 "one" 2 "two" 3 "three"
(integer) 3
127.0.0.1:6379> ZREVRANGEBYSCORE myset +inf -inf
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> ZREVRANGEBYSCORE myset 2 1
1) "two"
2) "one"
127.0.0.1:6379> ZREVRANGEBYSCORE myset 2 (1
1) "two"
127.0.0.1:6379> ZREVRANGEBYSCORE myset (2 (1
(empty array)
127.0.0.1:6379>
可用版本>= 2.2.0.
时间复杂度: O(log(N)+M) with N being the number of elements in the sorted set and M the number of elements being returned. If M is constant (e.g. always asking for the first 10 elements with LIMIT), you can consider it O(log(N)).
1.6.17 ZREVRANK key member
Redis ZREVRANK 命令返回有序集key
中成员member
的排名,其中有序集成员按score值从高到低排列。
排名从0开始,也就是说,score值最大的成员排名为0
。
使用ZRANK
命令可以获得成员按score值递增(从低到高)排列的排名。
语法:
1
127.0.0.1:6379> ZREVRANK key member
返回值:
- 如果
member
是有序集key的成员,整数:member
的排名。 - 如果
member
不是有序集key的成员, 或key
不存在,多行字符串:nil
。
- 如果
实例:
1
2
3
4
5
6
7
8
9127.0.0.1:6379> ZADD myset 1 "one" 2 "two" 3 "three"
(integer) 3
127.0.0.1:6379> ZREVRANK myset "one"
(integer) 2
127.0.0.1:6379> ZREVRANK myset "two"
(integer) 1
127.0.0.1:6379> ZREVRANK myset "four"
(nil)
127.0.0.1:6379>
可用版本>= 2.0.0.
时间复杂度: O(log(N))
1.6.18 ZSCORE key member
Redis zscore 命令用于返回有序集 key
.中成员 member
的分数。
如果有续集中 不存在 member
,或者 key
不存在,返回 nil
。
语法:
1
127.0.0.1:6379> ZSCORE key member
返回值:
多行字符串: 成员的分数。(双精度浮点数,字符串格式)
实例:
1
2
3
4
5
6
7127.0.0.1:6379> ZADD myset 1 "one" 2 "two"
(integer) 2
127.0.0.1:6379> ZSCORE myset "two"
"2"
127.0.0.1:6379> ZSCORE myset "one"
"1"
127.0.0.1:6379>
可用版本>= 1.2.0.
时间复杂度: O(1)
1.6.19 ZUNIONSTORE destination numkeys key [key …] [WEIGHTS weight [weight …]] [AGGREGATE SUM|MIN|MAX]
Redis ZUNIONSTORE 用于计算给定的numkeys
个有序集合的并集,并且把结果放到destination中。
在给定要计算的key和其它参数之前,必须先给定key个数(numkeys
)。
默认情况下,结果集中某个成员的score值是所有给定集中该成员score值之和。
使用WEIGHTS
选项,你可以为每个给定的有序集指定一个乘法因子,意思就是,每个给定有序集的所有成员的score值在传递给聚合函数之前都要先乘以该因子。如果WEIGHTS
没有给定,默认是 1
。
使用AGGREGATE
选项,你可以指定并集的结果集的聚合方式。默认使用的参数SUM,可以将所有集合中某个成员的score值之和作为结果集中该成员的score值。如果使用参数MIN
或者MAX
,结果集就是所有集合中该元素最小或最大score。
如果destination
存在,会被覆盖。
语法:
1
127.0.0.1:6379> ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]
返回值:
整数: 结果集destination中成员的数量。
实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14127.0.0.1:6379> ZADD myset1 1 "one" 2 "two"
(integer) 2
127.0.0.1:6379> ZADD myset2 1 "one" 2 "two" 3 "three"
(integer) 3
127.0.0.1:6379> ZUNIONSTORE out 2 myset1 myset2 WEIGHTS 2 3
(integer) 3
127.0.0.1:6379> ZRANGE out 0 -1 WITHSCORES
1) "one"
2) "5"
3) "three"
4) "9"
5) "two"
6) "10"
127.0.0.1:6379>
可用版本>= 2.0.0.
时间复杂度: O(N)+O(M log(M)) with N being the sum of the sizes of the input sorted sets, and M being the number of elements in the resulting sorted set.
1.6.20 ZSCAN key cursor [MATCH pattern] [COUNT count]
查看 SCAN 获取关于 ZSCAN 命令的信息。
语法:
1
127.0.0.1:6379> ZSCAN key cursor [MATCH pattern] [COUNT count]
参数说明:
- cursor: 游标。
- pattern: 匹配的模式。
- count: 指定从数据集里返回多少元素,默认值为 10
返回值:
返回的每个元素都是一个有序集合元素,一个有序集合元素由一个成员(member)和一个分值(score)组成。
实例:
1
2
3
4
5
6
7127.0.0.1:6379> ZADD myset 1 "one" 2 "two" 3 "three"
(integer) 3
127.0.0.1:6379> ZSCAN myset 0 match *w*
1) "0"
2) 1) "two"
2) "2"
127.0.0.1:6379>
可用版本>= 2.8.0.
时间复杂度: O(1) for every call. O(N) for a complete iteration, including enough command calls for the cursor to return back to 0. N is the number of elements inside the collection..
1.7 Redis 发布订阅
1.7.1 PSUBSCRIBE pattern [pattern …]
Redis PSUBSCRIBE 命令用于订阅一个或多个符合给定模式的频道。
模式支持 glob 风格的正则表达式。每个模式以 *
作为匹配符,比如 it*
匹配所有以 it
开头的频道( it.news
、 it.blog
、 it.tweets
等等), news.*
匹配所有以 news.
开头的频道( news.it
、 news.global.today
等等),诸如此类。
特殊字符使用 \
转义。
语法:
1
127.0.0.1:6379> PSUBSCRIBE pattern [pattern ...]
返回值:
接收到的信息。
实例:
1
2
3
4
5
6
7
8
9
10
11127.0.0.1:6379> SUBSCRIBE rediscomcnChat
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "rediscomcnChat"
3) (integer) 1
1) "message"
2) "rediscomcnChat"
3) "Redis PUBLISH test"
1) "message"
2) "rediscomcnChat"
3) "Learn redis with python"
可用版本>= 2.0.0.
时间复杂度: O(N) where N is the number of patterns the client is already subscribed to.
1.7.2 PUBSUB subcommand [argument [argument …]]
Redis Pubsub 命令用于查看订阅与发布系统状态,它由数个不同格式的子命令组成。
PUBSUB CHANNELS [pattern]
列出当前的活跃频道。
活跃频道指的是那些至少有一个订阅者的频道, 订阅模式的客户端不计算在内。
pattern
参数是可选的:
- 如果不给出
pattern
参数,那么列出订阅与发布系统中的所有活跃频道。- 如果给出
pattern
参数,那么只列出和给定模式pattern
相匹配的那些活跃频道。返回值:
数组: 一个由活跃频道组成的列表。
PUBSUB NUMSUB [channel-1 ... channel-N]
返回给定频道的订阅者数量, 订阅模式的客户端不计算在内。
返回值:
数组: 一个多条批量回复(Multi-bulk reply),回复中包含给定的频道,以及频道的订阅者数量。
格式为:频道
channel-1
,channel-1
的订阅者数量,频道channel-2
,channel-2
的订阅者数量,诸如此类。回复中频道的排列顺序和执行命令时给定频道的排列顺序一致。
不给定任何频道而直接调用这个命令也是可以的, 在这种情况下, 命令只返回一个空列表。
PUBSUB NUMPAT
返回订阅模式的数量。
注意, 这个命令返回的不是订阅模式的客户端的数量, 而是客户端订阅的所有模式的数量总和。
返回值:
整数: 所有客户端订阅的所有模式的数量总和。
语法:
1
127.0.0.1:6379> PUBSUB subcommand [argument [argument ...]]
返回值:
数组: 一个由活跃频道组成的列表。
实例:
1
2
3127.0.0.1:6379> PUBSUB CHANNELS
(empty array)
127.0.0.1:6379>
可用版本>= 2.8.0.
时间复杂度: O(N) for the CHANNELS subcommand, where N is the number of active channels, and assuming constant time pattern matching (relatively short channels and patterns). O(N) for the NUMSUB subcommand, where N is the number of requested channels. O(1) for the NUMPAT subcommand.
1.7.3 PUBLISH channel message
Redis PUBLISH 命令用于将信息 message
发送到指定的频道 channel
。
语法:
1
127.0.0.1:6379> PUBLISH channel message
返回值:
整数: 接收到信息 message 的订阅者数量。
实例:
1
2
3
4
5
6
7
8
9
10对没有订阅者的频道发送信息
127.0.0.1:6379> PUBLISH bad_channel "can any body hear me?"
(integer) 0
向有一个订阅者的频道发送信息
127.0.0.1:6379> PUBLISH rediscomcnChat "Hello World"
(integer) 1
# 向有多个订阅者的频道发送信息(前提是,启动了多个订阅者)
127.0.0.1:6379> PUBLISH rediscomcnChat1 "two channel infos"
(integer) 2
127.0.0.1:6379>在订阅者频道可以接收到最新消息:
l lsh l 1
2
3
4
5
6
7
8
9127.0.0.1:6379> SUBSCRIBE rediscomcnChat
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "rediscomcnChat"
3) (integer) 1
1) "message"
2) "rediscomcnChat"
3) "Hello World"
可用版本>= 2.0.0.
时间复杂度: O(N+M) where N is the number of clients subscribed to the receiving channel and M is the total number of subscribed patterns (by any client).
1.7.4 PUNSUBSCRIBE [pattern [pattern …]]
Redis PUNSUBSCRIBE 命令用于客户端退订所有给定模式。
如果没有模式被指定,也即是,一个无参数的 PUNSUBSCRIBE 调用被执行,那么客户端使用PSUBSCRIBE 命令订阅的所有模式都会被退订。在这种情况下,命令会返回一个信息,告知客户端所有被退订的模式。
语法:
1
127.0.0.1:6379> PUNSUBSCRIBE [pattern [pattern ...]]
返回值:
这个命令在不同的客户端中有不同的表现。
实例:
1
2
3
4
5127.0.0.1:6379> PUNSUBSCRIBE rediscomcnChat1
1) "punsubscribe"
2) "rediscomcnChat1"
3) (integer) 0
127.0.0.1:6379>
可用版本>= 2.0.0.
时间复杂度: O(N+M) where N is the number of patterns the client is already subscribed and M is the number of total patterns subscribed in the system (by any client).
1.7.5 SUBSCRIBE channel [channel …]
Redis SUBSCRIBE 命令用于订阅给定的一个或多个频道的信息。
进入订阅模式后只能执行如下命令: SUBSCRIBE, PSUBSCRIBE, UNSUBSCRIBE, PUNSUBSCRIBE, PING 和QUIT 。
语法:
1
127.0.0.1:6379> SUBSCRIBE channel [channel ...]
返回值:
接收到的信息
实例:
1
2
3
4
5
6
7
8
9127.0.0.1:6379> SUBSCRIBE rediscomcnChat
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "rediscomcnChat"
3) (integer) 1
1) "message"
2) "rediscomcnChat"
3) "Hello World"
可用版本>= 2.0.0.
时间复杂度: O(N) where N is the number of channels to subscribe to.
1.7.6 UNSUBSCRIBE [channel [channel …]]
Redis UNSUBSCRIBE 命令用于指示客户端退订给定的频道。
如果没有频道被指定,一个无参数的 UNSUBSCRIBE 调用被执行,那么客户端使用 SUBSCRIBE 命令订阅的所有频道都会被退订。在这种情况下,命令会返回一个信息,告知客户端所有被退订的频道。
语法:
1
127.0.0.1:6379> UNSUBSCRIBE [channel [channel ...]]
返回值:
这个命令在不同的客户端中有不同的表现。
实例:
1
2
3
4
5127.0.0.1:6379> UNSUBSCRIBE rediscomcnChat1
1) "unsubscribe"
2) "rediscomcnChat1"
3) (integer) 0
127.0.0.1:6379>
可用版本>= 2.0.0.
时间复杂度: O(N) where N is the number of clients already subscribed to a channel.
1.8 Redis 事务
1.8.1 DISCARD
DISCARD 命令取消事务,放弃执行事务队列内的所有命令,恢复连接为非 (transaction) 模式。
如果正在使用 WATCH 命令监视某个(或某些) key,那么取消所有监视,等同于执行命令 UNWATCH 。
语法:
1
127.0.0.1:6379> DISCARD
返回值:
字符串:
OK
.实例:
1
2
3
4
5
6
7
8
9127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> ping
QUEUED
127.0.0.1:6379(TX)> SET myset "kungs"
QUEUED
127.0.0.1:6379(TX)> DISCARD
OK
127.0.0.1:6379>
可用版本>= 2.0.0.
1.8.2 EXEC
Redis EXEC 命令用于执行事务 (transaction )队列内的所有命令。
假如某个(或某些) key 正处于 WATCH 命令的监视之下,且事务块中有和这个(或这些) key 相关的命令,那么EXEC 命令只在这个(或这些) key 没有被其他命令所改动的情况下执行并生效,否则该事务被打断(abort)。 check-and-set mechanism.
语法:
1
127.0.0.1:6379> EXEC
返回值:
事务块内所有命令的返回值,按命令执行的先后顺序排列。当操作被打断时,返回空值
nil
。实例:
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事务被成功执行
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> INCR user_id
QUEUED
127.0.0.1:6379(TX)> INCR user_id
QUEUED
127.0.0.1:6379(TX)> INCR user_id
QUEUED
127.0.0.1:6379(TX)> PING
QUEUED
127.0.0.1:6379(TX)> EXEC
1) (integer) 1
2) (integer) 2
3) (integer) 3
4) PONG
监视 key ,且事务成功执行
127.0.0.1:6379> WATCH lock lock_times
OK
127.0.0.1:6379>
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> SET lock "huangz"
QUEUED
127.0.0.1:6379(TX)> INCR lock_times
QUEUED
127.0.0.1:6379(TX)> EXEC
1) OK
2) (integer) 1
监视 key ,且事务被打断
127.0.0.1:6379> WATCH lock lock_times
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> SET lock "joe" # 就在这时,另一个客户端修改了 lock_times 的值
QUEUED
127.0.0.1:6379(TX)> INCR lock_times
QUEUED
127.0.0.1:6379(TX)> EXEC # 因为 lock_times 被修改, joe 的事务执行失败
(nil)
127.0.0.1:6379>
可用版本>= 1.2.0.
1.8.3 MULTI
Redis MULTI 命令用于标记一个事务块的开始。
事务块内的多条命令会按照先后顺序被放进一个队列当中,最后由 EXEC 命令原子性(atomic)地执行。
语法:
1
127.0.0.1:6379> MULTI
返回值:
字符串: 总是返回
OK
.实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> INCR user_id
QUEUED
127.0.0.1:6379(TX)> INCR user_id
QUEUED
127.0.0.1:6379(TX)> INCR user_id
QUEUED
127.0.0.1:6379(TX)> PING
QUEUED
127.0.0.1:6379(TX)> EXEC
1) (integer) 1
2) (integer) 2
3) (integer) 3
4) PONG
127.0.0.1:6379>
可用版本>= 1.2.0.
1.8.4 UNWATCH
Redis UNWATCH命令用于取消 WATCH 命令对所有 key 的监视。
详细参考 transaction.
如果执行过 EXEC 或DISCARD,无需再执行 UNWATCH。
因为 EXEC 命令会执行事务,因此 WATCH 命令的效果已经产生了;而 DISCARD命令在取消事务的同时也会取消所有对 key 的监视,因此这两个命令执行之后,就没有必要执行 UNWATCH
了。
语法:
1
127.0.0.1:6379> UNWATCH
返回值:
字符串: 总是返回
OK
.实例:
1
2
3
4
5127.0.0.1:6379> WATCH lock lock_times
OK
127.0.0.1:6379> UNWATCH
OK
127.0.0.1:6379>
可用版本>= 2.2.0.
时间复杂度: O(1)
1.8.5 WATCH key [key …]
Redis WATCH 命令用于标记要监视的key,以便有条件地执行事务(更多参考transaction)。
WATCH 命令可以监控一个或多个键,一旦其中有一个键被修改(或删除),之后的事务就不会执行。
监控一直持续到EXEC命令(事务中的命令是在EXEC之后才执行的,所以在MULTI命令后可以修改WATCH监控的键值)
语法:
1
127.0.0.1:6379> WATCH key [key ...]
返回值:
字符串: 总是返回
OK
。实例:
1
2
3127.0.0.1:6379> WATCH lock lock_times
OK
127.0.0.1:6379>
可用版本>= 2.2.0.
时间复杂度: O(1) for every key.
1.9 Script(脚本)
1.9.1 EVAL script numkeys key [key ...] arg [arg ...]
Redis Eval 命令使用 Lua 解释器执行脚本。
语法:
1
127.0.0.1:6379> EVAL script numkeys key [key ...] arg [arg ...]
参数说明:
- script: 参数是一段 Lua 5.1 脚本程序。脚本不必(也不应该)定义为一个 Lua 函数。
- numkeys: 用于指定键名参数的个数。
- key [key …]: 从 EVAL 的第三个参数开始算起,表示在脚本中所用到的那些 Redis 键(key),这些键名参数可以在 Lua 中通过全局变量 KEYS 数组,用 1 为基址的形式访问( KEYS[1] , KEYS[2] ,以此类推)。
- arg [arg …]: 附加参数,在 Lua 中通过全局变量 ARGV 数组访问,访问的形式和 KEYS 变量类似( ARGV[1] 、 ARGV[2] ,诸如此类)。
返回值:
返回需要执行的输出内容。
实例:
1
2
3
4
5
6127.0.0.1:6379> eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second
1) "key1"
2) "key2"
3) "first"
4) "second"
127.0.0.1:6379>
可用版本>= 2.6.0.
1.9.2 EVALSHA sha1 numkeys key [key ...] arg [arg ...]
Redis Evalsha 命令根据给定的 sha1 校验码,执行缓存在服务器中的脚本。
将脚本缓存到服务器的操作可以通过 SCRIPT LOAD 命令进行。
这个命令的其他地方,比如参数的传入方式,都和 EVAL 命令一样。
语法:
1
127.0.0.1:6379> EVALSHA sha1 numkeys key [key ...] arg [arg ...]
参数说明:
- sha1 : 通过 SCRIPT LOAD 生成的 sha1 校验码。
- numkeys: 用于指定键名参数的个数。
- key [key …]: 从 EVAL 的第三个参数开始算起,表示在脚本中所用到的那些 Redis 键(key),这些键名参数可以在 Lua 中通过全局变量 KEYS 数组,用 1 为基址的形式访问( KEYS[1] , KEYS[2] ,以此类推)。
- arg [arg …]: 附加参数,在 Lua 中通过全局变量 ARGV 数组访问,访问的形式和 KEYS 变量类似( ARGV[1] 、 ARGV[2] ,诸如此类)。
返回值:
输出缓存的数据内容。
实例:
1
2
3
4
5127.0.0.1:6379> SCRIPT LOAD "return 'hello moto'"
"232fd51614574cf0867b83d384a5e898cfd24e5a"
127.0.0.1:6379> EVALSHA "232fd51614574cf0867b83d384a5e898cfd24e5a" 0
"hello moto"
127.0.0.1:6379>
可用版本>= 2.6.0.
1.9.3 SCRIPT EXISTS sha1 [sha1 ...]
Redis Script Exists 命令用于校验指定的脚本是否已经被保存在缓存当中。
语法:
1
127.0.0.1:6379> SCRIPT EXISTS sha1 [sha1 ...]
返回值:
一个列表,包含 0 和 1 ,前者表示脚本不存在于缓存,后者表示脚本已经在缓存里面了。
列表中的元素和给定的 SHA1 校验和保持对应关系,比如列表的第三个元素的值就表示第三个 SHA1 校验和所指定的脚本在缓存中的状态。
实例:
1
2
3
4
5
6
7
8
9
10
11载入一个脚本
127.0.0.1:6379> SCRIPT LOAD "return 'hello moto'"
"232fd51614574cf0867b83d384a5e898cfd24e5a"
127.0.0.1:6379> SCRIPT EXISTS "232fd51614574cf0867b83d384a5e898cfd24e5a"
1) (integer) 1
清空缓存
127.0.0.1:6379> SCRIPT FLUSH
OK
127.0.0.1:6379> SCRIPT EXISTS "232fd51614574cf0867b83d384a5e898cfd24e5a"
1) (integer) 0
127.0.0.1:6379>
可用版本>= 2.6.0.
1.9.4 SCRIPT FLUSH
Redis Script Flush 命令用于清除所有 Lua 脚本缓存。
语法:
1
127.0.0.1:6379> SCRIPT FLUSH
返回值:
字符串: 总是返回
OK
.实例:
1
2
3127.0.0.1:6379> SCRIPT FLUSH
OK
127.0.0.1:6379>
可用版本>= 2.6.0.
1.9.5 SCRIPT KILL
Redis Script kill 命令用于杀死当前正在运行的 Lua 脚本,当且仅当这个脚本没有执行过任何写操作时,这个命令才生效。
这个命令主要用于终止运行时间过长的脚本,比如一个因为 BUG 而发生无限循环的脚本。
SCRIPT KILL 执行之后,当前正在运行的脚本会被杀死,执行这个脚本的客户端会从 EVAL 命令的阻塞当中退出,并收到一个错误作为返回值。
语法:
1
127.0.0.1:6379> SCRIPT KILL
返回值:
字符串: 总是返回
OK
.实例:
1
2
3127.0.0.1:6379> SCRIPT KILL
OK
127.0.0.1:6379>
可用版本>= 2.6.0.
1.9.6 SCRIPT LOAD script
Redis Script Load 命令用于将脚本 script 添加到脚本缓存中,但并不立即执行这个脚本。
EVAL 命令也会将脚本添加到脚本缓存中,但是它会立即对输入的脚本进行求值。
如果给定的脚本已经在缓存里面了,那么不执行任何操作。
在脚本被加入到缓存之后,通过 EVALSHA 命令,可以使用脚本的 SHA1 校验和来调用这个脚本。
脚本可以在缓存中保留无限长的时间,直到执行 SCRIPT FLUSH 为止。
关于使用 Redis 对 Lua 脚本进行求值的更多信息,请参见 EVAL 命令。
语法:
1
127.0.0.1:6379> SCRIPT LOAD script
返回值:
给定脚本的 SHA1 校验和
实例:
1
2
3127.0.0.1:6379> SCRIPT LOAD "return 1"
"e0e1f9fabfc9d4800c877a703b823ac0578ff8db"
127.0.0.1:6379>
可用版本>= 2.6.0.
1.10 Connection(连接)
1.10.1 AUTH [username] password
Redis AUTH 命令用来设置如下两种方式对访问Redis进行权限控制:
- 通过
requirepass
设置访问密码。If the Redis server is password protected via therequirepass
option. - Redis 6.0 起,支持ACL权限控制,具体参考 Redis ACL system 。
对应于配置文件中的 requirepass
命令。通过配置 requirepass
,可以使 Redis 拒绝未使用 AUTH
验证访问权限的客户端链接。
如果 AUTH
命令验证的密码与配置文件requirepass
配置的相同,则密码验证通过,服务器返回OK
,并开始接受客户端的命令。
密码验证失败,则返回提示信息重新输入密码。
安全注意
因为redis的高性能能在短时间接受非常多的尝试性密码,所以请务必设置一个足够复杂的密码以防止可能的攻击。推荐使用 ACL GENPASS 命令生成密码。
语法:
当使用 Redis ACLs 权限控制时,
AUTH
验证格式如下:1
127.0.0.1:6379> AUTH [username] password
通过验证用户名密码的方式验证访问权限,详细参考 ACL guide
在 ACLs 模式下,如果传递一个密码参数给 AUTH,那么会隐式设置用户名 “default”。
返回值:
字符串: 验证失败时返回错误。
实例:
1
2
3
4
5
6127.0.0.1:6379> AUTH PASSWORD
(error) ERR Client sent AUTH, but no password is set
127.0.0.1:6379> CONFIG SET requirepass "yanpenggong"
OK
127.0.0.1:6379> AUTH mypass
Ok
可用版本>= 1.0.0.
1.10.2 ECHO message
Redis ECHO 命令用于打印一个给定的信息 message ,测试时使用。
语法:
1
127.0.0.1:6379> ECHO message
返回值:
多行字符串:返回字符串
message
本身。实例:
1
2
3127.0.0.1:6379> ECHO "Hello World"
"Hello World"
127.0.0.1:6379>
可用版本>= 1.0.0.
1.10.3 PING
Redis PING 命令用于客户端向 Redis 服务器发送一个 PING ,如果服务器运作正常的话,会返回一个 PONG
。PING 命令不带参数返回 PONG
。带参数则返回参数 message
。
PING 通常用来测试连接是否存活,或者测试延迟。
如果客户端订阅某个频道或某个模式,不带参数执行命令会返回一个数组第一个元素是 “pong” ,第二个元素是空,带参数执行同样返回参数 message
。
语法:
1
127.0.0.1:6379> PING
返回值:
字符串:如果连接正常就返回一个 PONG ,否则返回一个连接错误。
实例:
1
2
3
4
5127.0.0.1:6379> PING
PONG
127.0.0.1:6379> PING "Hello World"
"Hello World"
127.0.0.1:6379>
可用版本>= 1.0.0.
1.10.4 QUIT
Redis QUIT 命令用于请求服务器关闭连接。在当前连接上的待处理请求完成后,立刻断开连接。
语法:
1
127.0.0.1:6379> QUIT
返回值:
字符串: 总是返回 OK。
实例:
1
2127.0.0.1:6379> QUIT
[root@localhost redis-6.2.6]#
可用版本>= 1.0.0.
1.10.5 SELECT index
Redis SELECT 命令用于切换到指定的数据库,index 是从 0 开始的整数。默认使用数据库 0 。
Redis 可选择的数据库是一种逻辑命名空间格式:物理上所有的数据库还是持久化在一起的,在同一个RDB/AOF文件中。不同的数据库中可以有同名的 key, FLUSHDB, SWAPDB
或 RANDOMKEY 这些命令都是针对选定的数据库有效。
从实际应用角度出发,Redis databases 主要用来表示不同的 key
属于同一个应用,而不是一个 Redis 实例对应多个不同的应用。
Reids 分片(Cluster)不能使用 SELECT 。因为 Redis 分片只支持数据库 0 。Redis 分片的情况下,有多个数据库是没有用的。
当前选定的数据库是连接的一个属性,客户端应该记录当前连接的数据库并在重连的时候重新选择对应的数据库。
没有查询当前连接所选择的数据库的命令,可以使用 CLIENT LIST 输出所有用户当前选择的数据库。
语法:
1
127.0.0.1:6379> SELECT index
返回值:
字符串:总是返回 OK 。
实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18默认使用 0 号数据库
127.0.0.1:6379> SET dn_number 0
OK
使用 1 号数据库
127.0.0.1:6379> SELECT 1
OK
已经切换到 1 号数据库,注意 Redis 现在的命令提示符多了个 [1]
127.0.0.1:6379[1]> GET db_number
(nil)
127.0.0.1:6379[1]> SET db_number 1
OK
127.0.0.1:6379[1]> GET db_number
"1"
再切换到 3 号数据库
127.0.0.1:6379[1]> SELECT 3
OK
提示符从 [1] 改变成了 [3]
127.0.0.1:6379[3]>
可用版本>= 1.0.0.
1.11 SERVER(服务器)
1.11.1 BGREWRITEAOF
Redis BGREWRITEAOF
命令用于异步执行一个 AOF(Append Only File ) 文件重写操作。重写会创建一个当前 AOF 文件的体积优化版本。
即使 Bgrewriteaof 执行失败,也不会有任何数据丢失,因为旧的 AOF 文件在 Bgrewriteaof 成功之前不会被修改。
注意:从 Redis 2.4 开始, AOF 重写由 Redis 自行触发, BGREWRITEAOF
仅仅用于手动触发重写操作。
只有当后台没有正在运行的持久化进程的时候,重写才会被 Redis 触发。
具体来说:
- 如果一个 redis 的子进程在创建磁盘快照,AOF 重写被列入执行计划但是不会执行直到生成 RDB 的子程序退出。在这种情况下
BGREWRITEAOF
将仍然返回OK状态码, 不过使用一个合适的提示信息。你可以检查一个 AOF 重写是否被例入执行计划通过查询INFO
命令。 - 如果一个 AOF rewrite 已经在运行,那么这个命令将会返回错误并且不会有 AOF rewrite 命令被列入后续的执行计划中。
- 如果 AOF 重启可以启动,但是在运行开始的时候失败(例如创建子进程失败),会返回错误信息给调用者。
从 Redis 2.4 起 AOF rewrite 是被自动触发的,当然 BGREWRITEAOF
命令可以用来在任何时间触发重写。
请参考 Redis持久化文档 获取更多信息。
语法:
1
127.0.0.1:6379> BGREWRITEAOF
返回值:
字符串: 启动重写的提示信息或者执行错误信息。
实例:
1
2
3127.0.0.1:6379> BGREWRITEAOF
Background append only file rewriting started
127.0.0.1:6379>
可用版本>= 1.0.0.
1.11.2 BGSAVE
后台保存DB。一般立即返回 OK 状态码。 Redis forks, 父进程继续提供服务以供客户端调用,子进程将DB数据保存到磁盘然后退出。
如果有运行中的SAVE或AOF返回错误。
如果使用 BGSAVE SCHEDULE
那么立即返回 OK
,如果后台正好有运行中的AOF,SAVE操作会在下次运行。
客户端可以通过 LASTSAVE
命令查看相关信息,判断 BGSAVE
命令是否执行成功。
请移步 持久化文档 查看更多相关细节。
语法:
1
127.0.0.1:6379> BGSAVE [SCHEDULE]
返回值:
字符串:
Background saving started
或Background saving scheduled
使用SCHEDULE
时。实例:
1
2
3127.0.0.1:6379> BGSAVE
Background saving started
127.0.0.1:6379>
可用版本>= 1.0.0.
1.11.3 CLIENT KILL
Redis CLIENT KILL 命令用于关闭地址为 ip:port
的客户端连接。
语法:
1
127.0.0.1:6379> CLIENT KILL [ip:port] [ID client-id] [TYPE normal|master|slave|pubsub] [USER username] [ADDR ip:port] [SKIPME yes/no]
ip:port
应该和CLIENT LIST
命令返回的结果中addr
列其中一行匹配。因为 Redis 使用单线程设计,所以当 Redis 正在执行命令的时候,不会有客户端被断开连接。
如果要被断开连接的客户端正在执行命令,那么当这个命令执行之后,在发送下一个命令的时候,它就会收到一个网络错误,告知它自身的连接已被关闭。
可以根据不同属性杀死客户端而不是只按地址杀死。他们有以下选项:
CLIENT KILL ADDR ip:port
和旧版的三个参数时的行为完全一样。CLIENT KILL ID client-id
可以通过唯一ID
字段杀死一个客户端,唯一ID
可以通过Redis2.8.12的CLIENT LIST
命令查询。CLIENT KILL TYPE type
这里的type
可以是normal
,slave
,pubsub
。 这将关闭给定烈性的所有客户端。请注意MONITOR
命令阻塞的客户端是normal
类型。CLIENT KILL USER username
关闭使用 ACL username 连接的客户端。如果不存在 ACL user 则返回错误。CLIENT KILL SKIPME yes/no
默认情况下是yes
, 调用该命令的客户端自身不被删掉,如果为no
也会删除自身。
返回值:
三参数格式执行命令:字符串: 连接存在并被关闭返回
OK
。新格式:整数: 被杀死的客户端个数。
实例:
1
2
3
4
5
6
7
8
9
10
11列出所有已连接客户端
127.0.0.1:6379> CLIENT list
id=90 addr=127.0.0.1:34566 laddr=127.0.0.1:6379 fd=7 name= age=0 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=26 qbuf-free=40928 argv-mem=10 obl=0 oll=0 omem=0 tot-mem=61466 events=r cmd=client user=default redir=-1
杀死当前客户端的连接
127.0.0.1:6379> CLIENT KILL 127.0.0.1:34566
OK
之前的连接已经被关闭,CLI 客户端又重新建立了连接
之前的端口是 34566 ,现在是 34568
127.0.0.1:6379> CLIENT list
id=91 addr=127.0.0.1:34568 laddr=127.0.0.1:6379 fd=7 name= age=0 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=26 qbuf-free=40928 argv-mem=10 obl=0 oll=0 omem=0 tot-mem=61466 events=r cmd=client user=default redir=-1
127.0.0.1:6379>
可用版本>= 2.4.0.
时间复杂度: O(N) where N is the number of client connections
1.11.4 CLIENT LIST
Redis CLIENT LIST 命令用于返回所有连接到服务器的客户端信息和统计数据。
从 v5.0 起,TYPE type
子命令可以用来过滤客户端类型,type 可以是 normal
, master
, replica
或pubsub
。
注意,被 MONITOR
阻塞的客户端被归类为 normal
类型。
语法:
1
127.0.0.1:6379> CLIENT LIST [TYPE normal|master|replica|pubsub]
返回值:
命令返回多行字符串,这些字符串按以下形式被格式化:
- 每个已连接客户端对应一行(以 LF 分割)
- 每行字符串由一系列 属性=值 形式的域组成,每个域之间以空格分开
以下是域的含义:
- addr : 客户端的地址和端口
- fd : 套接字所使用的文件描述符
- age : 以秒计算的已连接时长
- idle : 以秒计算的空闲时长
- flags : 客户端 flag
- db : 该客户端正在使用的数据库 ID
- sub : 已订阅频道的数量
- psub : 已订阅模式的数量
- multi : 在事务中被执行的命令数量
- qbuf : 查询缓冲区的长度(字节为单位, 0 表示没有分配查询缓冲区)
- qbuf-free : 查询缓冲区剩余空间的长度(字节为单位, 0 表示没有剩余空间)
- obl : 输出缓冲区的长度(字节为单位, 0 表示没有分配输出缓冲区)
- oll : 输出列表包含的对象数量(当输出缓冲区没有剩余空间时,命令回复会以字符串对象的形式被入队到这个队列里)
- omem : 输出缓冲区和输出列表占用的内存总量
- events : 文件描述符事件
- cmd : 最近一次执行的命令
客户端 flag 可以由以下部分组成:
- O : 客户端是 MONITOR 模式下的附属节点(slave)
- S : 客户端是一般模式下(normal)的附属节点
- M : 客户端是主节点(master)
- x : 客户端正在执行事务
- b : 客户端正在等待阻塞事件
- i : 客户端正在等待 VM I/O 操作(已废弃)
- d : 一个受监视(watched)的键已被修改, EXEC 命令将失败
- c : 在将回复完整地写出之后,关闭链接
- u : 客户端未被阻塞(unblocked)
- A : 尽可能快地关闭连接
- N : 未设置任何 flag
文件描述符事件可以是:
- r : 客户端套接字(在事件 loop 中)是可读的(readable)
- w : 客户端套接字(在事件 loop 中)是可写的(writeable)
实例:
1
2
3127.0.0.1:6379> CLIENT LIST
id=92 addr=127.0.0.1:34570 laddr=127.0.0.1:6379 fd=7 name= age=0 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=26 qbuf-free=40928 argv-mem=10 obl=0 oll=0 omem=0 tot-mem=61466 events=r cmd=client user=default redir=-1
127.0.0.1:6379>
可用版本>= 2.4.0.
时间复杂度: O(N) where N is the number of client connections
1.11.5 CLIENT GETNAME
Redis CLIENT GETNAME 命令用于返回 CLIENT SETNAME
命令为当前连接设置的名字。 因为新创建的连接默认是没有名字的, 对于没有名字的连接, CLIENT GETNAME
返回空白回复。
语法:
1
127.0.0.1:6379> CLIENT GETNAME
返回值:
多行字符串: 如果连接没有设置名字,那么返回空白回复; 如果有设置名字,那么返回名字。
实例:
1
2
3
4
5
6
7
8
9
10新连接默认没有名字
127.0.0.1:6379> CLIENT GETNAME
(nil)
设置名字
127.0.0.1:6379> CLIENT SETNAME hello-world-connection
OK
返回名字
127.0.0.1:6379> CLIENT GETNAME
"hello-world-connection"
127.0.0.1:6379>
可用版本>= 2.6.9.
时间复杂度: O(1)
1.11.6 CLIENT PAUSE
CLIENT PAUSE
是连接控制命令,它可以将所有客户端的访问暂停给定的毫秒数。
该命令执行如下:
- 它会停止处理所有来自一般客户端或者pub/sub客户端的命令。但是和slaves的复制命令不受影响。
- 因为它会立刻返回OK给调用者,所以CLIENT PAUSE 不会被自己暂停。
- 当给定的时间结束,所有的客户端都被解除阻塞:这时所有客户端的查询缓存里积累的所有命令都会被处理。
CLIENT PAUSE
命令可以可控的将客户端从一个Redis实例切换至另一个实例。
比如,当需要升级一个实例时,管理员可以作如下操作:
- 使用CLIENT PAUSE 暂停所有客户端
- 等待数秒,让slaves 节点处理完所有来自master的复制命令
- 将一个salve节点切换为 master
- 重配客户端以来接新的 master 节点
可以在MULTI/EXEC中一起使用CLIENT PAUSE 和INFO replication以在阻塞的同时获取当前master的偏移量。用这种方法,可以检查slaves处理至给定的复制偏移节点,确保复制完整。
从 3.2.10 / 4.0.0 起,该命令也会停止过期和淘汰在暂停时期,保持数据处于静止不变的状态。
语法:
1
127.0.0.1:6379> CLIENT PAUSE timeout
返回值:
字符串: OK 或者 error timeout is invalid。
实例:
1
2
3127.0.0.1:6379> CLIENT PAUSE 10
OK
127.0.0.1:6379>
可用版本>= 2.9.50.
时间复杂度: O(1)
1.11.7 CLIENT SETNAME
Redis CLIENT SETNAME
命令为当前连接设置一个名字。
这个名字会显示在CLIENT LIST
命令的结果中, 用于客户端识别当前与服务器之间的连接。
例如, 在使用 Redis 构建队列(queue)时, 可以根据连接负责的任务(role), 为信息生产者(producer)和信息消费者(consumer)分别设置不同的名字。
名字使用 Redis 的字符串类型来保存, 最大可以占用 512 MB 。 另外, 为了避免和CLIENT LIST
命令的输出格式发生冲突, 名字里不允许使用空格。
要移除一个连接的名字, 可以将连接的名字设为空字符串 “” 。
使用 CLIENT GETNAME
命令可以取出连接的名字。
新创建的连接默认是没有名字的。
提示:在 Redis 应用程序发生连接泄漏时,为连接设置名字是一种很好的 debug 手段。
语法:
1
127.0.0.1:6379> CLIENT SETNAME connection-name
返回值:
字符串:
OK
设置成功。实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20新连接默认没有名字
127.0.0.1:6379> CLIENT GETNAME
(nil)
设置名字
127.0.0.1:6379> CLIENT SETNAME link1-connection
OK
返回名字
127.0.0.1:6379> CLIENT GETNAME
"link1-connection"
在客户端列表中查看
127.0.0.1:6379> CLIENT LIST
id=94 addr=127.0.0.1:34574 laddr=127.0.0.1:6379 fd=7 name=link1-connection age=49 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=26 qbuf-free=40928 argv-mem=10 obl=0 oll=0 omem=0 tot-mem=61466 events=r cmd=client user=default redir=-1
清除名字
127.0.0.1:6379> CLIENT SETNAME # 只用空格是不行的!
(error) ERR Unknown subcommand or wrong number of arguments for 'SETNAME'. Try CLIENT HELP.
127.0.0.1:6379> CLIENT SETNAME "" # 必须双引号显示包围
OK
127.0.0.1:6379> CLIENT GETNAME # 清除完毕
(nil)
127.0.0.1:6379>
可用版本>= 2.6.9.
时间复杂度: O(1)
1.11.8 CLUSTER SLOTS
Redis Client Slots 命令用于当前的集群状态,以数组形式展示。
语法:
1
127.0.0.1:6379> CLUSTER SLOT
返回值:
IP/端口嵌套的列表数组。
实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25127.0.0.1:6379> cluster slots
1) 1) (integer) 0
2) (integer) 4095
3) 1) "127.0.0.1"
2) (integer) 7000
4) 1) "127.0.0.1"
2) (integer) 7004
2) 1) (integer) 12288
2) (integer) 16383
3) 1) "127.0.0.1"
2) (integer) 7003
4) 1) "127.0.0.1"
2) (integer) 7007
3) 1) (integer) 4096
2) (integer) 8191
3) 1) "127.0.0.1"
2) (integer) 7001
4) 1) "127.0.0.1"
2) (integer) 7005
4) 1) (integer) 8192
2) (integer) 12287
3) 1) "127.0.0.1"
2) (integer) 7002
4) 1) "127.0.0.1"
2) (integer) 7006
可用版本>= 3.0.0.
时间复杂度: O(N) where N is the total number of Cluster nodes
1.11.9 COMMAND
Redis COMMAND 命令以数组的形式返回有关所有 Redis 命令的详细信息。
如果集群客户端必须知道命令中 key 的位置,以便命令可以转到匹配的实例, 但是 Redis 命令在接收一个 key,多个 key 甚至由其他数据分隔开的多个 key 之间会有所不同。
你可以使用 COMMAND 来为每一个命令缓存命令和 key 位置之间的映射关系,以实现命令到集群的精确路由。
嵌套结果数组:
每一个顶级结果包含了六个嵌套的结果。每一个嵌套结果是:
命令名称
命令参数个数
嵌套的命令选项
参数列表中第一个 key 的位置
参数列表中最后一个 key 的位置
用于定位重复 key 的步数
命令名称
命令名称是以小写字符串形式返回的命令。
命令参数个数
| | |
| —————————————————————————————— | —————————————————————————————— |
| 1) 1) “get”
2) (integer) 2
3) 1) readonly
4) (integer) 1
5) (integer) 1
6) (integer) 1 | 1) 1) “mget”
2) (integer) -2
3) 1) readonly
4) (integer) 1
5) (integer) -1
6) (integer) 1 |命令参数个数遵循一个简单的模式
- 正数:命令拥有固定数量的必需参数。
- 负数:命令拥有最小数量的必需参数,可以有更多的参数。
命令参数个数包含计算命令名称本身。
例如:
GET
参数个数是 2,因为该命令仅接收一个参数,并且命令格式始终是GET _key_
。MGET
的参数个数是 -2,因为该命令接收至少一个参数,但最多可以接收无限数量:MGET _key1_ [key2] [key3] ...
。在
MGET
中同样需要注意,『最后一个key的位置』的值是 -1,这表示 key 列表可以具有无限长度。选项
命令标志是包含一个或多个状态回复的数组:
- write - 命令可能会导致修改
- readonly - 命令永远不会修改键
- denyoom - 如果当前发生OOM,则拒绝该命令
- admin - 服务器管理命令
- pubsub - 发布订阅相关的命令
- noscript - 在脚本中将会拒绝此命令
- random - 命令具有随机结果,在脚本中使用很危险
- sort\for*script* - 如果从脚本调用,则排序输出
- loading - 允许在数据库加载时使用此命令
- stale - 允许在从节点具有陈旧数据时使用此命令
- skip_monitor - 在MONITOR中不会显示此命令
- asking - 集群相关的 - 即使正在导入数据也接受此命令
- fast - 命令以常量或log(N)时间运行。用于延迟监控。
- movablekeys - key在命令中没有预先确定的位置。你必须自己发现key
可变位置的 Key
1
2
3
4
5
6
7
8 1) 1) "sort"
2) (integer) -2
3) 1) write
2) denyoom
3) movablekeys
4) (integer) 1
5) (integer) 1
6) (integer) 1某些 Redis 命令没有预先确定 key 的位置。对于那些命令,标志
movablekeys
会被添加到命令的选项中。 Redis 集群客户端需要解析标记为movabkeleys
的命令,以便定位所有相关的 key 的位置。目前需要解析 key 位置的完整命令列表:
SORT
- 可选的STORE
key,可选的BY
权重,可选的 GET keysZUNIONSTORE
- keys 参数列表在WEIGHT
或者AGGREGATE
之前ZINTERSTORE
- keys 参数列表在WEIGHT
或者AGGREGATE
之前EVAL
- keys 列表是在参数numkeys
之后的numkeys
个参数EVALSHA
- keys 列表是在参数numkeys
之后的numkeys
个参数另请参阅
COMMAND GETKEYS
来让 Redis 服务器告诉你任意给定完整命令中的 keys 在哪里。参数列表中的第一个Key
对大部分命令来说,第一个 key 的位置是 1。位置 0 始终是命令名称本身。
参数列表中的最后一个 Key
Redis 命令通常可以接收一个 key,两个 key 或者无限数量的 key 。
如果命令只接收一个 key,那么第一个 key 和最后一个 key 的位置都是1。
如果命令接收两个 key(例如:BRPOPLPUSH、SMOVE、
RENAME
等),那么最后一个 key 的位置是最后一个 key 在参数列表中的位置。如果命令接收无限数量的 key,那么最后一个 key 的位置是 -1。
步数
1) 1) “mset”
2) (integer) -3
3) 1) write
2) denyoom
4) (integer) 1
5) (integer) -1
6) (integer) 21) 1) “mget”
2) (integer) -2
3) 1) readonly
4) (integer) 1
5) (integer) -1
6) (integer) 1Key 的步数允许我们在命令中查找 key 的位置,比如
MSET
,其格式是MSET _key1_ _val1_ [key2] [val2] [key3] [val3]...
。在
MSET
的用例中,key 是每隔一个位置出现,所以步数的值是 2。对比上面的MGET
,其步数是 1。
语法:
1
127.0.0.1:6379> COMMAND
返回值:
数组: 嵌套的命令详细信息列表。命令以随机的顺序返回。
实例:
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307127.0.0.1:6379> COMMAND
1) 1) "xsetid"
2) (integer) 3
3) 1) write
2) denyoom
3) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @stream
3) @fast
2) 1) "lpop"
2) (integer) -2
3) 1) write
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @list
3) @fast
3) 1) "xautoclaim"
2) (integer) -6
3) 1) write
2) random
3) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @stream
3) @fast
4) 1) "discard"
2) (integer) 1
3) 1) noscript
2) loading
3) stale
4) fast
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @fast
2) @transaction
5) 1) "copy"
2) (integer) -3
3) 1) write
2) denyoom
4) (integer) 1
5) (integer) 2
6) (integer) 1
7) 1) @keyspace
2) @write
3) @slow
6) 1) "type"
2) (integer) 2
3) 1) readonly
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @keyspace
2) @read
3) @fast
7) 1) "failover"
2) (integer) -1
3) 1) admin
2) noscript
3) stale
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @admin
2) @slow
3) @dangerous
8) 1) "setnx"
2) (integer) 3
3) 1) write
2) denyoom
3) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @string
3) @fast
9) 1) "bgrewriteaof"
2) (integer) 1
3) 1) admin
2) noscript
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @admin
2) @slow
3) @dangerous
10) 1) "psync"
2) (integer) -3
3) 1) admin
2) noscript
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @admin
2) @slow
3) @dangerous
11) 1) "smove"
2) (integer) 4
3) 1) write
2) fast
4) (integer) 1
5) (integer) 2
6) (integer) 1
7) 1) @write
2) @set
3) @fast
12) 1) "zrevrangebylex"
2) (integer) -4
3) 1) readonly
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @sortedset
3) @slow
13) 1) "zinter"
2) (integer) -3
3) 1) readonly
2) movablekeys
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @read
2) @sortedset
3) @slow
14) 1) "geopos"
2) (integer) -2
3) 1) readonly
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @geo
3) @slow
15) 1) "readwrite"
2) (integer) 1
3) 1) fast
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @keyspace
2) @fast
16) 1) "hincrby"
2) (integer) 4
3) 1) write
2) denyoom
3) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @hash
3) @fast
17) 1) "keys"
2) (integer) 2
3) 1) readonly
2) sort_for_script
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @keyspace
2) @read
3) @slow
4) @dangerous
18) 1) "lpos"
2) (integer) -3
3) 1) readonly
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @list
3) @slow
19) 1) "exec"
2) (integer) 1
3) 1) noscript
2) loading
3) stale
4) skip_slowlog
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @slow
2) @transaction
20) 1) "zcount"
2) (integer) 4
3) 1) readonly
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @sortedset
3) @fast
21) 1) "zdiffstore"
2) (integer) -4
3) 1) write
2) denyoom
3) movablekeys
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @sortedset
3) @slow
22) 1) "replconf"
2) (integer) -1
3) 1) admin
2) noscript
3) loading
4) stale
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @admin
2) @slow
3) @dangerous
23) 1) "rpush"
2) (integer) -3
3) 1) write
2) denyoom
3) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @list
3) @fast
24) 1) "getdel"
2) (integer) 2
3) 1) write
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @string
3) @fast
25) 1) "brpop"
2) (integer) -3
3) 1) write
2) noscript
4) (integer) 1
5) (integer) -2
6) (integer) 1
7) 1) @write
2) @list
3) @slow
4) @blocking
26) 1) "georadius"
2) (integer) -6
3) 1) write
2) denyoom
3) movablekeys
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @geo
3) @slow
27) 1) "persist"
2) (integer) 2
3) 1) write
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @keyspace
2) @write
3) @fast
28) 1) "blpop"
2) (integer) -3
3) 1) write
2) noscript
4) (integer) 1
5) (integer) -2
6) (integer) 1
7) 1) @write
2) @list
3) @slow
4) @blocking
29) 1) "zrangebylex"
2) (integer) -4
3) 1) readonly
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @sortedset
3) @slow
30) 1) "sadd"
2) (integer) -3
3) 1) write
2) denyoom
3) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @set
3) @fast
31) 1) "unlink"
2) (integer) -2
3) 1) write
2) fast
4) (integer) 1
5) (integer) -1
6) (integer) 1
7) 1) @keyspace
2) @write
3) @fast
32) 1) "hello"
2) (integer) -1
3) 1) noscript
2) loading
3) stale
4) fast
5) no_auth
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @fast
2) @connection
33) 1) "smismember"
2) (integer) -3
3) 1) readonly
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @set
3) @fast
34) 1) "msetnx"
2) (integer) -3
3) 1) write
2) denyoom
4) (integer) 1
5) (integer) -1
6) (integer) 2
7) 1) @write
2) @string
3) @slow
35) 1) "zrange"
2) (integer) -4
3) 1) readonly
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @sortedset
3) @slow
36) 1) "zscan"
2) (integer) -3
3) 1) readonly
2) random
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @sortedset
3) @slow
37) 1) "ltrim"
2) (integer) 4
3) 1) write
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @list
3) @slow
38) 1) "save"
2) (integer) 1
3) 1) admin
2) noscript
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @admin
2) @slow
3) @dangerous
39) 1) "replicaof"
2) (integer) 3
3) 1) admin
2) noscript
3) stale
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @admin
2) @slow
3) @dangerous
40) 1) "sscan"
2) (integer) -3
3) 1) readonly
2) random
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @set
3) @slow
41) 1) "decr"
2) (integer) 2
3) 1) write
2) denyoom
3) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @string
3) @fast
42) 1) "flushdb"
2) (integer) -1
3) 1) write
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @keyspace
2) @write
3) @slow
4) @dangerous
43) 1) "object"
2) (integer) -2
3) 1) readonly
2) random
4) (integer) 2
5) (integer) 2
6) (integer) 1
7) 1) @keyspace
2) @read
3) @slow
44) 1) "zmscore"
2) (integer) -3
3) 1) readonly
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @sortedset
3) @fast
45) 1) "geosearchstore"
2) (integer) -8
3) 1) write
2) denyoom
4) (integer) 1
5) (integer) 2
6) (integer) 1
7) 1) @write
2) @geo
3) @slow
46) 1) "srem"
2) (integer) -3
3) 1) write
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @set
3) @fast
47) 1) "rpoplpush"
2) (integer) 3
3) 1) write
2) denyoom
4) (integer) 1
5) (integer) 2
6) (integer) 1
7) 1) @write
2) @list
3) @slow
48) 1) "zunion"
2) (integer) -3
3) 1) readonly
2) movablekeys
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @read
2) @sortedset
3) @slow
49) 1) "pfselftest"
2) (integer) 1
3) 1) admin
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @hyperloglog
2) @admin
3) @slow
4) @dangerous
50) 1) "shutdown"
2) (integer) -1
3) 1) admin
2) noscript
3) loading
4) stale
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @admin
2) @slow
3) @dangerous
51) 1) "pfdebug"
2) (integer) -3
3) 1) write
2) denyoom
3) admin
4) (integer) 2
5) (integer) 2
6) (integer) 1
7) 1) @write
2) @hyperloglog
3) @admin
4) @slow
5) @dangerous
52) 1) "pexpireat"
2) (integer) 3
3) 1) write
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @keyspace
2) @write
3) @fast
53) 1) "lset"
2) (integer) 4
3) 1) write
2) denyoom
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @list
3) @slow
54) 1) "zrem"
2) (integer) -3
3) 1) write
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @sortedset
3) @fast
55) 1) "sync"
2) (integer) 1
3) 1) admin
2) noscript
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @admin
2) @slow
3) @dangerous
56) 1) "geodist"
2) (integer) -4
3) 1) readonly
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @geo
3) @slow
57) 1) "setrange"
2) (integer) 4
3) 1) write
2) denyoom
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @string
3) @slow
58) 1) "lmove"
2) (integer) 5
3) 1) write
2) denyoom
4) (integer) 1
5) (integer) 2
6) (integer) 1
7) 1) @write
2) @list
3) @slow
59) 1) "expireat"
2) (integer) 3
3) 1) write
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @keyspace
2) @write
3) @fast
60) 1) "slaveof"
2) (integer) 3
3) 1) admin
2) noscript
3) stale
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @admin
2) @slow
3) @dangerous
61) 1) "ttl"
2) (integer) 2
3) 1) readonly
2) random
3) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @keyspace
2) @read
3) @fast
62) 1) "incrby"
2) (integer) 3
3) 1) write
2) denyoom
3) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @string
3) @fast
63) 1) "move"
2) (integer) 3
3) 1) write
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @keyspace
2) @write
3) @fast
64) 1) "monitor"
2) (integer) 1
3) 1) admin
2) noscript
3) loading
4) stale
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @admin
2) @slow
3) @dangerous
65) 1) "lastsave"
2) (integer) 1
3) 1) random
2) loading
3) stale
4) fast
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @admin
2) @fast
3) @dangerous
66) 1) "del"
2) (integer) -2
3) 1) write
4) (integer) 1
5) (integer) -1
6) (integer) 1
7) 1) @keyspace
2) @write
3) @slow
67) 1) "flushall"
2) (integer) -1
3) 1) write
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @keyspace
2) @write
3) @slow
4) @dangerous
68) 1) "debug"
2) (integer) -2
3) 1) admin
2) noscript
3) loading
4) stale
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @admin
2) @slow
3) @dangerous
69) 1) "zincrby"
2) (integer) 4
3) 1) write
2) denyoom
3) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @sortedset
3) @fast
70) 1) "pttl"
2) (integer) 2
3) 1) readonly
2) random
3) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @keyspace
2) @read
3) @fast
71) 1) "restore"
2) (integer) -4
3) 1) write
2) denyoom
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @keyspace
2) @write
3) @slow
4) @dangerous
72) 1) "xreadgroup"
2) (integer) -7
3) 1) write
2) movablekeys
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @write
2) @stream
3) @slow
4) @blocking
73) 1) "restore-asking"
2) (integer) -4
3) 1) write
2) denyoom
3) asking
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @keyspace
2) @write
3) @slow
4) @dangerous
74) 1) "dbsize"
2) (integer) 1
3) 1) readonly
2) fast
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @keyspace
2) @read
3) @fast
75) 1) "geoadd"
2) (integer) -5
3) 1) write
2) denyoom
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @geo
3) @slow
76) 1) "reset"
2) (integer) 1
3) 1) noscript
2) loading
3) stale
4) fast
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @fast
2) @connection
77) 1) "zremrangebyscore"
2) (integer) 4
3) 1) write
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @sortedset
3) @slow
78) 1) "zscore"
2) (integer) 3
3) 1) readonly
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @sortedset
3) @fast
79) 1) "hscan"
2) (integer) -3
3) 1) readonly
2) random
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @hash
3) @slow
80) 1) "sunion"
2) (integer) -2
3) 1) readonly
2) sort_for_script
4) (integer) 1
5) (integer) -1
6) (integer) 1
7) 1) @read
2) @set
3) @slow
81) 1) "migrate"
2) (integer) -6
3) 1) write
2) random
3) movablekeys
4) (integer) 3
5) (integer) 3
6) (integer) 1
7) 1) @keyspace
2) @write
3) @slow
4) @dangerous
82) 1) "zunionstore"
2) (integer) -4
3) 1) write
2) denyoom
3) movablekeys
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @sortedset
3) @slow
83) 1) "xack"
2) (integer) -4
3) 1) write
2) random
3) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @stream
3) @fast
84) 1) "rpushx"
2) (integer) -3
3) 1) write
2) denyoom
3) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @list
3) @fast
85) 1) "role"
2) (integer) 1
3) 1) noscript
2) loading
3) stale
4) fast
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @fast
2) @dangerous
86) 1) "pexpire"
2) (integer) 3
3) 1) write
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @keyspace
2) @write
3) @fast
87) 1) "rename"
2) (integer) 3
3) 1) write
4) (integer) 1
5) (integer) 2
6) (integer) 1
7) 1) @keyspace
2) @write
3) @slow
88) 1) "blmove"
2) (integer) 6
3) 1) write
2) denyoom
3) noscript
4) (integer) 1
5) (integer) 2
6) (integer) 1
7) 1) @write
2) @list
3) @slow
4) @blocking
89) 1) "zremrangebylex"
2) (integer) 4
3) 1) write
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @sortedset
3) @slow
90) 1) "zrevrange"
2) (integer) -4
3) 1) readonly
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @sortedset
3) @slow
91) 1) "hkeys"
2) (integer) 2
3) 1) readonly
2) sort_for_script
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @hash
3) @slow
92) 1) "mget"
2) (integer) -2
3) 1) readonly
2) fast
4) (integer) 1
5) (integer) -1
6) (integer) 1
7) 1) @read
2) @string
3) @fast
93) 1) "dump"
2) (integer) 2
3) 1) readonly
2) random
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @keyspace
2) @read
3) @slow
94) 1) "srandmember"
2) (integer) -2
3) 1) readonly
2) random
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @set
3) @slow
95) 1) "randomkey"
2) (integer) 1
3) 1) readonly
2) random
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @keyspace
2) @read
3) @slow
96) 1) "georadiusbymember"
2) (integer) -5
3) 1) write
2) denyoom
3) movablekeys
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @geo
3) @slow
97) 1) "zrangestore"
2) (integer) -5
3) 1) write
2) denyoom
4) (integer) 1
5) (integer) 2
6) (integer) 1
7) 1) @write
2) @sortedset
3) @slow
98) 1) "incrbyfloat"
2) (integer) 3
3) 1) write
2) denyoom
3) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @string
3) @fast
99) 1) "zrandmember"
2) (integer) -2
3) 1) readonly
2) random
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @sortedset
3) @slow
100) 1) "substr"
2) (integer) 4
3) 1) readonly
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @string
3) @slow
101) 1) "incr"
2) (integer) 2
3) 1) write
2) denyoom
3) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @string
3) @fast
102) 1) "post"
2) (integer) -1
3) 1) readonly
2) loading
3) stale
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @read
2) @slow
103) 1) "zrank"
2) (integer) 3
3) 1) readonly
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @sortedset
3) @fast
104) 1) "hrandfield"
2) (integer) -2
3) 1) readonly
2) random
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @hash
3) @slow
105) 1) "zdiff"
2) (integer) -3
3) 1) readonly
2) movablekeys
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @read
2) @sortedset
3) @slow
106) 1) "zrevrangebyscore"
2) (integer) -4
3) 1) readonly
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @sortedset
3) @slow
107) 1) "zadd"
2) (integer) -4
3) 1) write
2) denyoom
3) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @sortedset
3) @fast
108) 1) "append"
2) (integer) 3
3) 1) write
2) denyoom
3) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @string
3) @fast
109) 1) "sdiffstore"
2) (integer) -3
3) 1) write
2) denyoom
4) (integer) 1
5) (integer) -1
6) (integer) 1
7) 1) @write
2) @set
3) @slow
110) 1) "hstrlen"
2) (integer) 3
3) 1) readonly
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @hash
3) @fast
111) 1) "linsert"
2) (integer) 5
3) 1) write
2) denyoom
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @list
3) @slow
112) 1) "zrevrank"
2) (integer) 3
3) 1) readonly
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @sortedset
3) @fast
113) 1) "watch"
2) (integer) -2
3) 1) noscript
2) loading
3) stale
4) fast
4) (integer) 1
5) (integer) -1
6) (integer) 1
7) 1) @fast
2) @transaction
114) 1) "hdel"
2) (integer) -3
3) 1) write
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @hash
3) @fast
115) 1) "script"
2) (integer) -2
3) 1) noscript
2) may_replicate
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @slow
2) @scripting
116) 1) "punsubscribe"
2) (integer) -1
3) 1) pubsub
2) noscript
3) loading
4) stale
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @pubsub
2) @slow
117) 1) "lolwut"
2) (integer) -1
3) 1) readonly
2) fast
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @read
2) @fast
118) 1) "xinfo"
2) (integer) -2
3) 1) readonly
2) random
4) (integer) 2
5) (integer) 2
6) (integer) 1
7) 1) @read
2) @stream
3) @slow
119) 1) "hgetall"
2) (integer) 2
3) 1) readonly
2) random
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @hash
3) @slow
120) 1) "hexists"
2) (integer) 3
3) 1) readonly
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @hash
3) @fast
121) 1) "multi"
2) (integer) 1
3) 1) noscript
2) loading
3) stale
4) fast
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @fast
2) @transaction
122) 1) "lindex"
2) (integer) 3
3) 1) readonly
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @list
3) @slow
123) 1) "strlen"
2) (integer) 2
3) 1) readonly
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @string
3) @fast
124) 1) "zlexcount"
2) (integer) 4
3) 1) readonly
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @sortedset
3) @fast
125) 1) "xclaim"
2) (integer) -6
3) 1) write
2) random
3) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @stream
3) @fast
126) 1) "zcard"
2) (integer) 2
3) 1) readonly
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @sortedset
3) @fast
127) 1) "stralgo"
2) (integer) -2
3) 1) readonly
2) movablekeys
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @read
2) @string
3) @slow
128) 1) "host:"
2) (integer) -1
3) 1) readonly
2) loading
3) stale
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @read
2) @slow
129) 1) "scard"
2) (integer) 2
3) 1) readonly
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @set
3) @fast
130) 1) "xgroup"
2) (integer) -2
3) 1) write
2) denyoom
4) (integer) 2
5) (integer) 2
6) (integer) 1
7) 1) @write
2) @stream
3) @slow
131) 1) "rpop"
2) (integer) -2
3) 1) write
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @list
3) @fast
132) 1) "unwatch"
2) (integer) 1
3) 1) noscript
2) loading
3) stale
4) fast
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @fast
2) @transaction
133) 1) "spop"
2) (integer) -2
3) 1) write
2) random
3) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @set
3) @fast
134) 1) "hget"
2) (integer) 3
3) 1) readonly
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @hash
3) @fast
135) 1) "pubsub"
2) (integer) -2
3) 1) pubsub
2) random
3) loading
4) stale
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @pubsub
2) @slow
136) 1) "lrange"
2) (integer) 4
3) 1) readonly
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @list
3) @slow
137) 1) "set"
2) (integer) -3
3) 1) write
2) denyoom
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @string
3) @slow
138) 1) "renamenx"
2) (integer) 3
3) 1) write
2) fast
4) (integer) 1
5) (integer) 2
6) (integer) 1
7) 1) @keyspace
2) @write
3) @fast
139) 1) "hvals"
2) (integer) 2
3) 1) readonly
2) sort_for_script
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @hash
3) @slow
140) 1) "bgsave"
2) (integer) -1
3) 1) admin
2) noscript
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @admin
2) @slow
3) @dangerous
141) 1) "georadiusbymember_ro"
2) (integer) -5
3) 1) readonly
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @geo
3) @slow
142) 1) "setbit"
2) (integer) 4
3) 1) write
2) denyoom
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @bitmap
3) @slow
143) 1) "exists"
2) (integer) -2
3) 1) readonly
2) fast
4) (integer) 1
5) (integer) -1
6) (integer) 1
7) 1) @keyspace
2) @read
3) @fast
144) 1) "readonly"
2) (integer) 1
3) 1) fast
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @keyspace
2) @fast
145) 1) "zrangebyscore"
2) (integer) -4
3) 1) readonly
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @sortedset
3) @slow
146) 1) "info"
2) (integer) -1
3) 1) random
2) loading
3) stale
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @slow
2) @dangerous
147) 1) "xpending"
2) (integer) -3
3) 1) readonly
2) random
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @stream
3) @slow
148) 1) "lpush"
2) (integer) -3
3) 1) write
2) denyoom
3) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @list
3) @fast
149) 1) "scan"
2) (integer) -2
3) 1) readonly
2) random
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @keyspace
2) @read
3) @slow
150) 1) "getbit"
2) (integer) 3
3) 1) readonly
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @bitmap
3) @fast
151) 1) "geosearch"
2) (integer) -7
3) 1) readonly
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @geo
3) @slow
152) 1) "unsubscribe"
2) (integer) -1
3) 1) pubsub
2) noscript
3) loading
4) stale
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @pubsub
2) @slow
153) 1) "zinterstore"
2) (integer) -4
3) 1) write
2) denyoom
3) movablekeys
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @sortedset
3) @slow
154) 1) "geohash"
2) (integer) -2
3) 1) readonly
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @geo
3) @slow
155) 1) "bitfield"
2) (integer) -2
3) 1) write
2) denyoom
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @bitmap
3) @slow
156) 1) "bitop"
2) (integer) -4
3) 1) write
2) denyoom
4) (integer) 2
5) (integer) -1
6) (integer) 1
7) 1) @write
2) @bitmap
3) @slow
157) 1) "get"
2) (integer) 2
3) 1) readonly
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @string
3) @fast
158) 1) "xread"
2) (integer) -4
3) 1) readonly
2) movablekeys
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @read
2) @stream
3) @slow
4) @blocking
159) 1) "bitfield_ro"
2) (integer) -2
3) 1) readonly
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @bitmap
3) @fast
160) 1) "sunionstore"
2) (integer) -3
3) 1) write
2) denyoom
4) (integer) 1
5) (integer) -1
6) (integer) 1
7) 1) @write
2) @set
3) @slow
161) 1) "decrby"
2) (integer) 3
3) 1) write
2) denyoom
3) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @string
3) @fast
162) 1) "sort"
2) (integer) -2
3) 1) write
2) denyoom
3) movablekeys
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @set
3) @sortedset
4) @list
5) @slow
6) @dangerous
163) 1) "hmget"
2) (integer) -3
3) 1) readonly
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @hash
3) @fast
164) 1) "sdiff"
2) (integer) -2
3) 1) readonly
2) sort_for_script
4) (integer) 1
5) (integer) -1
6) (integer) 1
7) 1) @read
2) @set
3) @slow
165) 1) "evalsha"
2) (integer) -3
3) 1) noscript
2) skip_monitor
3) may_replicate
4) movablekeys
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @slow
2) @scripting
166) 1) "psetex"
2) (integer) 4
3) 1) write
2) denyoom
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @string
3) @slow
167) 1) "client"
2) (integer) -2
3) 1) admin
2) noscript
3) random
4) loading
5) stale
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @admin
2) @slow
3) @dangerous
4) @connection
168) 1) "sinter"
2) (integer) -2
3) 1) readonly
2) sort_for_script
4) (integer) 1
5) (integer) -1
6) (integer) 1
7) 1) @read
2) @set
3) @slow
169) 1) "zpopmax"
2) (integer) -2
3) 1) write
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @sortedset
3) @fast
170) 1) "publish"
2) (integer) 3
3) 1) pubsub
2) loading
3) stale
4) fast
5) may_replicate
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @pubsub
2) @fast
171) 1) "subscribe"
2) (integer) -2
3) 1) pubsub
2) noscript
3) loading
4) stale
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @pubsub
2) @slow
172) 1) "xadd"
2) (integer) -5
3) 1) write
2) denyoom
3) random
4) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @stream
3) @fast
173) 1) "swapdb"
2) (integer) 3
3) 1) write
2) fast
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @keyspace
2) @write
3) @fast
4) @dangerous
174) 1) "lrem"
2) (integer) 4
3) 1) write
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @list
3) @slow
175) 1) "llen"
2) (integer) 2
3) 1) readonly
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @list
3) @fast
176) 1) "select"
2) (integer) 2
3) 1) loading
2) stale
3) fast
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @keyspace
2) @fast
177) 1) "wait"
2) (integer) 3
3) 1) noscript
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @keyspace
2) @slow
178) 1) "time"
2) (integer) 1
3) 1) random
2) loading
3) stale
4) fast
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @fast
179) 1) "brpoplpush"
2) (integer) 4
3) 1) write
2) denyoom
3) noscript
4) (integer) 1
5) (integer) 2
6) (integer) 1
7) 1) @write
2) @list
3) @slow
4) @blocking
180) 1) "setex"
2) (integer) 4
3) 1) write
2) denyoom
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @string
3) @slow
181) 1) "touch"
2) (integer) -2
3) 1) readonly
2) fast
4) (integer) 1
5) (integer) -1
6) (integer) 1
7) 1) @keyspace
2) @read
3) @fast
182) 1) "hlen"
2) (integer) 2
3) 1) readonly
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @hash
3) @fast
183) 1) "echo"
2) (integer) 2
3) 1) fast
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @fast
2) @connection
184) 1) "sismember"
2) (integer) 3
3) 1) readonly
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @set
3) @fast
185) 1) "command"
2) (integer) -1
3) 1) random
2) loading
3) stale
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @slow
2) @connection
186) 1) "xlen"
2) (integer) 2
3) 1) readonly
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @stream
3) @fast
187) 1) "xdel"
2) (integer) -3
3) 1) write
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @stream
3) @fast
188) 1) "slowlog"
2) (integer) -2
3) 1) admin
2) random
3) loading
4) stale
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @admin
2) @slow
3) @dangerous
189) 1) "bzpopmax"
2) (integer) -3
3) 1) write
2) noscript
3) fast
4) (integer) 1
5) (integer) -2
6) (integer) 1
7) 1) @write
2) @sortedset
3) @fast
4) @blocking
190) 1) "hsetnx"
2) (integer) 4
3) 1) write
2) denyoom
3) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @hash
3) @fast
191) 1) "expire"
2) (integer) 3
3) 1) write
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @keyspace
2) @write
3) @fast
192) 1) "ping"
2) (integer) -1
3) 1) stale
2) fast
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @fast
2) @connection
193) 1) "bzpopmin"
2) (integer) -3
3) 1) write
2) noscript
3) fast
4) (integer) 1
5) (integer) -2
6) (integer) 1
7) 1) @write
2) @sortedset
3) @fast
4) @blocking
194) 1) "memory"
2) (integer) -2
3) 1) readonly
2) random
3) movablekeys
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @read
2) @slow
195) 1) "xrevrange"
2) (integer) -4
3) 1) readonly
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @stream
3) @slow
196) 1) "pfadd"
2) (integer) -2
3) 1) write
2) denyoom
3) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @hyperloglog
3) @fast
197) 1) "config"
2) (integer) -2
3) 1) admin
2) noscript
3) loading
4) stale
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @admin
2) @slow
3) @dangerous
198) 1) "hmset"
2) (integer) -4
3) 1) write
2) denyoom
3) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @hash
3) @fast
199) 1) "acl"
2) (integer) -2
3) 1) admin
2) noscript
3) loading
4) stale
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @admin
2) @slow
3) @dangerous
200) 1) "xrange"
2) (integer) -4
3) 1) readonly
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @stream
3) @slow
201) 1) "zpopmin"
2) (integer) -2
3) 1) write
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @sortedset
3) @fast
202) 1) "lpushx"
2) (integer) -3
3) 1) write
2) denyoom
3) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @list
3) @fast
203) 1) "auth"
2) (integer) -2
3) 1) noscript
2) loading
3) stale
4) fast
5) no_auth
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @fast
2) @connection
204) 1) "pfmerge"
2) (integer) -2
3) 1) write
2) denyoom
4) (integer) 1
5) (integer) -1
6) (integer) 1
7) 1) @write
2) @hyperloglog
3) @slow
205) 1) "getrange"
2) (integer) 4
3) 1) readonly
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @string
3) @slow
206) 1) "bitcount"
2) (integer) -2
3) 1) readonly
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @bitmap
3) @slow
207) 1) "getex"
2) (integer) -2
3) 1) write
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @string
3) @fast
208) 1) "psubscribe"
2) (integer) -2
3) 1) pubsub
2) noscript
3) loading
4) stale
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @pubsub
2) @slow
209) 1) "smembers"
2) (integer) 2
3) 1) readonly
2) sort_for_script
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @set
3) @slow
210) 1) "cluster"
2) (integer) -2
3) 1) admin
2) random
3) stale
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @admin
2) @slow
3) @dangerous
211) 1) "zremrangebyrank"
2) (integer) 4
3) 1) write
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @sortedset
3) @slow
212) 1) "pfcount"
2) (integer) -2
3) 1) readonly
2) may_replicate
4) (integer) 1
5) (integer) -1
6) (integer) 1
7) 1) @read
2) @hyperloglog
3) @slow
213) 1) "bitpos"
2) (integer) -3
3) 1) readonly
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @bitmap
3) @slow
214) 1) "latency"
2) (integer) -2
3) 1) admin
2) noscript
3) loading
4) stale
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @admin
2) @slow
3) @dangerous
215) 1) "hincrbyfloat"
2) (integer) 4
3) 1) write
2) denyoom
3) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @hash
3) @fast
216) 1) "mset"
2) (integer) -3
3) 1) write
2) denyoom
4) (integer) 1
5) (integer) -1
6) (integer) 2
7) 1) @write
2) @string
3) @slow
217) 1) "asking"
2) (integer) 1
3) 1) fast
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @keyspace
2) @fast
218) 1) "xtrim"
2) (integer) -4
3) 1) write
2) random
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @stream
3) @slow
219) 1) "hset"
2) (integer) -4
3) 1) write
2) denyoom
3) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @hash
3) @fast
220) 1) "sinterstore"
2) (integer) -3
3) 1) write
2) denyoom
4) (integer) 1
5) (integer) -1
6) (integer) 1
7) 1) @write
2) @set
3) @slow
221) 1) "module"
2) (integer) -2
3) 1) admin
2) noscript
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @admin
2) @slow
3) @dangerous
222) 1) "eval"
2) (integer) -3
3) 1) noscript
2) skip_monitor
3) may_replicate
4) movablekeys
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @slow
2) @scripting
223) 1) "getset"
2) (integer) 3
3) 1) write
2) denyoom
3) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @string
3) @fast
224) 1) "georadius_ro"
2) (integer) -6
3) 1) readonly
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @geo
3) @slow
可用版本>= 2.8.13.
时间复杂度: O(N) where N is the total number of Redis commands
1.11.10 COMMAND COUNT
Redis Command Count 命令用于统计 redis 命令的个数。
语法:
1
127.0.0.1:6379> COMMAND COUNT
返回值:
整数: 支持的命令类型总数。
实例:
1
2
3127.0.0.1:6379> COMMAND COUNT
(integer) 224
127.0.0.1:6379>
可用版本>= 2.8.13.
时间复杂度: O(1)
1.11.11 COMMAND GETKEYS
以数据的形式检测一个 Redis 命令 中的 key。
COMMAND GETKEYS是一个辅助命令,让你可以从 Redis 命令中找到key。
COMMAND显示了某些命令拥有可变位置的key,这意味着必须分析完整的命令才能找到要存储或者检索的 key。 你可以使用COMMAND GETKEYS直接从 Redis 解析命令的方式来发现 key 的位置。
语法:
1
127.0.0.1:6379> COMMAND GETKEYS
返回值:
数组: 命令参数中的 key。
实例:
1
2
3
4
5
6
7
8
9
10
11
12127.0.0.1:6379> COMMAND GETKEYS MSET a b c d e f
1) "a"
2) "c"
3) "e"
127.0.0.1:6379> COMMAND GETKEYS EVAL "not consulted" 3 key1 key2 key3 arg1 arg2 arg3 argN
1) "key1"
2) "key2"
3) "key3"
127.0.0.1:6379> COMMAND GETKEYS SORT mylist ALPHA STORE outlist
1) "mylist"
2) "outlist"
127.0.0.1:6379>
可用版本>= 2.8.13.
时间复杂度: O(N) where N is the number of arguments to the command
1.11.12 TIME
TIME 命令返回当前服务器的时间,包含两个条目 Unix 时间戳和这一秒已经过去的微秒数。基本上,该接口非常相似 gettimeofday。
语法:
1
127.0.0.1:6379> TIME
返回值:
数组:
返回内容包含两个元素
- UNIX时间戳(单位:秒)
- 微秒
实例:
1
2
3
4
5
6
7127.0.0.1:6379> TIME
1) "1653066894"
2) "387030"
127.0.0.1:6379> TIME
1) "1653066896"
2) "328152"
127.0.0.1:6379>
可用版本>= 2.6.0.
时间复杂度: O(1)
1.11.13 COMMAND INFO
以数组的形式返回多个Redis命令的详细信息。
此命令返回的结果与COMMAND
相同,但是你可以指定返回哪些命令。
如果你指定了一些不存在的命令,那么在它们的返回位置将会是nil。
语法:
1
127.0.0.1:6379> COMMAND INFO command-name [command-name ...]
返回值:
数组: 命令信息
实例:
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59127.0.0.1:6379> COMMAND INFO get set eval
1) 1) "get"
2) (integer) 2
3) 1) readonly
2) fast
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @read
2) @string
3) @fast
2) 1) "set"
2) (integer) -3
3) 1) write
2) denyoom
4) (integer) 1
5) (integer) 1
6) (integer) 1
7) 1) @write
2) @string
3) @slow
3) 1) "eval"
2) (integer) -3
3) 1) noscript
2) skip_monitor
3) may_replicate
4) movablekeys
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @slow
2) @scripting
127.0.0.1:6379> COMMAND INFO foo evalsha config bar
1) (nil)
2) 1) "evalsha"
2) (integer) -3
3) 1) noscript
2) skip_monitor
3) may_replicate
4) movablekeys
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @slow
2) @scripting
3) 1) "config"
2) (integer) -2
3) 1) admin
2) noscript
3) loading
4) stale
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @admin
2) @slow
3) @dangerous
4) (nil)
127.0.0.1:6379>
可用版本>= 2.8.13.
时间复杂度: O(N) when N is number of commands to look up
1.11.14 CONFIG GET
Redis Config Get
命令用于获取 redis 服务的配置参数。
在 Redis 2.4 版本中, 有部分参数没有办法用 CONFIG GET 访问,但是在最新的 Redis 2.6 版本中,所有配置参数都已经可以用 CONFIG GET 访问了。
CONFIG GET
对应的是修改运行时参数的命令CONFIG SET
.
CONFIG GET
命令只接受一个 glob 风格的正则参数,所有配置参数都采用key-value的形式。 例如:
1
2
3
4
5
6
7 redis> config get *max-*-entries*
1) "hash-max-zipmap-entries"
2) "512"
3) "list-max-ziplist-entries"
4) "512"
5) "set-max-intset-entries"
6) "512"通过
redis-cli
提示符下输入 CONFIG GET * 可以查看 Redis 所有支持的参数。所有支持的参数都与 redis.conf 里面的一样,除了如下的重要差异:
10kb
、2gb
这些在配置文件中所使用的储存单位缩写,不可以用在CONFIG
命令中,CONFIG SET
的值只能通过数字值显式地设定。像CONFIG SET xxx 1k
这样的命令是错误的,正确的格式是CONFIG SET xxx 1000
。save
选项在 redis.conf 中是用多行文字储存的,但在CONFIG GET
命令中,它只打印一行文字。例如,redis.conf 里面的有如下配置:
1
2 save 900 1
save 300 10它的意思是:如果900秒内有一个数据发生变化,或者300秒内有10个数据发生变化则执行
SAVE
,那么使用CONFIG GET
查看时将会看到 “900 1 300 10”。
语法:
1
127.0.0.1:6379> CONFIG GET parameter
返回值:
数组: 给定配置参数的值。
实例:
1
2
3
4
5
6
7
8127.0.0.1:6379> config get *max-*-entries*
1) "hash-max-ziplist-entries"
2) "512"
3) "set-max-intset-entries"
4) "512"
5) "zset-max-ziplist-entries"
6) "128"
127.0.0.1:6379>
可用版本>= 2.0.0.
1.11.15 CONFIG REWRITE
Redis CONFIG REWRITE 命令对启动 Redis 服务器时所指定的 redis.conf 配置文件进行改写。
CONFIG SET 命令可以对服务器的当前配置进行修改, 而修改后的配置可能和 redis.conf 文件中所描述的配置不一样, CONFIG REWRITE 的作用就是通过尽可能少的修改, 将服务器当前所使用的配置记录到 redis.conf
文件中。
重写以非常保守的方式执行:
- 注释和原始 redis.conf 文件的整体结构会尽可能的保留下来。
- 如果一个选项在旧的 redis.conf 文件中已经存在,那么它会在相同的位置(行号)被重写。
- 如果某个选项在配置文件中尚不存在,但被设置为了该选项的默认值,那么他将不会被重写进程写入配置文件。
- 如果某个选项在配置文件中尚不存在,但被设置了一个非默认值,那么它会被追加到文件的末尾。
- 未使用的行将会留空。例如,如果你之前在配置文件中有多个
save
配置项,但由于你禁用了 RDB 持久化,当前的save
配置变少了或者变为空,那么所有的那些行将会是空行。如果原始文件由于某些原因不再存在,CONFIG REWRITE 也能够从头开始重写配置文件。但是,如果服务器启动的时候没有指定任何配置文件,则 CONFIG REWRITE 将只会返回一个错误。
原子重写过程
为了保证redis.conf文件始终是一致的,也即,在异常或者崩溃的时候,你的配置文件要么是旧的文件,或者是重写完的新文件。重写是通过一次具有足够内容的
write(2)
调用来执行的,至少和旧的文件一样大。有时会以注释的形式添加额外的padding,以确保生成的文件足够大,稍后文件会被截断以删除末尾的padding。
语法:
1
127.0.0.1:6379> CONFIG REWRITE parameter
返回值:
字符串: 当配置被正确重写时返回
OK
,否则返回错误。实例:
以下是执行 CONFIG REWRITE 前, 被载入到 Redis 服务器的 redis.conf 文件中关于 appendonly 选项的设置:
1
2
3
4
5... 其他选项
appendonly no
... 其他选项在执行以下命令之后:
1
2
3
4
5
6
7
8
9
10
11127.0.0.1:6379> CONFIG GET appendonly # appendonly 处于关闭状态
1) "appendonly"
2) "no"
127.0.0.1:6379> CONFIG SET appendonly yes # 打开 appendonly
OK
127.0.0.1:6379> CONFIG GET appendonly
1) "appendonly"
2) "yes"
127.0.0.1:6379> CONFIG REWRITE # 将 appendonly 的修改写入到 redis.conf 中
OK
127.0.0.1:6379>重写后的 redis.conf 文件中的 appendonly 选项将被改写:
1
2
3
4
5... 其他选项
appendonly yes
... 其他选项
可用版本>= 2.8.0.
1.11.16 CONFIG SET
CONFIG SET 命令用于在服务器运行期间重写某些配置,而不用重启 Redis。可以使用此命令更改不重要的参数或从一个参数切换到另一个持久性选项。
可以通过 CONFIG GET *
获得CONFIG SET
命令支持的配置参数列表,该命令是用于获取有关正在运行的 Redis 实例的配置信息的对称命令。
所有使用
CONFIG SET
设置的配置参数将会立即被 Redis 加载,并从下一个执行的命令开始生效。所有支持的参数与 [redis.conf][hgcarr22rc] 文件中使用的等效配置参数具有相同含义,但有以下重要区别:
- 在指定字节或其他数量的选项中,不能使用在
redis.conf
中使用的简写形式(如10k
,2gb
等),所有内容都应该指定为格式良好的64位整数,以配置指令的基本单位表示。但从Redis3.0以及更高版本开始,可以将CONFIG SET
与内存单元一起用于maxmemory
、客户端输出缓冲以及复制积压大小(repl-backlog-size)指定内存单位。- save参数是一个以空格分隔的整数字符串。每对整数代表一个秒/修改阈值。
例如在
redis.conf
中看起来像这样:
1
2 save 900 1
save 300 10这意味着,如果数据集有 1 个以上变更,则在 900 秒后保存;如果有 10 个以上变更,则在 300 秒后就保存,应使用
CONFIG SET SAVE
“900 1 300 10” 来设置。可以使用
CONFIG SET
命令将持久化从 RDB 快照切换到 AOF 文件(或其他相似的方式)。 有关如何执行此操作的详细信息,请查看persistencepage。一般来说,你应该知道将
appendonly
参数设置为yes
将启动后台进程以保存初始 AOF 文件(从内存数据集中获取),并将所有后续命令追加到 AOF 文件,从而达到了与一个 Redis 服务器从一开始就开启了 AOF 选项相同的效果。如果你愿意,可以同时开启 AOF 和 RDB 快照,这两个选项不是互斥的。
语法:
1
127.0.0.1:6379> CONFIG Set parameter value
返回值:
字符串: 当配置被正确设置时返回
OK
,否则将返回错误。实例:
1
2
3
4
5
6
7
8
9127.0.0.1:6379> CONFIG GET slowlog-max-len
1) "slowlog-max-len"
2) "128"
127.0.0.1:6379> CONFIG SET slowlog-max-len 10086
OK
127.0.0.1:6379> CONFIG GET slowlog-max-len
1) "slowlog-max-len"
2) "10086"
127.0.0.1:6379>
可用版本>= 2.0.0.
1.11.17 CONFIG RESETSTAT
Redis CONFIG RESETSTAT 命令用于重置 INFO 命令中的某些统计数据,包括:
1 | - Keyspace hits (键空间命中次数) |
语法:
1
127.0.0.1:6379> CONFIG RESETSTAT
返回值:
字符串:
OK
.实例:
重置前 INFO 命令输出信息:
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181127.0.0.1:6379> INFO
Server
redis_version:6.2.6
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:eac5b3c736e2a107
redis_mode:standalone
os:Linux 3.10.0-1160.el7.x86_64 x86_64
arch_bits:64
multiplexing_api:epoll
atomicvar_api:atomic-builtin
gcc_version:4.8.5
process_id:17277
process_supervised:no
run_id:4884ead059e4a0ad9cb88e2231856af69ff9ac7e
tcp_port:6379
server_time_usec:1653069721652249
uptime_in_seconds:128889
uptime_in_days:1
hz:10
configured_hz:10
lru_clock:8902553
executable:/opt/software/redis-6.2.6/./src/redis-server
config_file:/opt/software/redis-6.2.6/./redis.conf
io_threads_active:0
Clients
connected_clients:1
cluster_connections:0
maxclients:10000
client_recent_max_input_buffer:0
client_recent_max_output_buffer:0
blocked_clients:0
tracking_clients:0
clients_in_timeout_table:0
Memory
used_memory:879352
used_memory_human:858.74K
used_memory_rss:3055616
used_memory_rss_human:2.91M
used_memory_peak:977792
used_memory_peak_human:954.88K
used_memory_peak_perc:89.93%
used_memory_overhead:811872
used_memory_startup:810112
used_memory_dataset:67480
used_memory_dataset_perc:97.46%
allocator_allocated:988920
allocator_active:1265664
allocator_resident:3502080
total_system_memory:1019572224
total_system_memory_human:972.34M
used_memory_lua:43008
used_memory_lua_human:42.00K
used_memory_scripts:248
used_memory_scripts_human:248B
number_of_cached_scripts:2
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction
allocator_frag_ratio:1.28
allocator_frag_bytes:276744
allocator_rss_ratio:2.77
allocator_rss_bytes:2236416
rss_overhead_ratio:0.87
rss_overhead_bytes:-446464
mem_fragmentation_ratio:3.75
mem_fragmentation_bytes:2239976
mem_not_counted_for_evict:0
mem_replication_backlog:0
mem_clients_slaves:0
mem_clients_normal:0
mem_aof_buffer:0
mem_allocator:jemalloc-5.1.0
active_defrag_running:0
lazyfree_pending_objects:0
lazyfreed_objects:0
Persistence
loading:0
current_cow_size:0
current_cow_size_age:0
current_fork_perc:0.00
current_save_keys_processed:0
current_save_keys_total:0
rdb_changes_since_last_save:0
rdb_bgsave_in_progress:0
rdb_last_save_time:1653062505
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:0
rdb_current_bgsave_time_sec:-1
rdb_last_cow_size:475136
aof_enabled:0
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok
aof_last_cow_size:561152
module_fork_in_progress:0
module_fork_last_cow_size:0
Stats
total_connections_received:95
total_commands_processed:933
instantaneous_ops_per_sec:0
total_net_input_bytes:36763
total_net_output_bytes:432050
instantaneous_input_kbps:0.00
instantaneous_output_kbps:0.00
rejected_connections:0
sync_full:0
sync_partial_ok:0
sync_partial_err:0
expired_keys:0
expired_stale_perc:0.00
expired_time_cap_reached_count:0
expire_cycle_cpu_milliseconds:6902
evicted_keys:0
keyspace_hits:194
keyspace_misses:13
pubsub_channels:0
pubsub_patterns:0
latest_fork_usec:668
total_forks:76
migrate_cached_sockets:0
slave_expires_tracked_keys:0
active_defrag_hits:0
active_defrag_misses:0
active_defrag_key_hits:0
active_defrag_key_misses:0
tracking_total_keys:0
tracking_total_items:0
tracking_total_prefixes:0
unexpected_error_replies:0
total_error_replies:84
dump_payload_sanitizations:0
total_reads_processed:944
total_writes_processed:931
io_threaded_reads_processed:0
io_threaded_writes_processed:0
Replication
role:master
connected_slaves:0
master_failover_state:no-failover
master_replid:5747e010248e99df63f6fc7132cd4f5e778e4c23
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
CPU
used_cpu_sys:250.581855
used_cpu_user:278.320178
used_cpu_sys_children:0.452773
used_cpu_user_children:0.073380
used_cpu_sys_main_thread:250.516158
used_cpu_user_main_thread:278.278268
Modules
Errorstats
errorstat_ERR:count=51
errorstat_NOAUTH:count=13
errorstat_NOTBUSY:count=3
errorstat_WRONGPASS:count=4
errorstat_WRONGTYPE:count=13
Cluster
cluster_enabled:0
Keyspace
db0:keys=21,expires=0,avg_ttl=0
db1:keys=5,expires=0,avg_ttl=0
db2:keys=3,expires=0,avg_ttl=0重置后查看 INFO 命令输出信息:
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181重置操作
127.0.0.1:6379> CONFIG RESETSTAT
OK
重置后查看 INFO 命令输出信息:
127.0.0.1:6379> INFO
Server
redis_version:6.2.6
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:eac5b3c736e2a107
redis_mode:standalone
os:Linux 3.10.0-1160.el7.x86_64 x86_64
arch_bits:64
multiplexing_api:epoll
atomicvar_api:atomic-builtin
gcc_version:4.8.5
process_id:17277
process_supervised:no
run_id:4884ead059e4a0ad9cb88e2231856af69ff9ac7e
tcp_port:6379
server_time_usec:1653069741529106
uptime_in_seconds:128909
uptime_in_days:1
hz:10
configured_hz:10
lru_clock:8902573
executable:/opt/software/redis-6.2.6/./src/redis-server
config_file:/opt/software/redis-6.2.6/./redis.conf
io_threads_active:0
Clients
connected_clients:1
cluster_connections:0
maxclients:10000
client_recent_max_input_buffer:24
client_recent_max_output_buffer:0
blocked_clients:0
tracking_clients:0
clients_in_timeout_table:0
Memory
used_memory:879048
used_memory_human:858.45K
used_memory_rss:3051520
used_memory_rss_human:2.91M
used_memory_peak:977792
used_memory_peak_human:954.88K
used_memory_peak_perc:89.90%
used_memory_overhead:832376
used_memory_startup:810112
used_memory_dataset:46672
used_memory_dataset_perc:67.70%
allocator_allocated:1026488
allocator_active:1343488
allocator_resident:3624960
total_system_memory:1019572224
total_system_memory_human:972.34M
used_memory_lua:43008
used_memory_lua_human:42.00K
used_memory_scripts:248
used_memory_scripts_human:248B
number_of_cached_scripts:2
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction
allocator_frag_ratio:1.31
allocator_frag_bytes:317000
allocator_rss_ratio:2.70
allocator_rss_bytes:2281472
rss_overhead_ratio:0.84
rss_overhead_bytes:-573440
mem_fragmentation_ratio:3.65
mem_fragmentation_bytes:2215232
mem_not_counted_for_evict:0
mem_replication_backlog:0
mem_clients_slaves:0
mem_clients_normal:20504
mem_aof_buffer:0
mem_allocator:jemalloc-5.1.0
active_defrag_running:0
lazyfree_pending_objects:0
lazyfreed_objects:0
Persistence
loading:0
current_cow_size:0
current_cow_size_age:0
current_fork_perc:0.00
current_save_keys_processed:0
current_save_keys_total:0
rdb_changes_since_last_save:0
rdb_bgsave_in_progress:0
rdb_last_save_time:1653062505
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:0
rdb_current_bgsave_time_sec:-1
rdb_last_cow_size:475136
aof_enabled:0
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok
aof_last_cow_size:561152
module_fork_in_progress:0
module_fork_last_cow_size:0
Stats
total_connections_received:0
total_commands_processed:1
instantaneous_ops_per_sec:0
total_net_input_bytes:14
total_net_output_bytes:5
instantaneous_input_kbps:0.00
instantaneous_output_kbps:0.00
rejected_connections:0
sync_full:0
sync_partial_ok:0
sync_partial_err:0
expired_keys:0
expired_stale_perc:0.00
expired_time_cap_reached_count:0
expire_cycle_cpu_milliseconds:0
evicted_keys:0
keyspace_hits:0
keyspace_misses:0
pubsub_channels:0
pubsub_patterns:0
latest_fork_usec:0
total_forks:0
migrate_cached_sockets:0
slave_expires_tracked_keys:0
active_defrag_hits:0
active_defrag_misses:0
active_defrag_key_hits:0
active_defrag_key_misses:0
tracking_total_keys:0
tracking_total_items:0
tracking_total_prefixes:0
unexpected_error_replies:0
total_error_replies:0
dump_payload_sanitizations:0
total_reads_processed:1
total_writes_processed:1
io_threaded_reads_processed:0
io_threaded_writes_processed:0
Replication
role:master
connected_slaves:0
master_failover_state:no-failover
master_replid:5747e010248e99df63f6fc7132cd4f5e778e4c23
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
CPU
used_cpu_sys:250.620934
used_cpu_user:278.359987
used_cpu_sys_children:0.452773
used_cpu_user_children:0.073380
used_cpu_sys_main_thread:250.556253
used_cpu_user_main_thread:278.316859
Modules
Errorstats
Cluster
cluster_enabled:0
Keyspace
db0:keys=21,expires=0,avg_ttl=0
db1:keys=5,expires=0,avg_ttl=0
db2:keys=3,expires=0,avg_ttl=0
127.0.0.1:6379>
可用版本>= 2.0.0.
时间复杂度: O(1)
1.11.18 DBSIZE
Redis DBSIZE 返回当前数据库中 key 的数量。
语法:
1
127.0.0.1:6379> DBSIZE
返回值:
整数:当前数据库中 key 的数量。
实例:
1
2
3
4
5
6
7
8127.0.0.1:6379> DBSIZE
(integer) 21
增加一个key,再看看效果
127.0.0.1:6379> SET new_key "hello kungs"
OK
127.0.0.1:6379> DBSIZE
(integer) 22
127.0.0.1:6379>
可用版本>= 1.0.0.
1.11.19 DEBUG OBJECT
Redis DEBUG OBJECT 是一个调试命令,它不应该被客户端所使用。
查看 OBJECT 命令获取更多信息。
语法:
1
127.0.0.1:6379> DEBUG OBJECT key
返回值:
字符串: 当
key
存在时,返回有关信息。 当key
不存在时,返回 (error) ERR no such key。实例:
1
2
3
4
5
6
7127.0.0.1:6379> SET new_key "hello kungs"
OK
127.0.0.1:6379> DEBUG OBJECT new_key
Value at:0x7fceb660e9e0 refcount:1 encoding:embstr serializedlength:12 lru:8902992 lru_seconds_idle:4
127.0.0.1:6379> DEBUG OBJECT new_key1
(error) ERR no such key
127.0.0.1:6379>
可用版本>= 1.0.0.
1.11.20 DEBUG SEGFAULT
DEBUG SEGFAULT 执行一个不合法的内存访问从而让 Redis 崩溃,仅在开发时用于模拟 BUG 。
语法:
1
127.0.0.1:6379> DEBUG SEGFAULT
返回值:
字符串
实例:
1
2
3
4127.0.0.1:6379> DEBUG SEGFAULT
Error: Server closed the connection
(0.69s)
127.0.0.1:6379>
可用版本>= 1.0.0.
1.11.21 FLUSHALL
清空整个 Redis 中的数据(清空所有数据库的所有 key,不仅仅是当前 select 的数据库 )。
此命令不会失败。
FLUSHALL ASYNC
(Redis 4.0.0 or greater):支持在后台单独的线程执行删除 key 的操作而不阻塞 Redis。
FLUSHALL 和
FLUSHDB
增加了ASYNC
来使整个数据集或单个数据库异步释放。异步
FLUSHALL
和FLUSHDB
命令仅仅删除它们被调用时已经存在的 key。命令调用之后,删除 key 的过程中新建的 key 不受影响。
语法:
1
127.0.0.1:6379> FLUSHALL
返回值:
字符串:
OK
实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
210 号数据库的 key 数量
127.0.0.1:6379> DBSIZE
(integer) 22
切换到 1 号数据库
127.0.0.1:6379> SELECT 1
OK
1 号数据库的 key 数量
127.0.0.1:6379[1]> DBSIZE
(integer) 5
清空所有数据库的所有 key
127.0.0.1:6379[1]> FLUSHALL
OK
不但 1 号数据库被清空了
127.0.0.1:6379[1]> DBSIZE
(integer) 0
0 号数据库(以及其他所有数据库)也一样
127.0.0.1:6379[1]> SELECT 0
OK
127.0.0.1:6379> DBSIZE
(integer) 0
127.0.0.1:6379>
可用版本>= 1.0.0.
时间复杂度是 O(N), N 代表所有数据库中 key 的总数。
1.11.22 FLUSHDB
清空当前 select
数据库中的所有 key。此命令不会失败。
语法:
1
127.0.0.1:6379> FLUSHDB
返回值:
字符串:
OK
实例:
1
2
3
4
5
6
7
8清空前的 key 数量
127.0.0.1:6379> DBSIZE
(integer) 4
127.0.0.1:6379> FLUSHDB
OK
清空后的 key 数量
redis 127.0.0.1:6379> DBSIZE
(integer) 0
可用版本>= 1.0.0.
时间复杂度是 O(N), N 代表当前数据库中 key 的总数。
1.11.23 INFO
INFO
命令以一种易于理解和阅读的格式,返回关于Redis服务器的各种信息和统计数值。
通过给定可选的参数 section ,可以让命令只返回某一部分的信息:
server
: 查看 Redis 服务器信息,如 Redis 的版本clients
: 客户端的连接部分memory
: 内存消耗相关信息persistence
: RDB和AOF相关信息stats
: 一般统计replication
: 主/从复制信息cpu
: 统计CPU的消耗commandstats
: Redis命令统计cluster
: Redis集群信息keyspace
: 数据库的相关统计modules
: Module 相关信息它也可以采取以下值:
all
: 返回所有信息default
: 值返回默认设置的信息everything
: 包括all
和modules
如果没有使用任何参数时,默认为
default
。注意:
请注意不同Redis版本会添加或者删除一些字段。一个健壮的客户端应用解析该命令的结果时,应该跳过未知的字段,并且优雅的处理缺少的字段。
以下是Redis >= 2.4的字段说明。
下面是所有 server 相关的信息:
redis_version
: Redis 服务器版本redis_git_sha1
: Git SHA1redis_git_dirty
: Git dirty flagredis_build_id
: 构建IDredis_mode
: 服务器模式(standalone,sentinel或者cluster)os
: Redis 服务器的宿主操作系统arch_bits
: 架构(32 或 64 位)multiplexing_api
: Redis 所使用的事件处理机制atomicvar_api
: Redis使用的Atomicvar APIgcc_version
: 编译 Redis 时所使用的 GCC 版本process_id
: 服务器进程的 PIDrun_id
: Redis 服务器的随机标识符(用于 Sentinel 和集群)tcp_port
: TCP/IP 监听端口uptime_in_seconds
: 自 Redis 服务器启动以来,经过的秒数uptime_in_days
: 自 Redis 服务器启动以来,经过的天数hz
: 服务器的频率设置lru_clock
: 以分钟为单位进行自增的时钟,用于 LRU 管理executable
: 服务器的可执行文件路径config_file
: 配置文件路径下面是所有 clients 相关的信息:
connected_clients
: 已连接客户端的数量(不包括通过从属服务器连接的客户端)client_longest_output_list
: 当前连接的客户端当中,最长的输出列表client_biggest_input_buf
: 当前连接的客户端当中,最大输入缓存blocked_clients
: 正在等待阻塞命令(BLPOP、BRPOP、BRPOPLPUSH)的客户端的数量下面是所有 memory 相关的信息:
used_memory
: 由 Redis 分配器分配的内存总量,以字节(byte)为单位used_memory_human
: 以人类可读的格式返回 Redis 分配的内存总量used_memory_rss
: 从操作系统的角度,返回 Redis 已分配的内存总量(俗称常驻集大小)。这个值和 top 、 ps 等命令的输出一致。used_memory_peak
: Redis 的内存消耗峰值(以字节为单位)used_memory_peak_human
: 以人类可读的格式返回 Redis 的内存消耗峰值used_memory_peak_perc
: 使用内存占峰值内存的百分比used_memory_overhead
: 服务器为管理其内部数据结构而分配的所有开销的总和(以字节为单位)used_memory_startup
: Redis在启动时消耗的初始内存大小(以字节为单位)used_memory_dataset
: 以字节为单位的数据集大小(usedmemory减去usedmemory_overhead)used_memory_dataset_perc
: usedmemorydataset占净内存使用量的百分比(usedmemory减去usedmemory_startup)total_system_memory
: Redis主机具有的内存总量total_system_memory_human
: 以人类可读的格式返回 Redis主机具有的内存总量used_memory_lua
: Lua 引擎所使用的内存大小(以字节为单位)used_memory_lua_human
: 以人类可读的格式返回 Lua 引擎所使用的内存大小maxmemory
: maxmemory配置指令的值maxmemory_human
: 以人类可读的格式返回 maxmemory配置指令的值maxmemory_policy
: maxmemory-policy配置指令的值mem_fragmentation_ratio
:used_memory_rss
和used_memory
之间的比率mem_allocator
: 在编译时指定的, Redis 所使用的内存分配器。可以是 libc 、 jemalloc 或者 tcmalloc 。active_defrag_running
: 指示活动碎片整理是否处于活动状态的标志lazyfree_pending_objects
: 等待释放的对象数(由于使用ASYNC选项调用UNLINK或FLUSHDB和FLUSHALL)在理想情况下, usedmemoryrss 的值应该只比 used_memory 稍微高一点儿。
当 rss > used ,且两者的值相差较大时,表示存在(内部或外部的)内存碎片。
内存碎片的比率可以通过 memfragmentationratio 的值看出。
当 used > rss 时,表示 Redis 的部分内存被操作系统换出到交换空间了,在这种情况下,操作可能会产生明显的延迟。
由于Redis无法控制其分配的内存如何映射到内存页,因此常住内存(usedmemoryrss)很高通常是内存使用量激增的结果。
当 Redis 释放内存时,内存将返回给分配器,分配器可能会,也可能不会,将内存返还给操作系统。
如果 Redis 释放了内存,却没有将内存返还给操作系统,那么 used_memory 的值可能和操作系统显示的 Redis 内存占用并不一致。
查看 usedmemorypeak 的值可以验证这种情况是否发生。
要获得有关服务器内存的其他内省信息,可以参考
MEMORY STATS
和MEMORY DOCTOR
。下面是所有 persistence 相关的信息:
loading
: 指示转储文件(dump)的加载是否正在进行的标志rdb_changes_since_last_save
: 自上次转储以来的更改次数rdb_bgsave_in_progress
: 指示RDB文件是否正在保存的标志rdb_last_save_time
: 上次成功保存RDB的基于纪年的时间戳rdb_last_bgsave_status
: 上次RDB保存操作的状态rdb_last_bgsave_time_sec
: 上次RDB保存操作的持续时间(以秒为单位)rdb_current_bgsave_time_sec
: 正在进行的RDB保存操作的持续时间(如果有)rdb_last_cow_size
: 上次RDB保存操作期间copy-on-write分配的字节大小aof_enabled
: 表示AOF记录已激活的标志aof_rewrite_in_progress
: 表示AOF重写操作正在进行的标志aof_rewrite_scheduled
: 表示一旦进行中的RDB保存操作完成,就会安排进行AOF重写操作的标志aof_last_rewrite_time_sec
: 上次AOF重写操作的持续时间,以秒为单位aof_current_rewrite_time_sec
: 正在进行的AOF重写操作的持续时间(如果有)aof_last_bgrewrite_status
: 上次AOF重写操作的状态aof_last_write_status
: 上一次AOF写入操作的状态aof_last_cow_size
: 上次AOF重写操作期间copy-on-write分配的字节大小
changes_since_last_save
指的是从上次调用SAVE
或者BGSAVE
以来,在数据集中产生某种变化的操作的数量。如果启用了AOF,则会添加以下这些额外的字段:
aof_current_size
: 当前的AOF文件大小aof_base_size
: 上次启动或重写时的AOF文件大小aof_pending_rewrite
: 指示AOF重写操作是否会在当前RDB保存操作完成后立即执行的标志。aof_buffer_length
: AOF缓冲区大小aof_rewrite_buffer_length
: AOF重写缓冲区大小aof_pending_bio_fsync
: 在后台IO队列中等待fsync处理的任务数aof_delayed_fsync
: 延迟fsync计数器如果正在执行加载操作,将会添加这些额外的字段:
loading_start_time
: 加载操作的开始时间(基于纪元的时间戳)loading_total_bytes
: 文件总大小loading_loaded_bytes
: 已经加载的字节数loading_loaded_perc
: 已经加载的百分比loading_eta_seconds
: 预计加载完成所需的剩余秒数下面是所有 stats 相关的信息:
total_connections_received
: 服务器接受的连接总数total_commands_processed
: 服务器处理的命令总数instantaneous_ops_per_sec
: 每秒处理的命令数rejected_connections
: 由于maxclients
限制而拒绝的连接数expired_keys
: key到期事件的总数evicted_keys
: 由于maxmemory
限制而导致被驱逐的key的数量keyspace_hits
: 在主字典中成功查找到key的次数keyspace_misses
: 在主字典中查找key失败的次数pubsub_channels
: 拥有客户端订阅的全局pub/sub通道数pubsub_patterns
: 拥有客户端订阅的全局pub/sub模式数latest_fork_usec
: 最新fork操作的持续时间,以微秒为单位下面是所有 replication 相关的信息:
role
: 如果实例不是任何节点的从节点,则值是”master”,如果实例从某个节点同步数据,则是”slave”。 请注意,一个从节点可以是另一个从节点的主节点(菊花链)。如果实例是从节点,则会提供以下这些额外字段:
master_host
: 主节点的Host名称或IP地址master_port
: 主节点监听的TCP端口master_link_status
: 连接状态(up或者down)master_last_io_seconds_ago
: 自上次与主节点交互以来,经过的秒数master_sync_in_progress
: 指示主节点正在与从节点同步如果SYNC操作正在进行,则会提供以下这些字段:
master_sync_left_bytes
: 同步完成前剩余的字节数master_sync_last_io_seconds_ago
: 在SYNC操作期间自上次传输IO以来的秒数如果主从节点之间的连接断开了,则会提供一个额外的字段:
master_link_down_since_seconds
: 自连接断开以来,经过的秒数以下字段将始终提供:
connected_slaves
: 已连接的从节点数对每个从节点,将会添加以下行:
slaveXXX
: id,地址,端口号,状态下面是所有 cpu 相关的信息:
used_cpu_sys
: 由Redis服务器消耗的系统CPUused_cpu_user
: 由Redis服务器消耗的用户CPUused_cpu_sys_children
: 由后台进程消耗的系统CPUused_cpu_user_children
: 由后台进程消耗的用户CPUcommandstats部分提供基于命令类型的统计,包含调用次数,这些命令消耗的总CPU时间,以及每个命令执行所消耗的平均CPU。
对于每一个命令类型,添加以下行:
cmdstat_XXX
:calls=XXX,usec=XXX,usec_per_call=XXX
cluster部分当前只包含一个唯一的字段:
cluster_enabled
: 表示已启用Redis集群keyspace部分提供有关每个数据库的主字典的统计,统计信息是key的总数和带有过期key的总数。
对于每个数据库,提供以下行:
dbXXX
:keys=XXX,expires=XXX
语法:
1
127.0.0.1:6379>
返回值:
多行字符串: 文本行的合集
每一行包含了包含一种信息或者属性(从#字符开始)。 所有的属性都是以字段:值(
field:value
)的形式,以\r\n
结尾。实例:
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174127.0.0.1:6379> INFO
Server
redis_version:6.2.6
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:eac5b3c736e2a107
redis_mode:standalone
os:Linux 3.10.0-1160.el7.x86_64 x86_64
arch_bits:64
multiplexing_api:epoll
atomicvar_api:atomic-builtin
gcc_version:4.8.5
process_id:19069
process_supervised:no
run_id:94c6005986e59722cbf438a37cf5513236a5d841
tcp_port:6379
server_time_usec:1653071002486948
uptime_in_seconds:449
uptime_in_days:0
hz:10
configured_hz:10
lru_clock:8903834
executable:/opt/software/redis-6.2.6/src/redis-server
config_file:/opt/software/redis-6.2.6/./redis.conf
io_threads_active:0
Clients
connected_clients:1
cluster_connections:0
maxclients:10000
client_recent_max_input_buffer:0
client_recent_max_output_buffer:0
blocked_clients:0
tracking_clients:0
clients_in_timeout_table:0
Memory
used_memory:873840
used_memory_human:853.36K
used_memory_rss:3063808
used_memory_rss_human:2.92M
used_memory_peak:935096
used_memory_peak_human:913.18K
used_memory_peak_perc:93.45%
used_memory_overhead:810112
used_memory_startup:810112
used_memory_dataset:63728
used_memory_dataset_perc:100.00%
allocator_allocated:1032136
allocator_active:1355776
allocator_resident:3592192
total_system_memory:1019572224
total_system_memory_human:972.34M
used_memory_lua:37888
used_memory_lua_human:37.00K
used_memory_scripts:0
used_memory_scripts_human:0B
number_of_cached_scripts:0
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction
allocator_frag_ratio:1.31
allocator_frag_bytes:323640
allocator_rss_ratio:2.65
allocator_rss_bytes:2236416
rss_overhead_ratio:0.85
rss_overhead_bytes:-528384
mem_fragmentation_ratio:3.78
mem_fragmentation_bytes:2253680
mem_not_counted_for_evict:0
mem_replication_backlog:0
mem_clients_slaves:0
mem_clients_normal:0
mem_aof_buffer:0
mem_allocator:jemalloc-5.1.0
active_defrag_running:0
lazyfree_pending_objects:0
lazyfreed_objects:0
Persistence
loading:0
current_cow_size:0
current_cow_size_age:0
current_fork_perc:0.00
current_save_keys_processed:0
current_save_keys_total:0
rdb_changes_since_last_save:0
rdb_bgsave_in_progress:0
rdb_last_save_time:1653070888
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:0
rdb_current_bgsave_time_sec:-1
rdb_last_cow_size:180224
aof_enabled:0
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:-1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok
aof_last_cow_size:0
module_fork_in_progress:0
module_fork_last_cow_size:0
Stats
total_connections_received:2
total_commands_processed:11
instantaneous_ops_per_sec:0
total_net_input_bytes:237
total_net_output_bytes:20373
instantaneous_input_kbps:0.00
instantaneous_output_kbps:0.00
rejected_connections:0
sync_full:0
sync_partial_ok:0
sync_partial_err:0
expired_keys:0
expired_stale_perc:0.00
expired_time_cap_reached_count:0
expire_cycle_cpu_milliseconds:21
evicted_keys:0
keyspace_hits:0
keyspace_misses:0
pubsub_channels:0
pubsub_patterns:0
latest_fork_usec:245
total_forks:1
migrate_cached_sockets:0
slave_expires_tracked_keys:0
active_defrag_hits:0
active_defrag_misses:0
active_defrag_key_hits:0
active_defrag_key_misses:0
tracking_total_keys:0
tracking_total_items:0
tracking_total_prefixes:0
unexpected_error_replies:0
total_error_replies:0
dump_payload_sanitizations:0
total_reads_processed:12
total_writes_processed:11
io_threaded_reads_processed:0
io_threaded_writes_processed:0
Replication
role:master
connected_slaves:0
master_failover_state:no-failover
master_replid:6a79d6f2d97cb3525136444bb32aae6dd41d07e1
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
CPU
used_cpu_sys:1.938793
used_cpu_user:1.406728
used_cpu_sys_children:0.002974
used_cpu_user_children:0.000991
used_cpu_sys_main_thread:1.937100
used_cpu_user_main_thread:1.407383
Modules
Errorstats
Cluster
cluster_enabled:0
Keyspace
127.0.0.1:6379>
可用版本>= 1.0.0.
1.11.24 LASTSAVE
以 UNIX 时间戳格式返回最近一次 Redis 成功将数据保存到磁盘上的时间。
LASTSAVE
通常被用来检查 BGSAVE
命令是否执行完成。通常是每隔几秒钟看一下 LASTSAVE
的是是否有变化。
语法:
1
127.0.0.1:6379> LASTSAVE
返回值:
整数: 一个 UNIX 时间戳。
实例:
1
2
3127.0.0.1:6379> LASTSAVE
(integer) 1653070888
127.0.0.1:6379>
可用版本>= 1.0.0.
1.11.25 MONITOR
Redis MONITOR
命令用于实时打印出 Redis 服务器接收到的命令,调试用。
MONITOR
用来帮助我们知道数库正在做什么。可以通过 redis-cli
和 telnet
调用 MONITOR
。
当 Redis 用做数据库或者分布式缓存时,MONITOR
可以帮助我们发现程序中的 bug 。
1 | [root@localhost redis-6.2.6]# ./src/redis-cli -a yanpenggong |
通过 redis-cli
运行 MONITOR
时,可以发送 SIGINT
(Ctrl+C) 信号来停止退出。
1 | 127.0.0.1:6379> MONITOR |
通过 telnet
运行 MONITOR
时,可以发送 QUIT
来停止退出。
MONITOR 不记录的命令:
处于安全方面的考虑,所有的管理相关的命令不会记录到
MONITOR
的输出者。下面几个命令也不会记录:
AUTH
EXEC
HELLO
QUIT
MONITOR 的消耗:
因为
MONITOR
流返回所有命令,所以用起来会有一定的消耗。 下面是一个基准测试对比:不带
MONITOR
命令:
1
2
3
4
5
6 $ src/redis-benchmark -c 10 -n 100000 -q
PING_INLINE: 101936.80 requests per second
PING_BULK: 102880.66 requests per second
SET: 95419.85 requests per second
GET: 104275.29 requests per second
INCR: 93283.58 requests per second带
MONITOR
命令 (redis-cli monitor > /dev/null
):
1
2
3
4
5
6 $ src/redis-benchmark -c 10 -n 100000 -q
PING_INLINE: 58479.53 requests per second
PING_BULK: 59136.61 requests per second
SET: 41823.50 requests per second
GET: 45330.91 requests per second
INCR: 41771.09 requests per second通过上面的例子可以看到运行一个
MONITOR
命令降低了超过 50% 的吞吐量。 运行多个MONITOR
会进一步降低性能。
语法:
1
127.0.0.1:6379> MONITOR
返回值:
输出Redis服务器处理的指令流直到退出。
实例:
1
2
3
4
5
6
7
8127.0.0.1:6379> MONITOR
OK
+1339518083.107412 [0 127.0.0.1:60866] "keys" "*"
+1339518087.877697 [0 127.0.0.1:60866] "dbsize"
+1339518090.420270 [0 127.0.0.1:60866] "set" "x" "6"
+1339518096.506257 [0 127.0.0.1:60866] "get" "x"
+1339518099.363765 [0 127.0.0.1:60866] "del" "x"
+1339518100.544926 [0 127.0.0.1:60866] "get" "x"
可用版本>= 1.0.0.
1.11.26 ROLE
Redis ROLE 命令返回实例在复制中担任的角色, 这个角色可以是 master
、 slave
或者 sentinel
。
除了角色之外, 命令还会返回与该角色相关的其他信息, 其中:
- 主服务器将返回属下从服务器的 IP 地址和端口。
- 从服务器将返回自己正在复制的主服务器的 IP 地址、端口、连接状态以及复制偏移量。
- Sentinel 将返回自己正在监视的主服务器列表。
语法:
1
127.0.0.1:6379> ROLE
返回值:
数组:第一个参数是 master, slave, sentinel 三个中的一个。
实例:
1
2
3
4
5127.0.0.1:6379> ROLE
1) "master"
2) (integer) 0
3) (empty array)
127.0.0.1:6379>
可用版本>= 2.8.12.
1.11.27 SAVE
Redis SAVE
命令用于执行同步保存操作,把 Redis 实例中某一时点的所有数据的快照以 RDB 文件的形式保存到磁盘上。
生产环境不要执行 SAVE
命令,因为这会阻塞所有其它的客户端。
可以使用 BGSAVE
代替。尽管如此,BGSAVE
也有执行失败的危险,SAVE
是转存最新数据集的最好也是最后一个方法。
详细参考 persistence documentation 。
语法:
1
127.0.0.1:6379> SAVE
返回值:
字符串: 成功时返回 “OK”。
实例:
1
2
3127.0.0.1:6379> SAVE
OK
127.0.0.1:6379>
可用版本>= 1.0.0.
1.11.28 SHUTDOWN
SHUTDOWN 命令执行如下操作:
1 | - 停止所有客户端 |
如果配置了持久化策略,那么这个命令将能够保证在关闭redis服务进程的时候数据不会丢失。
如果仅仅在客户端执行 QUIT
命令,然后 执行 QUIT
命令,那么数据的完整性将不会被保证,因为其他客户端可能在执行这两个命令的期间修改数据库的数据。
注意: 一个没有配置持久化策略的redis实例 (没有aof配置, 没有 “save” 命令) 将不会在执行SHUTDOWN
命令的时候转存一个rdb文件,可以提高关闭的速度,例如仅用来做缓存的 redis 不需要配置持久化转存。
SAVE 和 NOSAVE 修饰符
通过指定一个可选的修饰符可以改变这个命令的表现形式,比如:
- SHUTDOWN SAVE 能够在即使没有配置持久化的情况下强制数据库存储。
- SHUTDOWN NOSAVE 能够在配置一个或者多个持久化策略的情况下阻止数据库存储. (你可以假想它为一个中断服务的 ABORT 命令)。
SHUTDOWN 关闭失败的情况
当配置了 AOF 时,shutdown 可能会失败由于系统处于不允许立刻执行磁盘持久化操纵。
当有一个AOF的子进程在执行AOF重写时,Redis 会简单的kill 该子进程。有两种列外的情况,SHUTDOWN 会返回失败:
- AOF 刚刚打开,首次进行 AOF rewrite 创建初始的 AOF 文件。这种情况下停止redis将会丢失所有数据:一旦停止 redis时,虽然开启了AOF,但是还没有创建任何AOF文件。
- 复制节点打开了 AOF,向 master 发起重连,执行数据全同步,然后重起AOF,创建初始AOF文件。可能会丢失复制自master节点的数据。
如果我们只是想立刻关闭redis,而不管其它情况。正确的做法是先发送CONFIG appendonly no ,然后执行SHUTDOWN NOSAVE.。前一个命令关闭 AOF(如果打开AOF),终止可能存在的 AOF 重写子进程,这样后一个命令关闭不会失败。
语法:
1
127.0.0.1:6379> SHUTDOWN [NOSAVE] [SAVE]
返回值:
字符串: 当发生错误的时候返回状态码 . 当成功的时候不返回任何值,因为服务退出,链接关闭。
实例:
1
2
3
4
5
6
7
8127.0.0.1:6379> PING
Error: Server closed the connection
127.0.0.1:6379> PING
PONG
127.0.0.1:6379> SHUTDOWN
not connected> redis
Could not connect to Redis at 127.0.0.1:6379: Connection refused
not connected>
可用版本>= 1.0.0.
1.11.29 SLAVEOF
Redis SLAVEOF 命令可以将当前服务器转变为指定服务器的从属服务器(slave server)。
注意: 从 Redis 5 起使用 REPLICAOF
替代 SLAVEOF
。当然,为了向后兼容 SLAVEOF 命令仍然可用。
SLAVEOF
命令可以临时修改从节点的复制配置。如果当前服务器已经是某个主服务器(master server)的从属服务器,SLAVEOF
NO ONE 命令会停止复制,把节点改为主节点。
SLAVEOF
hostname port 可以使正在复制其它节点的 Redis 改为复制新的 hostname 和 port。
SLAVEOF
hostname port 将会停止从旧的主节点复制,丢弃已经同步的旧的数据,并开始从新的节点同步数据。
SLAVEOF
NO ONE 用来停止复制,把从节点改为主节点,但是不会丢弃已复制的数据。所以,当 Master 主节点出现问题时,可以把从节点变成 Master 主节点,使应用读/写新的主节点。当原来的主节点修复之后,可以把新的 Master 节点重新配置为从节点。
利用『 SLAVEOF NO ONE 不会丢弃同步所得数据集』这个特性,可以在主服务器失败的时候,将从属服务器用作新的主服务器,从而实现无间断运行。
语法:
1
127.0.0.1:6379> SLAVEOF host port
返回值:
字符串:总是返回 OK 。
实例:
1
2
3
4127.0.0.1:6379> SLAVEOF 127.0.0.1 6379
OK
127.0.0.1:6379> SLAVEOF NO ONE
OK
可用版本>= 1.0.0.
1.11.30 SLOWLOG
Redis slowlog 是 Redis 用来记录查询执行时间的日志系统。
查询执行时间指的是不包括像客户端响应(talking)、发送回复等 IO 操作,而单单是执行一个查询命令所耗费的时间。
另外,slow log 保存在内存里面,读写速度非常快,因此你可以放心地使用它,不必担心因为开启 slow log 而损害 Redis 的速度。
读取 slow log
慢日志记录在内存中,不会写到文件上。所以即使记录所有执行的命令到慢日志中性能开销也很小。
读取慢日志命令:
SLOWLOG GET 返回每一条慢日志。
SLOWLOG GET n 返回最新的n条慢日志。
注意:请使用新版 redis-cli 以便能解析慢日志输出,较老版本的 redis-cli 不支持多行嵌套。
响应输出格式
1
2
3
4
5
6
7
8
9
10
11 redis 127.0.0.1:6379> slowlog get 2
1) 1) (integer) 14
2) (integer) 1309448221
3) (integer) 15
4) 1) "ping"
2) 1) (integer) 13
2) (integer) 1309448128
3) (integer) 30
4) 1) "slowlog"
2) "get"
3) "100"Redis 4.0 及之后版本新增域:
1
2 5) "127.0.0.1:58217"
6) "worker-123"每条慢日志由 4 或 6 部分组成:
- 每条慢日志有一个递增的唯一 ID。
- 记录慢日志的 Unix 时间戳。
- 执行这个命令花费的时间,单位是微妙。
- 数组形式的命令参数。
- 客户端 ip 和端口 (4.0 only)。
- 通过 CLIENT SETNAME 命令设置的客户端名字 (4.0 only)。
可以用唯一 ID 来避免慢日志被处理多次(例如你有一个每当产生新的慢日志发送报警的脚本)。
ID 在 Redis 运行期间不会重置,Redis 重启之后会重置 ID。
查询当前 slowlog 的长度
SLOWLOG LEN 获取 slow log 的长度。
重置 slow log
SLOWLOG RESET 命令用来重置 slowlog。一旦删除 slowlog 不可恢复。
语法:
1
127.0.0.1:6379> SLOWLOG subcommand [argument]
返回值:
取决于不同命令,返回不同的值。
实例:
查看日志信息:
1
2
3
4
5
6
7
8
9
10
11127.0.0.1:6379> slowlog get 2
1) 1) (integer) 14
2) (integer) 1309448221
3) (integer) 15
4) 1) "ping"
2) 1) (integer) 13
2) (integer) 1309448128
3) (integer) 30
4) 1) "slowlog"
2) "get"
3) "100"查看当前日志的数量:
1
2127.0.0.1:6379> SLOWLOG LEN
(integer) 14使用命令 SLOWLOG RESET 可以清空 slow log 。
1
2
3
4
5
6127.0.0.1:6379> SLOWLOG LEN
(integer) 14
127.0.0.1:6379> SLOWLOG RESET
OK
127.0.0.1:6379> SLOWLOG LEN
(integer) 0
可用版本>= 2.2.12.
1.11.31 SYNC
从主服务节点初始化流复制。
Redis 从节点调用 SYNC
来从主节点启动流复制。在 redis 新版本中已经被 PSYNC
代替。
更多信息可以参考 Redis 复制。
语法:
1
127.0.0.1:6379> SYNC
返回值:
非标准数据, bulk 数据 + PING + 来自master的写请求。
实例:
1
2
3
4
5
6
7127.0.0.1:6379> SYNC
Entering replica output mode... (press Ctrl-C to quit)
SYNC with master, discarding 175 bytes of bulk transfer...
SYNC done. Logging commands from master.
"ping"
"ping"
可用版本>= 1.0.0.
1.12 Redis HyperLogLog
1.12.1 PFADD
Redis Pfadd
命令将所有元素参数添加到 HyperLogLog 数据结构中。
作为这个命令的副作用, HyperLogLog 内部可能会被更新, 以便反映一个不同的唯一元素估计数量(也即是集合的基数)。
如果 HyperLogLog 估计的近似基数(approximated cardinality)在命令执行之后出现了变化, 那么命令返回 1
, 否则返回 0
。 如果命令执行时给定的键不存在, 那么程序将先创建一个空的 HyperLogLog 结构, 然后再执行命令。
调用
PFADD
命令时可以只给定键名而不给定元素:
- 如果给定键已经是一个 HyperLogLog , 那么这种调用不会产生任何效果;
- 但如果给定的键不存在, 那么命令会创建一个空的 HyperLogLog , 并向客户端返回
1
。要了解更多关于 HyperLogLog 数据结构的介绍知识, 请查阅
PFCOUNT
命令的文档。
语法:
1
127.0.0.1:6379> PFADD key element [element ...]
返回值:
整数, specifically:
- 如果 HyperLogLog 的内部储存被修改了, 那么返回 1 , 否则返回 0 。
实例:
1
2
3
4
5127.0.0.1:6379> PFADD myset a b c d e f g
(integer) 1
127.0.0.1:6379> PFCOUNT myset
(integer) 7
127.0.0.1:6379>
可用版本>= 2.8.9.
时间复杂度: O(1) to add every element.
1.12.2 PFCOUNT
Redis PFCOUNT
命令返回给定 HyperLogLog 的基数估算值。
当 PFCOUNT
命令作用于单个键时, 返回储存在给定键的 HyperLogLog 的近似基数, 如果键不存在, 那么返回 0 。
当 PFCOUNT
命令作用于多个键时, 返回所有给定 HyperLogLog 的并集的近似基数, 这个近似基数是通过将所有给定 HyperLogLog 合并至一个临时 HyperLogLog 来计算得出的。
通过 HyperLogLog 数据结构, 用户可以使用少量固定大小的内存, 来储存集合中的唯一元素 (每个 HyperLogLog 只需使用 12k 字节内存,以及几个字节的内存来储存键本身)。
命令返回的可见集合(observed set)基数并不是精确值, 而是一个带有 0.81% 标准错误(standard error)的近似值。
举个例子, 为了记录一天会执行多少次各不相同的搜索查询, 一个程序可以在每次执行搜索查询时调用一次 PFADD
, 并通过调用 PFCOUNT
命令来获取这个记录的近似结果。
语法:
1
127.0.0.1:6379> PFCOUNT key [key ...]
返回值:
整数, specifically:
- 给定 HyperLogLog 包含的唯一元素的近似数量。
实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15127.0.0.1:6379> PFADD myset kungs1 kungs2 kungs3
(integer) 1
127.0.0.1:6379> PFADD myset kungs1 kungs2 kungs4
(integer) 1
127.0.0.1:6379> PFADD myset kungs1 kungs1 kungs1
(integer) 0
127.0.0.1:6379> PFADD myset kungs1 kungs2
(integer) 0
127.0.0.1:6379> PFCOUNT myset
(integer) 4
127.0.0.1:6379> PFADD myset-other a b c
(integer) 1
127.0.0.1:6379> PFCOUNT myset myset-other
(integer) 7
127.0.0.1:6379>
可用版本>= 2.8.9.
时间复杂度: O(1) with a very small average constant time when called with a single key. O(N) with N being the number of keys, and much bigger constant times, when called with multiple keys.
1.12.3 PFMERGE
Redis PFMERGE
命令将多个 HyperLogLog 合并为一个 HyperLogLog ,合并后的 HyperLogLog 的基数估算值是通过对所有 给定 HyperLogLog 进行并集计算得出的。
合并得出的 HyperLogLog 会被储存在 destkey
键里面, 如果该键并不存在, 那么命令在执行之前, 会先为该键创建一个空的 HyperLogLog 。
语法:
1
127.0.0.1:6379> PFMERGE destkey sourcekey [sourcekey ...]
返回值:
字符串:
OK
.实例:
1
2
3
4
5
6
7
8
9127.0.0.1:6379> PFADD myset kungs1 kungs2 kungs3
(integer) 1
127.0.0.1:6379> PFADD myset-other a b c
(integer) 1
127.0.0.1:6379> PFMERGE out myset myset-other
OK
127.0.0.1:6379> PFCOUNT out
(integer) 6
127.0.0.1:6379>
可用版本>= 2.8.9.
时间复杂度: O(N) to merge N HyperLogLogs, but with high constant times.
Redis协议详细规范
Redis客户端和服务器端通信使用名为 RESP (REdis Serialization Protocol) 的协议。虽然这个协议是专门为Redis设计的,它也可以用在其它 client-server 通信模式的软件上。
RESP 是下面条件的折中:
- 实现起来简单。
- 解析速度快。
- 有可读性。
RESP 能序列化不同的数据类型,例如整型(integers)、字符串(strings)、数组(arrays)。额外还有特殊的错误类型。请求从客户端以字符串数组的形式发送到redis服务器,这些字符串表示要执行的命令的参数。Redis用特定于命令的数据类型回复。
RESP 是二进制安全的,并且不需要处理从一个进程发到另外一个进程的批量数据,因为它使用前缀长度来传输批量数据。
注意:这里概述的协议仅用于客户机-服务器通信。Redis集群使用不同的二进制协议在节点之间交换消息。
1. 网络层
连到Redis服务器的客户端建立了一个到6379端口的TCP连接。
虽然RESP在技术上不特定于TCP,但是在Redis的上下文中,该协议仅用于TCP连接(或类似的面向流的连接,如unix套接字)。
2. 请求-响应模型
Redis接受由不同参数组成的命令。一旦收到命令,就会对其进行处理,并将应答发送回客户端。
这是最简单的模型,但是有两个例外:
- Redis 支持管道pipelining。所以,客户端可以一次发送多个命令,然后再等待应答。
- 当一个Redis客户端订阅一个频道,那么协议会改变语义并变成pushprotocol, 也就是说,客户客户端不再需要发送命令,因为服务器端会一收到新消息,就会自动发送给客户端。
除了上面两个例外情况,Redis协议是一个简单的请求-响应协议。
3. RESP 协议解释
RESP 协议在Redis1.2被引入,直到Redis2.0才成为和Redis服务器通信的标准。这个协议需要在你的Redis客户端实现。
RESP 是一个支持多种数据类型的序列化协议:简单字符串(Simple Strings),错误( Errors),整型( Integers), 大容量字符串(Bulk Strings)和数组(Arrays)。
RESP在Redis中作为一个请求-响应协议以如下方式使用:
- 客户端以大容量字符串RESP数组的方式发送命令给服务器端。
- 服务器端根据命令的具体实现返回某一种RESP数据类型。
在 RESP 中,数据的类型依赖于首字节:
- 单行字符串(Simple Strings): 响应的首字节是 “+”
- 错误(Errors): 响应的首字节是 “-“
- 整型(Integers): 响应的首字节是 “:”
- 多行字符串(Bulk Strings): 响应的首字节是“$“
- 数组(Arrays): 响应的首字节是 “
*
“
另外,RESP可以使用大容量字符串或者数组类型的特殊变量表示空值,下面会具体解释。RESP协议的不同部分总是以 “\r\n” (CRLF) 结束。
4. RESP 单行字符串
单行字符串编码方法: 加号后面跟着一个不包含回车或换行字符的字符串 (不允许出现换行),以CRLF(“\r\n”)结尾。
单行字符串通常被用来传输非二进制安全字符串并且消耗极小。例如,许多redis命令在成功时回复”OK”,即简单字符串用以下5个字节编码:
1 | "+OK\r\n" |
为了发送二进制安全的字符串,需要使用RESP的多行字符串(Bulk Strings)替代。
当Redis返回单行字符串(Simple String)时,客户端lib应该返回去掉首字符加号和结尾CRLF字符的字符串给调用者。
5. RESP 错误
RESP 有特殊类型来处理错误。errors类型除了首字符是减号 ‘-‘不是加号以外,其它跟简单字符串一样。RESP中简单字符和错误的真正区别是:错误被客户端当作异常处理,组成错误类型的字符串是错误消息自身。
基本格式如下:
1 | "-Error message\r\n" |
错误应答只在发生异常时发送,例如,要执行命令的参数数据类型不匹配或者命令不存在等。当收到错误返回时,客户端lib应该抛出一个异常。
错误返回例子:
1 | -ERR unknown command 'foobar' |
从”-“后面第一个单词起,直到第一个空格或者换行,表示返回的错误类型。这是Redis的一种约定,并不是RESP协议的要求。
ERR
是一个通用错误, 而 WRONGTYPE
是表示更具体的错误,意味着客户端在错误的数据类型上执行操作。这被叫做错误前缀(Error Prefix), 使客户端不用依赖具体错误消息就知道返回的错误类型,错误消息可能会随着时间而变化。
客户端实现可能会对不同异常返回不同类型的错误,或者可能提供一种通用的方式来捕获错误,通过以字符串的形式直接返回错误名给调用者。
尽管如此,这种特性不能认为很重要,因为它很少被使用。一小部分客户端的实现可能会返回通用错误条件,例如false。
6. RESP 整数
整数类型是由以冒号开头,CRLF结尾,中间是字符串形式表示的数字。 例如 “:0\r\n”, 或 “:1000\r\n” 都是整数回复。
很多Redis命令返回RESP整数,像 INCR, LLEN 和 LASTSAVE.
返回的整数并没有特别的意义, INCR 返回的是一个递增的数字, LASTSAVE 返回的是Unix时间戳等。返回的整数有效值需要在有符号64位整数范围内。
整数返回也被广泛的用来返回 true 或 false。比如 EXISTS 或 SISMEMBER 命令返回1表示true,返回0表示false。
其它命令像 SADD, SREM 和 SETNX 如果操作被执行则返回1,否则返回0。
返回整数回复的命令: SETNX, DEL, EXISTS, INCR, INCRBY, DECR, DECRBY, DBSIZE, LASTSAVE, RENAMENX, MOVE, LLEN, SADD, SREM, SISMEMBER, SCARD.
6. RESP 多行字符串
多行字符串被用来表示最大512MB长的二进制安全字符串。
多行字符串编码方式:
- 美元符 “$“ 后面跟着组成字符串的字节数(前缀长度),并以 CRLF 结尾。
- 实际的字符串数据。
- 结尾是 CRLF。
所以,字符串 “foobar” 编码如下:
1 | "$6\r\nfoobar\r\n" |
空字符串编码格式:
1 | "$0\r\n\r\n" |
RESP 多行字符串(Bulk Strings) 也可以使用一个特殊的用来表示空值的格式表示不存在的值。在这种格式里长度值为-1,数据部分不存在,所以空(Null)用如下方式表示:
1 | "$-1\r\n" |
叫做空的多行字符串Null Bulk String。
客户端API库不应该返回空串,当服务器端响应一个空的多行字符串时,API库可以返回一个空对象给调用者。例如,Ruby库应该返回 ‘nil’ ,而C库应该返回NULL。
7. RESP 数组
客户端使用 RESP 数组发送命令到 Redis 服务端。同样地,某些命令的应答使用RESP数组返回元素的集合给Redis客户端。 LRANGE 命令返回元素列表就是一个例子。
RESP 数组使用如下格式发送:
- 以星号
* 为首字符,接着是表示数组中元素个数的十进制数
,最后以 CRLF 结尾。 - 外加数组中每个 RESP 类型的元素。
空数组表示:
1 | "*0\r\n" |
有两个 RESP 多行字符串”foo” 和”bar”元素的 RESP 数组 :
1 | "*2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n" |
在前缀 *<count>CRLF
的后面,组成数组的其它数据类型一个接在另一个后面。 例如包含三个整数的数组编码方式:
1 | "*3\r\n:1\r\n:2\r\n:3\r\n" |
数组可以包含混合类型,不一定必须是同一种类型。例如,4个整型和1个多行字符串编码方式:
1 | *5\r\n |
(为了方便阅读,应答分成多行来展示)
第一个行表示 *5\r\n
说明后面有5个应答。这些应答组成一个大的应答一起发送。
空数组的概念也是存在的,另一个表示空值的方式(通常使用多行空字符串,历史遗留导致有这两种格式)。
例如,当 BLPOP 命令超时,它会返回一个空数组,数组的计数器是-1 :
1 | "*-1\r\n" |
当 Redis 返回一个空数组的时候,Redis客户端库API应该返回一个空对象而不是返回一个空数组。 这对区分空列表和其它不同情况(像 BLPOP 命令超时情况)是必要的。
数组的数组也是可行的。例如,一个含有两个数组元素的数组编码方式:
1 | *2\r\n |
(为了方便阅读,分成多行来展示).
上面的 RESP 数据类型包含两个数组,一个数组包含三个整数1, 2, 3 ,另一个是简单字符串和一个错误类型。
8. 数组中的空元素
数组中可以有为空的元素。主要使用在Redis应答中,为了表示这个元素丢失并且不是一个空的字符串。当SORT命令使用GET 模式选项,并且特定的key丢失的时会出现这种应答。 含有有空元素的应答数组例子:
1 | *3\r\n |
第二个元素是空,客户端库应该返回像下面这样的数据:
1 | ["foo",nil,"bar"] |
这不是前面提到的异常情况,这只是说明协议的一个例子。
9. 发送命令到Redis服务器
至此,我们已经很熟悉RESP序列化格式,写一个Redis客户端库的实现会变得很容易。我们可以进一步说明客户端和服务端如何交互工作:
- 客户端发送包含只有多行字符串的数组给Redis服务器。
- Redis 服务器给客户端发送任意有效的 RESP 数据类型作为应答。
下面是一个典型的交互过程例子:
客户端发送命令 LLEN mylist 来获取存储在 mylist 键中列表的长读,然后服务器端返回整数应答(C: 代表客户端, S: 代表服务器端).
1 | C: *2\r\n |
为了方便理解我们用换行把协议分成不同部分,实际上客户端发送的是一个整体没有换行:*2\r\n$4\r\nLLEN\r\n$6\r\nmylist\r\n
as a whole.
10. 管道和多个命令
客户端可以使用同一个连接发送多个命令。通过管道客户端可以一次写操作发送多个命令,发送下一个命令前不需要等待前一个命令的应答。所有应答可以在最后被读取。
关于管道详细参考 page about Pipelining.
11. 内联命令
有时你手边只能操作telnet
并且需要给Redis 服务器端发送命令。虽然Redis协议是容易实现的,但并不适合用在交互会话。redis-cli
也不是随时都能可用。因此,redis还以一种特殊的方式接受为人类设计的命令,称为内联命令格式。
以下是使用内联命令进行服务器/客户端聊天的示例(服务器聊天以s开头,客户端聊天以c开头)。
1 | C: PING |
以下是返回整数的内联命令的另一个示例:
1 | C: EXISTS somekey |
基本上,您只需在telnet会话中编写空格分隔的参数。由于统一请求协议中没有以*开头的命令,因此Redis能够检测到这种情况并解析您的命令。
12. Redis 协议的高性能解析器
虽然redis协议是非常容易被人阅读和实现的,但是它可以以类似于二进制协议的性能来实现。
RESP 使用带前缀的长度来传输批量数据,因此不需要像使用json那样扫描有效负载以查找特殊字符,也不需要引用需要发送到服务器的有效负载。
批量和多批量长度可以使用代码进行处理,代码对每个字符执行单个操作,同时扫描CR字符,如以下C代码:
RESP 使用带前缀的长度来传输多行数据,因此不需要像使用json那样扫描有效负载以查找特殊字符,也不需要引用需要发送到服务器的有效负载。
多行和多个多行长度可以使用代码进行处理,代码对每个字符执行单个操作,同时扫描CR字符,如以下C代码:
1 |
|
在识别出第一个CR之后,可以跳过它和下面的LF,而不需要任何处理。然后,可以使用不以任何方式检查有效负载的单个读取操作读取大容量数据。最后,剩余的CR和LF字符将被丢弃,而不进行任何处理。
Redis协议有着与二进制协议可比的性能,更重要的是易于在大多数高级语言中实现,从而减少了客户端软件中的错误数量。
Redis键空间通知
重要:键空间通知功能自2.8.0版本开始可用。
1. 功能概述
键空间通知允许客户端订阅发布/订阅频道,以便以某种方式接收影响Redis数据集的事件。可能接收的事件示例如下:
- 所有影响给定键的命令。
- 所有接收LPUSH操作的键。
- 所有在数据库0中到期的键。
事件使用Redis的普通发布/订阅层传递,因此实现了发布/订阅的客户端无需修改即可使用此功能。由于Redis的发布/订阅是fire and forget,因此如果你的应用要求可靠的事件通知,目前还不能使用这个功能,也就是说,如果你的发布/订阅客户端断开连接,并在稍后重连,那么所有在客户端断开期间发送的事件将会丢失。将来有计划允许更可靠的事件传递,但可能会在更一般的层面上解决,要么为发布/订阅本身带来可靠性,要么允许Lua脚本拦截发布/订阅的消息以执行推送等操作,就像往队列里推送事件一样。
2. 事件类型
键空间通知的实现是为每一个影响Redis数据空间的操作发送两个不同类型的事件。例如,在数据库0
中名为mykey
的键上执行DEL
操作,将触发两条消息的传递,完全等同于下面两个PUBLISH
命令:
1 | PUBLISH __keyspace@0__:mykey del |
以上很容易看到,一个频道允许监听所有以键mykey
为目标的所有事件,以及另一个频道允许获取有关所有DEL
操作目标键的信息。第一种事件,在频道中使用keyspace
前缀的被叫做键空间通知,第二种,使用keyevent
前缀的,被叫做键事件通知。在以上例子中,为键mykey
生成了一个del
事件。 会发生什么:
- 键空间频道接收到的消息是事件的名称。
- 键事件频道接收到的消息是键的名称。
可以只启用其中一种通知,以便只传递我们感兴趣的事件子集。
3. 配置
默认情况下,键空间事件通知是不启用的,因为虽然不太明智,但该功能会消耗一些CPU。可以使用redis.conf中的notify-keyspace-events
或者使用CONFIG SET命令来开启通知。将参数设置为空字符串会禁用通知。 为了开启通知功能,使用了一个非空字符串,由多个字符组成,每一个字符都有其特殊的含义,具体参见下表:
1 | K 键空间事件,以__keyspace@<db>__前缀发布。 |
字符串中应当至少存在K
或者E
,否则将不会传递事件,不管字符串中其余部分是什么。例如,要为列表开启键空间事件,则配置参数必须设置为Kl
,以此类推。字符串KEA
可以用于开启所有可能的事件。
4. 不同的命令生成的事件
根据以下列表,不同的命令产生不同种类的事件。
DEL
命令为每一个删除的key生成一个del
事件。RENAME
生成两个事件,一个是为源key生成的rename_from
事件,一个是为目标key生成的rename_to
事件。EXPIRE
在给一个键设置有效期时,会生成一个expire
事件,或者每当设置有效期导致键被删除时,生成expired
事件(请查阅EXPIRE
文档以获取更多信息)。SORT
会在使用STORE
选项将结果存储到新键时,生成一个sortstore
事件。如果结果列表为空,且使用了STORE
选项,并且已经存在具有该名称的键时,那个键将被删除,因此在这种场景下会生成一个del
事件。SET
以及所有其变种(SETEX,SETNX,GETSET)生成set
事件。但是SETEX
还会生成一个expire
事件。MSET
为每一个key生成一个set
事件。SETRANGE
生成一个setrange
事件。- INCR、DECR、INCRBY、
DECRBY
命令都生成incrby
事件。 INCRBYFLOAT
生成一个incrbyfloat
事件。APPEND
生成一个append
事件。LPUSH
和LPUSHX
生成一个lpush
事件,即使在可变参数情况下也是如此。RPUSH
和RPUSHX
生成一个rpush
事件,即使在可变参数情况下也是如此。RPOP
生成rpop
事件。此外,如果键由于列表中的最后一个元素弹出而被删除,则会生成一个del
事件。LPOP
生成lpop
事件。此外,如果键由于列表中的最后一个元素弹出而被删除,则会生成一个del
事件。LINSERT
生成一个linsert
事件。LSET
生成一个lset
事件。LTRIM
生成ltrim
事件,此外,如果结果列表为空或者键被移除,将会生成一个del
事件。RPOPLPUSH
和BRPOPLPUSH
生成rpop
事件和lpush
事件。这两种情况下,顺序都将得到保证(lpush
事件将总是在rpop
事件之后传递)。此外,如果结果列表长度为零且键被删除,则会生成一个del
事件。- HSET、
HSETNX
以及HMSET
都生成一个hset
事件。 HINCRBY
生成一个hincrby
事件。HINCRBYFLOAT
生成一个hincrbyfloat
事件。HDEL
生成一个hdel
事件,此外,如果结果哈希集为空或者键被移除,将生成一个del
事件。SADD
生成一个sadd
事件,即使在可变参数情况下也是如此。SREM
生成一个srem
事件,此外,如果结果集合为空或者键被移除,将生成一个del
事件。SMOVE
为每一个源key生成一个srem
事件,以及为每一个目标key生成一个sadd
事件。SPOP
生成一个spop
事件,此外,如果结果集合为空或者键被移除,将生成一个del
事件。- SINTERSTORE、SUNIONSTORE、
SDIFFSTORE
分别生成sinterstore
、sunionostore
、sdiffstore
事件。在特殊情况下,结果集是空的,并且存储结果的键已经存在,因为删除了键,所以会生成del
事件。 ZINCR
生成一个zincr
事件。ZADD
生成一个zadd
事件,即使添加了多个元素。ZREM
生成一个zrem
事件,即使删除了多个元素。当结果有序集合为空且生成了键,则会生成额外的del
事件。ZREMBYSCORE
生成一个zrembyscore
事件。当结果有序集合为空且生成了键,则会生成额外的del
事件。ZREMBYRANK
生成一个zrembyrank
事件。当结果有序集合为空且生成了键,则会生成额外的del
事件。ZINTERSTORE
和ZUNIONSTORE
分别生成zinterstore
和zunionstore
事件。在特殊情况下,结果有序集合是空的,并且存储结果的键已经存在,因为删除了键,所以会生成del
事件。- 每次一个拥有过期时间的键由于过期而从数据集中移除时,将生成一个
expired
事件。 - 每次一个键由于
maxmemory
策略而被从数据集中驱逐,以便释放内存时,将生成一个evicted
事件。
重要 所有命令仅在真正修改目标键时才生成事件。例如,使用SREM
命令从集合中删除一个不存在的元素将不会改变键的值,因此不会生成任何事件。如果对某个命令如何生成事件有疑问,最简单的方法是自己观察:
1 | $ redis-cli config set notify-keyspace-events KEA |
此时,在另外一个终端使用redis-cli
发送命令到Redis服务器,并观察生成的事件:
1 | "pmessage","__key*__:*","__keyspace@0__:foo","set" |
5. 过期事件的时间安排
设置了生存时间的键由Redis以两种方式过期:
- 当命令访问键时,发现键已过期。
- 通过后台系统在后台逐步查找过期的键,以便能够收集那些从未被访问的键。
当通过以上系统之一访问键且发现键已经过期时,将生成expired
事件。因此无法保证Redis服务器在键过期的那一刻同时生成expired
事件。如果没有命令不断地访问键,并且有很多键都有关联的TTL,那么在键的生存时间降至零到生成expired
事件之间,将会有明显的延迟。基本上,expired
事件是在Redis服务器删除键的时候生成的,而不是在理论上生存时间达到零值时生成的。
Redis复制
在 Redis 复制的基础上,使用和配置主从复制非常简单,能使得从 Redis 服务器(下文称 slave)能精确得复制主 Redis 服务器(下文称 master)的内容。每次当 slave 和 master 之间的连接断开时, slave 会自动重连到 master 上,并且无论这期间 master 发生了什么, slave 都将尝试让自身成为 master 的精确副本。
这个系统的运行依靠三个主要的机制:
- 当一个 master 实例和一个 slave 实例连接正常时, master 会发送一连串的命令流来保持对 slave 的更新,以便于将自身数据集的改变复制给 slave , :包括客户端的写入、key 的过期或被逐出等等。
- 当 master 和 slave 之间的连接断开之后,因为网络问题、或者是主从意识到连接超时, slave 重新连接上 master 并会尝试进行部分重同步:这意味着它会尝试只获取在断开连接期间内丢失的命令流。
- 当无法进行部分重同步时, slave 会请求进行全量重同步。这会涉及到一个更复杂的过程,例如 master 需要创建所有数据的快照,将之发送给 slave ,之后在数据集更改时持续发送命令流到 slave 。
Redis使用默认的异步复制,其特点是低延迟和高性能,是绝大多数 Redis 用例的自然复制模式。但是,从 Redis 服务器会异步地确认其从主 Redis 服务器周期接收到的数据量。
客户端可以使用 WAIT 命令来请求同步复制某些特定的数据。但是,WAIT 命令只能确保在其他 Redis 实例中有指定数量的已确认的副本:在故障转移期间,由于不同原因的故障转移或是由于 Redis 持久性的实际配置,故障转移期间确认的写入操作可能仍然会丢失。你可以查看 Sentinel 或 Redis 集群文档,了解关于高可用性和故障转移的更多信息。本文的其余部分主要描述 Redis 基本复制功能的基本特性。
接下来的是一些关于 Redis 复制的非常重要的事实:
- Redis 使用异步复制,slave 和 master 之间异步地确认处理的数据量
- 一个 master 可以拥有多个 slave
- slave 可以接受其他 slave 的连接。除了多个 slave 可以连接到同一个 master 之外, slave 之间也可以像层叠状的结构(cascading-like structure)连接到其他 slave 。自 Redis 4.0 起,所有的 sub-slave 将会从 master 收到完全一样的复制流。
- Redis 复制在 master 侧是非阻塞的。这意味着 master 在一个或多个 slave 进行初次同步或者是部分重同步时,可以继续处理查询请求。
- 复制在 slave 侧大部分也是非阻塞的。当 slave 进行初次同步时,它可以使用旧数据集处理查询请求,假设你在 redis.conf 中配置了让 Redis 这样做的话。否则,你可以配置如果复制流断开, Redis slave 会返回一个 error 给客户端。但是,在初次同步之后,旧数据集必须被删除,同时加载新的数据集。 slave 在这个短暂的时间窗口内(如果数据集很大,会持续较长时间),会阻塞到来的连接请求。自 Redis 4.0 开始,可以配置 Redis 使删除旧数据集的操作在另一个不同的线程中进行,但是,加载新数据集的操作依然需要在主线程中进行并且会阻塞 slave 。
- 复制既可以被用在可伸缩性,以便只读查询可以有多个 slave 进行(例如 O(N) 复杂度的慢操作可以被下放到 slave ),或者仅用于数据安全。
- 可以使用复制来避免 master 将全部数据集写入磁盘造成的开销:一种典型的技术是配置你的 master Redis.conf 以避免对磁盘进行持久化,然后连接一个 slave ,其配置为不定期保存或是启用 AOF。但是,这个设置必须小心处理,因为重新启动的 master 程序将从一个空数据集开始:如果一个 slave 试图与它同步,那么这个 slave 也会被清空。
1. 当 master 关闭持久化时,复制的安全性
在使用 Redis 复制功能时的设置中,强烈建议在 master 和在 slave 中启用持久化。当不可能启用时,例如由于非常慢的磁盘性能而导致的延迟问题,应该配置实例来避免重置后自动重启。
为了更好地理解为什么关闭了持久化并配置了自动重启的 master 是危险的,检查以下故障模式,这些故障模式中数据会从 master 和所有 slave 中被删除:
- 我们设置节点 A 为 master 并关闭它的持久化设置,节点 B 和 C 从 节点 A 复制数据。
- 节点 A 崩溃,但是他有一些自动重启的系统可以重启进程。但是由于持久化被关闭了,节点重启后其数据集合为空。
- 节点 B 和 节点 C 会从节点 A 复制数据,但是节点 A 的数据集是空的,因此复制的结果是它们会销毁自身之前的数据副本。
当 Redis Sentinel 被用于高可用并且 master 关闭持久化,这时如果允许自动重启进程也是很危险的。例如, master 可以重启的足够快以致于 Sentinel 没有探测到故障,因此上述的故障模式也会发生。
任何时候数据安全性都是很重要的,所以如果 master 使用复制功能的同时未配置持久化,那么自动重启进程这项应该被禁用。
2. Redis 复制功能是如何工作的
每一个 Redis master 都有一个 replication ID :这是一个较大的伪随机字符串,标记了一个给定的数据集。每个 master 也持有一个偏移量,master 将自己产生的复制流发送给 slave 时,发送多少个字节的数据,自身的偏移量就会增加多少,目的是当有新的操作修改自己的数据集时,它可以以此更新 slave 的状态。复制偏移量即使在没有一个 slave 连接到 master 时,也会自增,所以基本上每一对给定的
Replication ID, offset
都会标识一个 master 数据集的确切版本。
当 slave 连接到 master 时,它们使用 PSYNC 命令来发送它们记录的旧的 master replication ID 和它们至今为止处理的偏移量。通过这种方式, master 能够仅发送 slave 所需的增量部分。但是如果 master 的缓冲区中没有足够的命令积压缓冲记录,或者如果 slave 引用了不再知道的历史记录(replication ID),则会转而进行一个全量重同步:在这种情况下, slave 会得到一个完整的数据集副本,从头开始。
下面是一个全量同步的工作细节:
master 开启一个后台保存进程,以便于生产一个 RDB 文件。同时它开始缓冲所有从客户端接收到的新的写入命令。当后台保存完成时, master 将数据集文件传输给 slave, slave将之保存在磁盘上,然后加载文件到内存。再然后 master 会发送所有缓冲的命令发给 slave。这个过程以指令流的形式完成并且和 Redis 协议本身的格式相同。
你可以用 telnet 自己进行尝试。在服务器正在做一些工作的同时连接到 Redis 端口并发出 SYNC 命令。你将会看到一个批量传输,并且之后每一个 master 接收到的命令都将在 telnet 回话中被重新发出。事实上 SYNC 是一个旧协议,在新的 Redis 实例中已经不再被使用,但是其仍然向后兼容:但它不允许部分重同步,所以现在 PSYNC 被用来替代 SYNC。
之前说过,当主从之间的连接因为一些原因崩溃之后, slave 能够自动重连。如果 master 收到了多个 slave 要求同步的请求,它会执行一个单独的后台保存,以便于为多个 slave 服务。
3. 无需磁盘参与的复制
正常情况下,一个全量重同步要求在磁盘上创建一个 RDB 文件,然后将它从磁盘加载进内存,然后 slave以此进行数据同步。
如果磁盘性能很低的话,这对 master 是一个压力很大的操作。Redis 2.8.18 是第一个支持无磁盘复制的版本。在此设置中,子进程直接发送 RDB 文件给 slave,无需使用磁盘作为中间储存介质。
4. 配置
配置基本的 Redis 复制功能是很简单的:只需要将以下内容加进 slave 的配置文件:
slaveof 192.168.1.1 6379
当然你需要用你自己的 master IP 地址(或者主机名)和端口替换掉 192.168.1.1 6379。另一种方法,你也可以使用 SLAVEOF 命令, master 会开启一个跟 slave 间的同步。
还有一些参数用于调节内存中保存的缓冲积压部分(replication backlog),以便执行部分重同步。详见 redis.conf 和 Redis Distribution 了解更多信息。
无磁盘复制可以使用 repl-diskless-sync 配置参数。repl-diskless-sync-delay 参数可以延迟启动数据传输,目的可以在第一个 slave就绪后,等待更多的 slave就绪。可以在 Redis Distribution 例子中的 redis.conf 中看到更多细节信息。
5. 只读性质的 slave
自从 Redis 2.6 之后, slave 支持只读模式且默认开启。redis.conf 文件中的 slave-read-only 变量控制这个行为,且可以在运行时使用 CONFIG SET 来随时开启或者关闭。
只读模式下的 slave 将会拒绝所有写入命令,因此实践中不可能由于某种出错而将数据写入 slave 。但这并不意味着该特性旨在将一个 slave 实例暴露到 Internet ,或者更广泛地说,将之暴露在存在不可信客户端的网络,因为像 DEBUG 或者 CONFIG 这样的管理员命令仍在启用。但是,在 redis.conf 文件中使用 rename-command 指令可以禁用上述管理员命令以提高只读实例的安全性。
您也许想知道为什么可以还原只读设置,并有可以通过写入操作来设置 slave 实例。如果 slave 跟 master 在同步或者 slave 在重启,那么这些写操作将会无效,但是将短暂数据存储在 writable slave 中还是有一些合理的用例的。
例如,计算 slow Set 或者 Sorted Set 的操作并将它们存储在本地 key 中是多次观察到的使用 writable slave 的用例。
但是注意,4.0 版本之前的 writable slaves 不能用生存时间来淘汰 key 。这意味着,如果你使用 EXPIRE 或者其他命令为 key 设置了最大 TTL 的话,你将会在键值计数(count of keys)中看到这个 key ,并且它还在内存中。所以总的来说,将 writable slaves 和设置过 TTL 的 key 混用将会导致问题。
Redis 4.0 RC3 及更高版本彻底解决了这个问题,现在 writable slaves 能够像 master 一样驱逐 TTL 设置过的 key 了,但 DB 编号大于 63(但默认情况下,Redis实例只有16个数据库)的 key 除外。
另请注意,由于 Redis 4.0 writable slaves 仅能本地,并且不会将数据传播到与该实例相连的 sub-slave 上。sub-slave 将总是接收与最顶层 master 向 intermediate slaves 发送的复制流相同的复制流。所以例如在以下设置中:
A —-> B ——> C
及时节点 B 是可写的,C 也不会看到 B 的写入,而是将拥有和 master 实例 A 相同的数据集。
6. 设置一个 slave 对 master 进行验证
如果你的 master 通过 requirepass 设置了密码,则在所有同步操作中配置 slave 使用该密码是很简单的。
要在正在运行的实例上执行此操作,请使用 redis-cli 并输入:
config set masterauth
要永久设置的话,请将其添加到您的配置文件中:
masterauth
7. 允许只写入 N 个附加的副本
从Redis 2.8开始,只有当至少有 N 个 slave 连接到 master 时,才有可能配置 Redis master 接受写查询。
但是,由于 Redis 使用异步复制,因此无法确保 slave 是否实际接收到给定的写命令,因此总会有一个数据丢失窗口。
以下是该特性的工作原理:
- Redis slave 每秒钟都会 ping master,确认已处理的复制流的数量。
- Redis master 会记得上一次从每个 slave 都收到 ping 的时间。
- 用户可以配置一个最小的 slave 数量,使得它滞后 <= 最大秒数。
如果至少有 N 个 slave ,并且滞后小于 M 秒,则写入将被接受。
你可能认为这是一个尽力而为的数据安全机制,对于给定的写入来说,不能保证一致性,但至少数据丢失的时间窗限制在给定的秒数内。一般来说,绑定的数据丢失比不绑定的更好。
如果条件不满足,master 将会回复一个 error 并且写入将不被接受。
这个特性有两个配置参数:
- min-slaves-to-write
- min-slaves-max-lag <秒数>
有关更多信息,请查看随 Redis 源代码发行版一起提供的示例 redis.conf 文件。
8. Redis 复制如何处理 key 的过期
Redis 的过期机制可以限制 key 的生存时间。此功能取决于 Redis 实例计算时间的能力,但是,即使使用 Lua 脚本更改了这些 key,Redis slaves 也能正确地复制具有过期时间的 key。
为了实现这样的功能,Redis 不能依靠主从使用同步时钟,因为这是一个无法解决的并且会导致 race condition 和数据集不一致的问题,所以 Redis 使用三种主要的技术使过期的 key 的复制能够正确工作:
- slave 不会让 key 过期,而是等待 master 让 key 过期。当一个 master 让一个 key 到期(或由于 LRU 算法将之驱逐)时,它会合成一个 DEL 命令并传输到所有的 slave。
- 但是,由于这是 master 驱动的 key 过期行为,master 无法及时提供 DEL 命令,所以有时候 slave 的内存中仍然可能存在在逻辑上已经过期的 key 。为了处理这个问题,slave 使用它的逻辑时钟以报告只有在不违反数据集的一致性的读取操作(从主机的新命令到达)中才存在 key。用这种方法,slave 避免报告逻辑过期的 key 仍然存在。在实际应用中,使用 slave 程序进行缩放的 HTML 碎片缓存,将避免返回已经比期望的时间更早的数据项。
- 在Lua脚本执行期间,不执行任何 key 过期操作。当一个Lua脚本运行时,从概念上讲,master 中的时间是被冻结的,这样脚本运行的时候,一个给定的键要么存在要么不存在。这可以防止 key 在脚本中间过期,保证将相同的脚本发送到 slave ,从而在二者的数据集中产生相同的效果。
一旦一个 slave 被提升为一个 master ,它将开始独立地过期 key,而不需要任何旧 master 的帮助。
9. 在 Docker 和 NAT 中配置复制
当使用 Docker 或其他类型的容器使用端口转发或网络地址转换时,Redis 复制需要特别小心,特别是在使用 Redis Sentinel 或其他系统(其中扫描 master INFO 或 ROLE 命令的输出情况以便于发现 slave 地址的)。
问题是 ROLE 命令和 INFO 输出的复制部分在发布到 master 实例中时,将显示 slave 具有的用于连接到 master 的 IP 地址,而在使用 NAT 的环境中,和 slave 实例的逻辑地址(客户机用来连接 slave 的地址)相比较可能会不同。
类似地,slaves 将以 redis.conf 文件中监听的端口为序列出,在重新映射端口的情况下,该端口可能与转发的端口不同。
为了解决这两个问题,从 Redis 3.2.2 开始,可以强制一个 slave 向 master 通告一对任意的 IP 和端口。使用的两个配置指令是:
slave-announce-ip 5.5.5.5
slave-announce-port 1234
在近期 Redis distributions 中的 redis.conf 的样例中可以找到记录。
10. INFO 和 ROLE 命令
有两个 Redis 命令可以提供有关主从实例当前复制参数的很多信息。一个是INFO。如果使用复制参数像 INFO replication 调用该命令,,则只显示与复制相关的信息。另一个更加 computer-friendly 的命令是 ROLE,它提供 master 和 slave 的复制状态以及它们的复制偏移量,连接的 slaves 列表等等。
11. 重新启动和故障转移后的部分重同步
从 Redis 4.0 开始,当一个实例在故障转移后被提升为 master 时,它仍然能够与旧 master 的 slaves 进行部分重同步。为此,slave 会记住旧 master 的旧 replication ID 和复制偏移量,因此即使询问旧的 replication ID,其也可以将部分复制缓冲提供给连接的 slave 。
但是,升级的 slave 的新 replication ID 将不同,因为它构成了数据集的不同历史记录。例如,master 可以返回可用,并且可以在一段时间内继续接受写入命令,因此在被提升的 slave 中使用相同的 replication ID 将违反一对复制标识和偏移对只能标识单一数据集的规则。
另外,slave 在关机并重新启动后,能够在 RDB 文件中存储所需信息,以便与 master 进行重同步。这在升级的情况下很有用。当需要时,最好使用 SHUTDOWN 命令来执行 slave 的保存和退出操作。