-
博文分类专栏
- Jquery基础教程
-
- 文章:(15)篇
- 阅读:46567
- shell命令
-
- 文章:(42)篇
- 阅读:154239
- Git教程
-
- 文章:(36)篇
- 阅读:234850
- leetCode刷题
-
- 文章:(76)篇
- 阅读:131794
-
redis中通过scan命令来搞定keys命令不可用的场景2018-09-15 17:30 阅读(11308) 评论(0)
一、概述
在redis中,我们经常通过keys命令,来查看当前redis中键,它是一个相当不错的命令,格式如下:
KEYS pattern
比如:
KEYS * 匹配数据库中所有 key 。
KEYS fi?d 匹配单个字符,如find、fied等
KEYS find*.wang 匹配一个或多个字符,比findme.wang
KEYS fin[de]me 匹配指定的字符,即匹配findme或fineme。
最近有个需求,需要删除redis中旧数据,其中键中含有日期,如下:
我想把3天前的数据,都删除,怎么搞呢?
首先,我想到的是通过 key hash.out.*,匹配出该类型的所有key,然后提取key中的日期,根据提取的日期做删除操作。
发现既然报错:
(error) ERR unknown command 'key'
原来当数据规模较大时使用,KEYS命令,会严重影响Redis性能,也非常危险,于是被禁用掉了。
既然key命令没了,只能能够scan命令来解决。
二、scan命令
SCAN 命令是一个基于游标的迭代器(cursor based iterator),每次被调用之后, 都会向用户返回一个 新的游标 , 用户在下次迭代时需要使用这个新游标作为 SCAN 命令的游标参数, 以此来延续之前的迭代过程。当 SCAN 命令的游标参数被设置为 0 时, 服务器将开始一次新的迭代, 而当服务器向用户返回值为 0 的游标时, 表示迭代已结束。
scan命令格式如下:
SCAN cursor [MATCH pattern] [COUNT count]
参数描述:
cursor,即游标;
MATCH pattern 匹配的格式,和keys命令匹配类似;
COUNT count 就是让用户告知迭代命令, 在每次迭代中应该从数据集里返回多少元素
三、解决方案
通过scan命令的了解,我们是可以通过scan命令来解决问题的。命令格式如下:
scan 0 MATCH hash.out.*
这样就可以匹配出一hash.out.开头的key
php的实现如下:
$index = 0; $matchKey = 'hash.out.*'; $data = $redis->scan($index, ['MATCH', $matchKey]); if (empty($data)) { return; } $nextId = array_shift($data); $data = array_shift($data); while ($nextId != $index) { //删除旧数据 foreach ($data as $curKey) { if (empty($curKey)) { continue; } $curDay = end(explode('.', $curKey)); if ($twoDaysAgo > $curDay) { //删除当前key $redis->del($curKey); } } $data = $redis->scan($nextId, ['MATCH', $matchKey]); if (empty($data)) { break; } $nextId = array_shift($data); $data = array_shift($data); }