phpredis在阿里云集群版Redis使用scan命令遇到的坑

发布时间:2018年04月24日 // 分类:代码 // 2 条评论

在利用phpredis扩展使用阿里云集群版Redis时,scan命令出现了奇怪的问题。集群节点0的CPU占用率飙到100%,数据却出不来。

跟踪scan的代码后发现,scan的游标卡在了72057594037927936上(2的56次方)。因为用的是phpredis官方文档提供的do{}while()方式循环扫描,游标卡在72057594037927936上就导致了死循环。这也解释了为什么CPU会飙到100%。

而使用Redis Desktop Manager管理Redis内容,使用scan方法管理列出key时,并未出错,但游标可以达到500000000000000000以上。

由此可以判断,phpredis在读取scan返回游标时可能发生了溢出。

在几乎不可能改动phpredis扩展的代码的情况下,好在phpredis支持直接执行命令,配合阿里redis集群版的自研命令iscan进行查询还是可以满足需求。(详见https://help.aliyun.com/knowledge_detail/51306.html)

以下是phpredis直接执行redis命令的方法(官方文档:https://github.com/phpredis/phpredis#rawcommand ):

/**
 * Send arbitrary things to the redis server.
 * @param   string      $command    Required command to send to the server.
 * @param   mixed       ...$arguments  Optional variable amount of arguments to send to the server.
 * @return  mixed
 * @example
 * <pre>
 * $redis->rawCommand('SET', 'key', 'value'); // bool(true)
 * $redis->rawCommand('GET", 'key'); // string(5) "value"
 * </pre>
 */
public function rawCommand( $command, $arguments ) {}

使用类似下面的方法即可实现scan:

$it=0; // 初始化游标
$idx=0;  // Redis节点ID

$scan_res = $redis->rawCommand('ISCAN', $idx, $it, 'MATCH', 'abc:*', 'COUNT', 10000);
$it=$scan_res[0];
$arr_keys = $scan_res[1];

需要注意的是:

  • 游标从0开始,phpredis原本的scan是从null开始的。
  • rawCommand传入游标进行scan后并不会自动修改传入变量,需要在返回结果时额外赋值。

本文固定链接
https://www.ywlib.com/archives/141.html

标签
redis, phpredis, 阿里云

已有 2 条 关于 " phpredis在阿里云集群版Redis使用scan命令遇到的坑 "的评论.

  1. xuesheng

    phpredis版本的问题。
    phpredis 5.3.0 fixed.
    * Use long for SCAN iteration to fix potential overflow [f13f9b7c]
    (Victor Kislov)

添加新评论 »

分类
随机文章
最新文章
最近回复