当有大量数据需要清除的时候,可以使用del批量删除 del k1 k2 …
但是当要删除的key是需要通过匹配来获得的时候,或许最先想到的办法就是先通过keys拿到这些key,然后拼接到 del 后面,这样是能解决问题,但是首先keys会造成短暂的阻塞,其次keys的返回,其次 del 后面的n个key的长指令也需要传输时间,实际上我们并不关心都是哪些key被删除了,于是我们可以lua脚本来实现。
1、当你可以预知这些key数量不是很多的时候
$keyPre = Read3Repository::CACHEPRE . Read3Repository::CACHE_DEPART_RANK . $activity_id . '_*';
$script = "return redis.call('del', unpack(redis.call('keys', ARGV[1])))";
$res = Redis::eval($script, 0, $keyPre);// 0表示没有传key值
2、当key的数量可能很大的时候
$keyPre = Read3Repository::CACHEPRE . Read3Repository::CACHE_DEPART_RANK . $activity_id . '_*';
$script = "local keys = redis.call('keys', ARGV[1]) for i=1,#keys,5000 do redis.call('del', unpack(keys, i, math.min(i+4999, #keys))) end return #keys";
$res = Redis::eval($script, 0, $keyPre);// 0表示没有传key值
3、命令行
/work/app/redis/bin/redis-cli -a youpassword EVAL "local keys = redis.call('keys', ARGV[1]) for i=1,#keys,5000 do redis.call('del', unpack(keys, i, math.min(i+4999, #keys))) end return #keys" 0 'Volume:*'
或者
/work/app/redis/bin/redis-cli -a youpassword EVAL "return redis.call('del', unpack(redis.call('keys', ARGV[1])))" 0 'Volume:*'
或者
/work/app/redis/bin/redis-cli -a youpassword keys 'Volume:*' | xargs /work/app/redis/bin/redis-cli -a youpassword del
4、推荐使用配合scan
public static function deleteRead3DepartRankById($activity_id)
{
$keyPre = Read3Repository::CACHEPRE . Read3Repository::CACHE_DEPART_RANK . $activity_id . '_*';
$keys = self::scanGetKeys($keyPre);
$set = [];
foreach ($keys as $v) {
array_push($set, $v);
}
call_user_func_array([Redis::class, 'del'], $set);
return true;
}
public static function scanGetKeys($pattern, $count = 50)
{
$ret = [];
$iterator = 0;
while (true) {
$result = Redis::rawCommand("scan", $iterator, 'match', $pattern, 'count', $count);
if ($result === false) {
break;
}
$ret = array_merge($ret, $result[1]);
$iterator = $result[0];
if($result[0] == 0){
break;
}
}
return $ret;
}