视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
php redis 批量删除keys的方法
2020-11-02 18:22:19 责编:小采
文档


php redis批量删除keys的方法:首先打开命令窗口;然后通过命令“redis-cli keys video* | xargs redis-cli del”实现批量删除key即可。

redis实现批量删除key功能

推荐:《PHP视频教程》

keys

在测试环境使用redis的时候,经常会要批量删除key,我们但是redis并没有提供批量删除的命令,但是我们可以在命令行下,使用keys遍历键实现

//批量删除以video开头的key
redis-cli keys video* | xargs redis-cli del

//以j,r开头,紧跟edis字符串的所有键
redis-cli keys [j,r]edis | xargs redis-cli del
注意:
 redis是单线程架构,如果redis包含了大量的键,执行keys命令可能会造成redis阻塞,所以一般建议不要在生产环境下使用keys命令。
 如果非要遍历键删除的话,可以在一下三种情况使用:
 (1)在一个不对外提供服务的Redis从节点上执行,这样不会阻塞到客户端的请求,但是会影响到主从复制。
 (2)如果确认键值总数确实比较少,可以执行该命令。
 (3)使用scan命令渐进式的遍历所有键,可以有效防止阻塞。

渐进式遍历

scan命令文档

Redis提供了面向哈希类型、集合类型、有序集合的扫描遍历命令,解决诸如hgetall、smembers、zrange可能产生的阻塞问题,对应的命令分别是hscan、sscan、zscan,它们的用法和scan基本类似。

注意:
渐进式遍历可以有效的解决keys命令可能产生的阻塞问题,但是scan并非完美无瑕,如果在scan的过程中如果有键的变化(增加、删除、修改),
那么遍历效果可能会碰到如下问题:新增的键可能没有遍历到,遍历出了重复的键等情况,也就是说scan并不能保证完整的遍历出来所有的键,这些是我们在开发时需要考虑的。

<?php

namespace Redis;


use Redis;

class RedisTest
{
 const PORT = 6379;

 /**
 * redis对象
 */
 public $redis = null;

 public function __construct()
 {
 $this->redis = new Redis();
 $this->redis->connect('127.0.0.1', self::PORT);
 }

 public function info()
 {
 print_r($this->redis->info());
 }

 /**
 * 删除前缀是test:的key
 */
 public function keyDelete()
 {
 $pre = 'test:';

 for ($i = 0; $i < 10; $i++) {
 $this->redis->set($pre . "$i", "$i");
 }

 // Have scan retry
 $this->redis->setOption(Redis::OPT_SCAN, Redis::SCAN_RETRY);

 $it = NULL;
 while ($arr_keys = $this->redis->scan($it, "$pre*", 5)) {
 call_user_func_array([$this->redis, 'del'], $arr_keys);

 echo var_export($arr_keys, true) . PHP_EOL;
 }
 }
}

返回结果

array (
 0 => 'test:8',
)
array (
 0 => 'test:1',
)
array (
 0 => 'test:9',
)
array (
 0 => 'test:6',
)
array (
 0 => 'test:5',
)
array (
 0 => 'test:0',
)
array (
 0 => 'test:3',
)
array (
 0 => 'test:7',
)
array (
 0 => 'test:4',
)
array (
 0 => 'test:2',
)

SSCAN、HSCAN、ZSCAN、SCAN命令的坑

// Have scan retry
 $this->redis->setOption(Redis::OPT_SCAN, Redis::SCAN_RETRY);

 $it = NULL;
 while ($arr_keys = $this->redis->scan($it, "$pre*", 5)) {
 call_user_func_array([$this->redis, 'del'], $arr_keys);

 echo var_export($arr_keys, true) . PHP_EOL;
 }

根据scan的文档说明可知:scan命令每次迭代的时候,有可能返回空,但这并不是结束的标志,而是当返回的迭代的值为”0″时才算结束。

因此,上面的代码在迭代的时候,若没有arr_keys返回,$arr_keys是个空数组,所以while循环自然就中断了,所以没有任何输出。

为了避免arr_keys返回是个空数组的问题我们可以这样解决:

解决方法一
 $this->redis->setOption(Redis::OPT_SCAN, Redis::SCAN_RETRY);

告诉redis扩展,当执行scan命令后,返回的结果集为空的话,函数不返回,而是直接继续执行scan命令。这样当scan函数返回的时候,要么返回false,即迭代结束。

注意:SSCAN、HSCAN、ZSCAN也是一样的逻辑

解决方法二

 //方式一
 // Have scan retry
 $this->redis->setOption(Redis::OPT_SCAN, Redis::SCAN_RETRY);

 $it = NULL;
 while ($arr_keys = $this->redis->scan($it, "$pre*", 5)) {
 call_user_func_array([$this->redis, 'del'], $arr_keys);

 echo var_export($arr_keys, true) . PHP_EOL;
 }
 

 //方式二
 while (true) {
 $arr_keys = $this->redis->scan($it, "$pre*");
 if ($arr_keys === false) {//迭代结束,未找到匹配pattern的key
 return;
 }

 call_user_func_array([$this->redis, 'del'], $arr_keys);

 echo var_export($arr_keys, true) . PHP_EOL;
 }

下载本文
显示全文
专题