使用tcpdump排查zRangeByScore参数无效问题

在做列表数据分页的时候,是将数据存储在redis的有序集合中实现的

核心代码如下

1
zRangeByScore($key, '-inf', '+inf', array('limit' => array($start, $size)));

问题

在进行翻页的时候,传入start=10,size=10,没有获取到新一页的数据,而是返回有序集合所有的数据

排查过程

排查命令是否写错

注:「将start和size写成定值」

1
zRangeByScore($key, '-inf', '+inf', array('limit' => array(10, 10)));

数据正常返回,排查传参问题

打印start,size

1
2
3
4
5
6
7
8
9
array(1) {
["limit"]=>
array(2) {
[0]=>
string(2) "10"
[1]=>
string(2) "10"
}
}

结果出乎意料,start,size传入没有问题
可是传入的都是page=10,size=10
为什么两种方式的结果会不一样,redis最终执行的是什么命令呢?

查看redis最终执行的命令

在服务器用tcpdump抓取redis的网络包
注:「在开发服务器执行tcpdump命令;redis端口为6379」

1
[root@test01v /]# tcpdump port 6379 and tcp -X -s 0

当走传参的方式的时候,最终redis执行的命令是这样的

1
2
3
4
5
6
7
8
9
10
02:46:46.220417 IP local_host.45816 > redis_host.6379: Flags [P.], seq 38:129, ack 6, win 29200, length 91
0x0000: 4500 0083 d940 4000 4006 32a2 ac11 0005 E....@@.@.2.....
0x0010: 0a83 77f9 b2f8 1875 e8b6 5ad8 4953 9e07 ..w....u..Z.IS..
0x0020: 5018 7210 2f08 0000 2a35 0d0a 2431 330d P.r./...*5..$13.
0x0030: 0a5a 5241 4e47 4542 5953 434f 5245 0d0a .ZRANGEBYSCORE..
0x0040: 2432 330d 0a70 6572 6665 6374 5f63 6f6d $23..perfect_com
0x0050: 6d65 6e74 5f69 645f 6c69 7374 0d0a 2434 ment_id_list..$4
0x0060: 0d0a 2d69 6e66 0d0a 2434 0d0a 2b69 6e66 ..-inf..$4..+inf
0x0070: 0d0a 2431 300d 0a57 4954 4853 434f 5245 ..$10..WITHSCORE
0x0080: 530d 0a S..

可以看出传输的redis的命令为

1
ZRANGEBYSCORE perfect_comment_id_list -inf +inf WITHSCORES

没有limit参数信息,当然会返回有序集合所有的数据

对比传入数据后发现:
定值的时候传入的是数字类型,传参的方式传入的是字符串类型

猜测是因为php连接redis的拓展的问题
当传入的start,size参数为字符串类型的时候会被过滤掉

为什么要这样做呢,难道是redis不支持吗
测试后发现redis是支持的

愉快的将参数做了类型转换,问题得到解决

最后也没忘记给phpredis提了一个issue

「注:phpredis的版本为3.0.0」

后记:在tcpdump使用的时候,也可以用来查询执行的MySQL语句
比如说,当我需要去熟悉一个新业务或者排查bug的时候,我会将该业务的sql语句都抓取出来
命令如下

1
tcpdump -A -s 0 port 3306 and tcp > ~/sql.log

感兴趣的朋友可以试试

坚持原创技术分享,您的支持将鼓励我继续创作!