redis cli的特殊用法包括下面这些:
1. 查看一个redis server的运行状态,可以用在监控报警上。
2. 扫描redis数据中的very large keys
3. 带有模式匹配的键空间扫描
4. 作为订阅频道的pub/sub客户端
5. 监控在redis实例上执行的命令
6. 检查redis server的延迟
7. 检查机器的调度延迟
8. 获取远端redis server的rdb backup,并保存到本地
9. 作为redis server的一个slave,查看一个slave收到了哪些消息
10. 模拟LRU负载,查看keys的命中率
1. 连续状态模式
可以用来实时监控redis server实例的运行状态。用法如下:
$ redis-cli --stat ------- data ------ --------------------- load -------------------- - child - keys mem clients blocked requests connections 506 1015.00K 1 0 24 (+0) 7 506 1015.00K 1 0 25 (+1) 7 506 3.40M 51 0 60461 (+60436) 57 506 3.40M 51 0 146425 (+85964) 107 507 3.40M 51 0 233844 (+87419) 157 507 3.40M 51 0 321715 (+87871) 207 508 3.40M 51 0 408642 (+86927) 257 508 3.40M 51 0 497038 (+88396) 257
在这种模式下,每秒会打印出redis server的状态信息,以及两次打印的差值(在括号中)。但是差值信息,并不是一定准确,我测试的时候,有过如下的打印:
------- data ------ --------------------- load -------------------- - child - keys mem clients blocked requests connections 3 562.48K 1 0 0 (+0) 1 3 562.48K 1 0 1 (+0) 1 3 562.48K 1 0 2 (+1) 1 3 562.48K 1 0 3 (+1) 1 3 562.48K 1 0 4 (+1) 1 3 562.48K 1 0 5 (+1) 1 3 562.48K 1 0 6 (+1) 1 3 562.48K 1 0 7 (+1) 1 3 562.48K 1 0 8 (+1) 1 3 562.48K 1 0 9 (+1) 1
其中第二行信息的差值信息存在错误。这个算是细枝末节的东西,只是在这里说明一下。通过--stat,你可以很容易知道redis server的内存使用状态,客户连接数,每秒请求个数等信息。通过-i <interval>选择,你可以改变打印的频率。默认情况下是1秒打印一次。
2. 扫描 big keys
在这种模式下,redis-cli作为键空间的分析器。redis cli扫描数据中的big keys,同时也会给出数据中的类型信息。用法如下:
$ redis-cli --bigkeys # Scanning the entire keyspace to find biggest keys as well as # average sizes per key type. You can use -i 0.1 to sleep 0.1 sec # per 100 SCAN commands (not usually needed). [00.00%] Biggest string found so far 'key-419' with 3 bytes [05.14%] Biggest list found so far 'mylist' with 100004 items [35.77%] Biggest string found so far 'counter:__rand_int__' with 6 bytes [73.91%] Biggest hash found so far 'myobject' with 3 fields -------- summary ------- Sampled 506 keys in the keyspace! Total key length in bytes is 3452 (avg len 6.82) Biggest string found 'counter:__rand_int__' has 6 bytes Biggest list found 'mylist' has 100004 items Biggest hash found 'myobject' has 3 fields 504 strings with 1403 bytes (99.60% of keys, avg size 2.78) 1 lists with 100004 items (00.20% of keys, avg size 100004.00) 0 sets with 0 members (00.00% of keys, avg size 0.00) 1 hashs with 3 fields (00.20% of keys, avg size 3.00) 0 zsets with 0 members (00.00% of keys, avg size 0.00)
在第一部分的输出中,同一个类型中,每个新的更加大的key会被打印出来。总结部分会给出redis实例一般的状态信息。输出信息通过scan命令获取。
3. 获取keys的列表
通过redis cli可以在不阻塞redis server的情况下,获取键的列表,打印出所有,或者通过特定模式过滤,只打印出符合过滤模式的键。获取键列表,也是通过SCAN命令,所以返回的键的保证和直接使用SCAN命令一致。感觉这个就只是SCAN命令的简单封装,没有特别的地方。用法如下:
$ redis-cli --scan | head -10 key-419 key-71 key-236 key-50 key-38 key-458 key-453 key-499 key-446 key-371
$ redis-cli --scan --pattern '*-11*' key-114 key-117 key-118 key-113 key-115 key-112 key-119 key-11 key-111 key-110 key-116
$ redis-cli --scan --pattern 'user:*' | wc -l 3829433
4. Pub/sub模式
redis cli可以使用publish命令将消息发布到redis的pub/sub频道。订阅消息和发布消息有所不同,因为订阅消息需要阻塞等待消息的到达。订阅消息的用法如下:
$ redis-cli psubscribe '*' Reading messages... (press Ctrl-C to quit) 1) "psubscribe" 2) "*" 3) (integer) 1
上面的打印中的“Reading messages"表示redis cli进入订阅模式。其中的"*"表示订阅任何频道,如果这时候一个client在一个channel中发布消息,例如:
redis-cli PUBLISH mychannel mymessage,
上面订阅的redis cli会打印如下信息:
1) "pmessage" 2) "*" 3) "mychannel" 4) "mymessage"
这个对于调试pub/sub的问题很有用处。
5. 监控redis中执行的命令
这个命令的用法如下,进入监控模式,这个redis cli就会打印被监控的redis server收到的所有命令。
$ redis-cli monitor OK 1460100081.165665 [0 127.0.0.1:51706] "set" "foo" "bar" 1460100083.053365 [0 127.0.0.1:51707] "get" "foo"
这个功能,同样对于调试很有用处。当你进行一个修改redis中的key的操作,发现没有按照你预料的情况变化时,这时候,你就可以使用redis的monitor模式。查看
(1)这个redis server是否收到你的修改请求
(2)这个redis server收到的修改请求是否正确
(3)这个redis server有没有收到你的查询请求
(4)这个redis server收到的查询请求是否正确
这样,你调试redis的使用就会很方便。
6. 监控redis实例的延迟
redis作为内存数据库,经常被用在延迟要求很高的场景,有很多因素会影响延迟,包括应用中的处理,从redis client库的网络调用,以及redis自身的延迟。
redis cli提供了很多选项用来了解一个redis实例的延迟,包括最大值,平均值和分布。有一点需要注意,这个命令可以用来查看一个远端的redis server的延迟信息,但是需要确保,本地的redis cli连接redis server可以正常发送命令,例如可以使用一个get命令,查看redis server能够给出正确的结果。
我曾经试过,对于一个远端的redis server注释了bind 127.0.0.1,这种情况下,redis cli可以连接到远端的redis server,但是不能正常执行命令。你还需要将protected-mode改为no,这样才可以正常测试延迟。这里只是用来说明latency的用法,不涉及安全问题,对于redis的安全问题,在部署上线的时候,需要认真考虑。
用来检测延迟的基本工具是--latency选项。使用这个选项,redis-cli会启动一个循环,然后记录从发送一个ping给redis server,到收到redis server响应的延迟。状态会实时显示在界面上。
$ redis-cli --latency min: 0, max: 1, avg: 0.19 (427 samples)
状态信息的时间单位是毫秒。由于redis-cli的系统调度等原因,给出的值可能偏大,但是,对于要求为毫秒的应用来说,这个值已经足够精确。
有时候,我们想知道随着时间变化,延迟的变化,就可以使用--latency-history。这个选项每15秒启动一个新的测量:
$ redis-cli --latency-history min: 0, max: 1, avg: 0.14 (1314 samples) -- 15.01 seconds range min: 0, max: 1, avg: 0.18 (1299 samples) -- 15.00 seconds range min: 0, max: 1, avg: 0.20 (113 samples)^C
你可以通过-i <interval>将15s改成其他的值。
还有一个用于展示延迟的选项,叫做--latency-dist,可以用来展示延迟分布,比较复杂,在需要的时候,可以自己多了解。
7. 机器的调度延迟
redis-cli还可以用来测试机器的调度延迟,这个有点类似于sysbench对于mysql的用处。这个延迟,受限于底层运行的内核调度,虚拟机的管理程序等。
我们称呼这个为内在延迟,因为这个是对编程人员不可见的。如果你的redis实例延迟很高,除了其他那些明显的问题之外,你可以测试一下这个内在延迟,知道这个延迟,你就知道redis实例在这台机器上运行时,最好的可能延迟情况(当然,实际上一般达不到)。通过使用 --intrinsic-latency <test-time> 参数,测试时间单位为秒。
$ ./redis-cli --intrinsic-latency 5 Max latency so far: 1 microseconds. Max latency so far: 7 microseconds. Max latency so far: 9 microseconds. Max latency so far: 11 microseconds. Max latency so far: 13 microseconds. Max latency so far: 15 microseconds. Max latency so far: 34 microseconds. Max latency so far: 82 microseconds. Max latency so far: 586 microseconds. Max latency so far: 739 microseconds. 65433042 total runs (avg latency: 0.0764 microseconds / 764.14 nanoseconds per run). Worst run took 9671x longer than the average latency.
注:这个命令不依赖于redis server,需要把redis cli运行在需要测试的机器上。
在上面那个例子中,在极端情况下,系统内在延迟可达739 microseconds,可以预见,会时不时出现redis的命令执行时间接近1 millisecond。
7.1 redis的吞吐量
这是与redis的延迟相关的一个变量,对于同步调用redis命令的程序来说,受限于两个因素,一个是延迟,延迟决定着单个redis同步调用线程的最大qps,另外一个影响因素是redis server的吞吐量。这个可以使用redis-benchmark来查看。具体参考:
https://redis.io/topics/benchmarks
8. 获取远端redis server的rdb backup,并保存到本地
在redis server复制的开始同步阶段,主节点和从节点,通过rdb文件格式进行整个数据的同步。redis-cli实现了类似的功能,可以从远端的redis server获取rdb文件。用法如下:
$ redis-cli --rdb /tmp/dump.rdb SYNC sent to master, writing 13256 bytes to '/tmp/dump.rdb' Transfer finished with success.
调用完命令之后,本机的/tmp目录中就会有一个dump.rdb文件。这个是一个简单的周期性备份的方式,类似于mysqldump的功能。使用脚本或者周期任务执行这个功能时,要注意检查一下返回值,像下面这样的,表示获取rdb失败。
$ redis-cli --rdb /tmp/dump.rdb SYNC with master failed: -ERR Can't SYNC while not connected with my master $ echo $? 1
9. 作为redis server的一个slave,查看一个slave收到了哪些消息(从节点模式)
从节点模式,是redis cli的一个高级特性,对于redis开发者以及调试会很有帮助。通过从节点模式,可以查看在复制过程中,主节点发送给从节点的命令。使用方法如下:
$ redis-cli --slave SYNC with master, discarding 13256 bytes of bulk transfer... SYNC done. Logging commands from master. "PING" "SELECT","0" "set","foo","bar" "PING" "incr","mycounter"
这个命令,首先会丢掉第一个同步阶段的rdb文件,然后以csv格式,记下每一个收到的命令。
10. 模拟LRU负载,查看keys的命中率
redis经常作为lru (least recently used) 清理的缓存。取决于keys的数量,以及cache可以使用的内存大小(通过maxmemory命令设定),cache的命中率会产生变化。有时候,通过查看命中率和内存的关系,可以更好的设置内存的大小。
redis cli有一个特殊的模式,可以用80-20%的调用分布,来模式GET和SET操作的场景,在这种常见场景中,在80%的时间,只会使用20%的keys。
从理论上说,给定redis的内存容量,给定调用分布,可以从理论上计算出命中率。但是,redis有不同的lru设置,以及不同的lru实现,这会导致不同版本和不同设置的redis的命中率有所改变。另外,每个key在不同的redis版本的内存占用,也可能发生改变,这个也会影响命中率。通过使用这个工具,就可以真实测试一个指定版本和指定配置的redis的命中率。
为了使用这个模式,你需要指定keys的数量,你还需要设置作为第一次测试合适的maxmemory.
注:maxmemory的设置是必需的,如果没有设置设置,所有的key最终都会缓存到redis server的内存中,命中率最终会达到100%. 如果你使用了太多的keys,但是又没有设置maximum memory,那redis server所在机器的所有内存都会被占用。同时,还需要设置一个合适的maxmemory policy,例如 allkeys-lru,这个取决于你实际场景的需要。
下面这个测试中,我们配置了maxmemory为100M,keys总数为1000万。
注:这个操作对redis server影响较大,不要对正在给客户服务的redis server进行这个测试。
$ ./redis-cli --lru-test 10000000 156000 Gets/sec | Hits: 4552 (2.92%) | Misses: 151448 (97.08%) 153750 Gets/sec | Hits: 12906 (8.39%) | Misses: 140844 (91.61%) 159250 Gets/sec | Hits: 21811 (13.70%) | Misses: 137439 (86.30%) 151000 Gets/sec | Hits: 27615 (18.29%) | Misses: 123385 (81.71%) 145000 Gets/sec | Hits: 32791 (22.61%) | Misses: 112209 (77.39%) 157750 Gets/sec | Hits: 42178 (26.74%) | Misses: 115572 (73.26%) 154500 Gets/sec | Hits: 47418 (30.69%) | Misses: 107082 (69.31%) 151250 Gets/sec | Hits: 51636 (34.14%) | Misses: 99614 (65.86%)
redis cli每秒打印一下当前状态。可以看出,在开始的阶段,keys不断被缓存,到后面命中率不断稳定。
120750 Gets/sec | Hits: 48774 (40.39%) | Misses: 71976 (59.61%) 122500 Gets/sec | Hits: 49052 (40.04%) | Misses: 73448 (59.96%) 127000 Gets/sec | Hits: 50870 (40.06%) | Misses: 76130 (59.94%) 124250 Gets/sec | Hits: 50147 (40.36%) | Misses: 74103 (59.64%)
59%的失败命中率,对我们来说是不可接受的。我们觉得100M的内存太小了,所以将maxmemory改为了0.5GB,经过几分钟后,可以看到如下稳定的命中率数据:
140000 Gets/sec | Hits: 135376 (96.70%) | Misses: 4624 (3.30%) 141250 Gets/sec | Hits: 136523 (96.65%) | Misses: 4727 (3.35%) 140250 Gets/sec | Hits: 135457 (96.58%) | Misses: 4793 (3.42%) 140500 Gets/sec | Hits: 135947 (96.76%) | Misses: 4553 (3.24%)
所以,我们知道,对于80-20分布,1000万条数据,500M的内存可以提供足够高的命中率。对于这种情况,也可以查看如果想要达到100%命中率,需要多少内存,来判断那种方式更加合算。
上述内容主要是对redis官方文档的一个简单翻译,添加了一些自己的说明,如果有兴趣可以查看官方文档:
https://redis.io/topics/rediscli