php使用redis的scan命令时遇到的坑
2018-04-03 22:36
591 查看
以前的项目中有用到redis的keys命令来获取某些key,这个命令在数据库特别大的情况会block很长一段时间,所以有很大的安全隐患,所以这次打算优化一下。官网建议使用scan命令来代替。于是就用了……以下是使用scan命令来匹配相应模式的key的代码:
使用keys命令可以得到设置的”test1″,”test2″,…..,”test5″这5个key,但是使用scan却什么也没有输出。………………………………经过多方分析,最终发现,是scan命令的返回值有问题。其实redis的官方文档也明确说了,scan命令每次迭代的时候,有可能返回空,但这并不是结束的标志,而是当返回的迭代的值为”0″时才算结束。因此,上面的代码在迭代的时候,若没有key返回,$keys是个空数组,所以while循环自然就中断了,所以没有任何输出。这种情况在redis中key特别多的时候尤其明显,当key只有几十个上百个的时候,很少会出现这种情况,但是当key达到上千万,这种情况几乎必现。要减少这种情况的出现,可以通过将scan函数的第三个参数count设定为一个较大的数。但这不是解决此问题的根本办法,根本办法有以下两种:1.setOption通过setOption函数来设定迭代时的行为。以下是示例代码:
$redis = new Redis(); $redis->connect('localhost', 6379); $iterator = null; while ($keys = $redis->scan($iterator, 'test*')) { foreach ($keys as $key) { echo $key . PHP_EOL; } }这代码应该没问题吧?这是从jetbrains 公司旗下软件phpstorm的代码提示库中摘出来的,只加了pattern参数,但是运行结果却是有问题的。
使用keys命令可以得到设置的”test1″,”test2″,…..,”test5″这5个key,但是使用scan却什么也没有输出。………………………………经过多方分析,最终发现,是scan命令的返回值有问题。其实redis的官方文档也明确说了,scan命令每次迭代的时候,有可能返回空,但这并不是结束的标志,而是当返回的迭代的值为”0″时才算结束。因此,上面的代码在迭代的时候,若没有key返回,$keys是个空数组,所以while循环自然就中断了,所以没有任何输出。这种情况在redis中key特别多的时候尤其明显,当key只有几十个上百个的时候,很少会出现这种情况,但是当key达到上千万,这种情况几乎必现。要减少这种情况的出现,可以通过将scan函数的第三个参数count设定为一个较大的数。但这不是解决此问题的根本办法,根本办法有以下两种:1.setOption通过setOption函数来设定迭代时的行为。以下是示例代码:
$redis = new Redis(); $redis->connect('localhost', 6379); $redis->setOption(Redis::OPT_SCAN,Redis::SCAN_RETRY); $iterator = null; while ($keys = $redis->scan($iterator, 'test*')) { foreach ($keys as $key) { echo $key . PHP_EOL; } }和上面的代码相比,只是多了个setOption的操作,这个操作的作用是啥呢?这个操作就是告诉redis扩展,当执行scan命令后,返回的结果集为空的话,函数不返回,而是直接继续执行scan命令,当然,这些步骤都是由扩展自动完成,当scan函数返回的时候,要么返回false,即迭代结束,未发现匹配模式pattern的key,要么就返回匹配的key,而不再会返回空数组了。 2.while(true)上面那种方式是由php的扩展自动完成的,那么我们也可以换一种写法来达到相同的效果。
$redis = new Redis(); $redis->connect('localhost', 6379); $iterator = null; while (true) { $keys = $redis->scan($iterator, 'test*'); if ($keys === false) {//迭代结束,未找到匹配pattern的key return; } foreach ($keys as $key) { echo $key . PHP_EOL; } }
相关文章推荐
- redis集群 - 使用php连接redis集群、redis自定义命令封装
- php redis扩展支持scan命令实现方法
- RedisTemplate SCAN 命令的使用和注意事项
- redis scan 命令遇到的坑总结
- centos 5 使用kangle命令扩展架设php网站
- PHP执行linux系统命令的常用函数使用说明
- 使用 php ssh2 模块实现远程执行命令
- 把php.exe加入系统环境变量-使用命令行可快速执行PHP命令
- PHP 中使用命令行工具 在 Web 应用程序中运行 shell 命令
- php使用中遇到的问题
- 使用php shell命令合并图片的代码
- 使用Oracle中fileopen命令加载文件时遇到的怪问题
- phpredis使用方法
- php中使用exec,system等函数调用系统命令
- php中使用exec,system等函数调用系统命令
- php-redis客户端使用方法
- lftp命令使用 操作系统(Windows、Linux) PHP学会网 php培训网 PHP暑期培训 PHP寒假培训 PHP假期培训 - powered by phpwhy.com
- PHP执行linux系统命令的常用函数使用说明
- 在 PHP 中使用命令行工具 在 Web 应用程序中运行 shell 命令
- Linux下使用whatis命令遇到错误的解决方法