如何在PHP中使用phpredis删除具有相同模式的多个redis键?

okxuctiv  于 2022-10-31  发布在  Redis
关注(0)|答案(8)|浏览(503)

通过使用phpredis,我以如下分页方式保存了一些数据:

review/itemA/1
   review/itemA/2

其中12是页码。我在文档中读到你可以使用通配符来检索多个键。

$allKeys = $redis->keys('*');   // all keys will match this.
$keyWithUserPrefix = $redis->keys('user*');

但是,当有人发布了新的评论时,我可以使用通配符删除所有旧的键吗?我可以这样做吗:

$redis->delete('review/itemA/*'); // or  $redis->delete('review/itemA*')

然而,这并没有奏效。

hs1ihplo

hs1ihplo1#

不- Redis的DEL不接受通配符,你必须明确地为键命名。https://stackoverflow.com/a/23399125/3160475

3yhwsihp

3yhwsihp2#

当使用phpredis时,可以获取前缀(phpredis会自动在所有地方添加前缀),并删除键的模式:

<?php
...

$prefix = $redisClient->getOption(Redis::OPT_PREFIX);
$redisClient->delete(array_map(
    function ($key) use ($prefix) {
        return str_replace($prefix, '', $key);
    }, $redisClient->keys('*'))
);
z3yyvxxp

z3yyvxxp3#

我只是用

$redis->delete($redis->keys('*'));

我觉得挺好的。

kh212irz

kh212irz4#

Predis(->del)也允许传递一个键数组。
它在这里工作,比foreach内部的del更快。

$prefix = $this->client->getOptions($this->OPT_PREFIX);
$keys = $this->client->keys("$key*");
if ($keys) $this->client->del($keys);
hl0ma9xz

hl0ma9xz5#

$bash = 'redis-cli --scan --pattern "' . $path . '*" | xargs -L 1000 redis-cli DEL';

$res = @shell_exec($bash);
vbopmzt1

vbopmzt16#

对于Predis,我是这样做的:

public function delete($key) {
        $keys = $this->client->keys($key);
        foreach ($keys as $key) {
            $this->client->del($key);
        }
    }
4ioopgfo

4ioopgfo7#

删除函数没有通配符解决方法如下,

// returns total number of keys deleted
function delete($key) {
    if (empty($key)) {  // empty key can delete all
      return false;
    }
    $keys = $redis->keys("$key*");  // keys() function returns array of key strings. `*` wild card pattern can be changed as per need
    if(!$keys) {
        return 0;
    }
    $prefix = $redis->getOption(\Redis::OPT_PREFIX); // keys already have prefix, so we clear until delete finish.
    $redis->setOption(\Redis::OPT_PREFIX, '');
    $count = $redis->del($keys);  // del() function delete array of keys and returns number of keys deleted.
    $redis->setOption(\Redis::OPT_PREFIX, $prefix);

    return $count;
}

**注意:**正如@Akash Gangrade所评论的,由于性能原因,不建议使用keys()。您可以考虑基于标签的缓存失效,如https://symfony.com/doc/current/components/cache/cache_invalidation.html#tag-aware-adapters

3bygqnnd

3bygqnnd8#

使用scanunlink是最佳实践,因为它们与 * key * 和 delete 不同,是非阻塞命令


# The keys set in redis

/*
1) "review/itemA/5"
2) "review/itemA/2"
3) "review/itemA/3"
4) "review/itemA/1"
5) "review/itemA/4"

* /

/**
 * vars used for scan
 */
$i = null;
$result = [];

/**
 * scan redis using desired pattern
 */
while ($result != 0) {
    $result = $redis->scan($i, 'review/itemA/*');
    if (!empty($result)) {
        $all_keys[] = $result;
    }
}

# Use call_user_func_array to flatten multidimensional array into indexed array

## Scan may return duplicate keys, so use array_unique

$unlink_keys = array_unique(call_user_func_array('array_merge', $all_keys));

# As of Redis 4.0 use unlink instead of del to stop blocking

$redis->unlink($unlink_keys);

相关问题