首頁  >  文章  >  後端開發  >  php redis 批次刪除keys的方法

php redis 批次刪除keys的方法

藏色散人
藏色散人原創
2020-10-07 00:38:095686瀏覽

php redis批次刪除keys的方法:先開啟指令視窗;然後透過指令「redis-cli keys video* | xargs redis-cli del」實作批次刪除key即可。

php redis 批次刪除keys的方法

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(&#39;127.0.0.1&#39;, self::PORT);
    }

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

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

        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, &#39;del&#39;], $arr_keys);

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

返回結果

array (
  0 => &#39;test:8&#39;,
)
array (
  0 => &#39;test:1&#39;,
)
array (
  0 => &#39;test:9&#39;,
)
array (
  0 => &#39;test:6&#39;,
)
array (
  0 => &#39;test:5&#39;,
)
array (
  0 => &#39;test:0&#39;,
)
array (
  0 => &#39;test:3&#39;,
)
array (
  0 => &#39;test:7&#39;,
)
array (
  0 => &#39;test:4&#39;,
)
array (
  0 => &#39;test:2&#39;,
)

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, &#39;del&#39;], $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, &#39;del&#39;], $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;
        }

以上是php redis 批次刪除keys的方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn