PHP가 redis 스캔 명령을 사용할 때 발생하는 함정

不言
풀어 주다: 2023-03-23 07:50:01
원래의
5030명이 탐색했습니다.


이전 프로젝트에서는 특정 키를 얻기 위해 redis의 keys 명령을 사용했습니다. 이 명령은 데이터베이스가 특히 큰 경우 오랫동안 차단되므로 보안 위험이 크기 때문에 이번에는 계획하고 있습니다. 한 번 최적화해 보세요.

공식 웹사이트에서는 대신 스캔 명령을 사용할 것을 권장합니다. 그래서 사용했는데...


다음은 해당 패턴의 키를 맞추기 위해 스캔 명령어를 사용하는 코드입니다.

$redis = new Redis();
$redis->connect('localhost', 6379);

$iterator = null;while ($keys = $redis->scan($iterator, 'test*')) {    foreach ($keys as $key) {        echo $key . PHP_EOL;
    }
}
로그인 후 복사

이 코드는 괜찮겠죠? 이는 jetbrains 회사 소유의 소프트웨어인 phpstorm의 코드 프롬프트 라이브러리에서 가져온 것입니다. 패턴 매개변수만 추가되었지만 실행 결과에 문제가 있습니다.

PHP가 redis 스캔 명령을 사용할 때 발생하는 함정

key 명령을 사용하면 "test1", "test2",..., "test5"의 5개 키 세트를 얻을 수 있지만 스캔을 사용할 때 아무것도 출력되지 않습니다.

……

…………

…………

다자간 분석 결과, 마침내 스캔 명령의 반환 값에 문제가 있는 것으로 확인되었습니다.

실제로 Redis 공식 문서에도 scan 명령이 반복마다 null을 반환할 수 있다고 명시되어 있지만 이는 끝을 의미하는 것이 아니며 반환된 반복의 값이 "0"일 때 완료됩니다.

따라서 위의 코드가 반복 실행될 때 키가 반환되지 않으면 $keys는 빈 배열이므로 while 루프가 자연스럽게 중단되어 출력이 없습니다.

이러한 상황은 Redis에 키가 많을 때 특히 두드러집니다. 키가 수십 또는 수백 개인 경우 이러한 상황은 거의 발생하지 않지만, 키가 수천만 개에 도달하면 이러한 상황이 거의 확실하게 발생합니다.

이런 상황의 발생을 줄이려면 스캔 기능의 세 번째 매개변수 개수를 더 큰 숫자로 설정할 수 있습니다. 그러나 이것이 이 문제에 대한 근본적인 해결책은 아닙니다. 두 가지 근본적인 해결책이 있습니다:

1.setOption

通过setOption函数来设定迭代时的行为。以下是示例代码:

$redis = new Redis();
$redis->connect('localhost', 6379);
$redis->setOption(Redis::OPT_SCAN,Redis::SCAN_RETRY);

$iterator = null;while ($keys = $redis->scan($iterator, 'test*')) {    foreach ($keys as $key) {        echo $key . PHP_EOL;
    }
}
로그인 후 복사

和上面的代码相比,只是多了个setOption的操作,这个操作的作用是啥呢?这个操作就是告诉redis扩展,当执行scan命令后,返回的结果集为空的话,函数不返回,而是直接继续执行scan命令,当然,这些步骤都是由扩展自动完成,当scan函数返回的时候,要么返回false,即迭代结束,未发现匹配模式pattern的key,要么就返回匹配的key,而不再会返回空数组了。

2.while(true)

上面那种方式是由php的扩展自动完成的,那么我们也可以换一种写法来达到相同的效果。

$redis = new Redis();
$redis->connect('localhost', 6379);

$iterator = null;while (true) {
    $keys = $redis->scan($iterator, 'test*');    if ($keys === false) {//迭代结束,未找到匹配pattern的key
        return;
    }    foreach ($keys as $key) {        echo $key . PHP_EOL;
    }
}
로그인 후 복사

               

위 내용은 PHP가 redis 스캔 명령을 사용할 때 발생하는 함정의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!