Redis 中使用 scan 替換 keys

13sai發表於2020-01-26

我們都知道查詢Redis的鍵時,可以使用keys pattern,但當key太多時,keys命令的效率就很低,如果線上上直接使用,甚至可能發生生產事故,這時候,我們不妨使用scan命令。

SCAN 命令是一個基於遊標的迭代器(cursor based iterator): SCAN 命令每次被呼叫之後, 都會向使用者返回一個新的遊標, 使用者在下次迭代時需要使用這個新遊標作為 SCAN 命令的遊標引數, 以此來延續之前的迭代過程。當 SCAN 命令的遊標引數被設定為 0 時, 伺服器將開始一次新的迭代, 而當伺服器向使用者返回值為 0 的遊標時, 表示迭代已結束。

生成key

<?php
// 生成1000個
$redis = new \Redis();
$redis->connect('127.0.0.1', 6379, 10);
$redis->select(2);

$arr = [
    'rwer',
    '24erw',
    'rterq4',
    'sdgfd5',
    'dgsdg',
    'sfst',
];

for ($i=0; $i<1000; $i++) {
    $redis->set(md5($i.$arr[$i%6]), md5($arr[$i%6].'sdfsd'));
}
echo "OK".PHP_EOL;

keys檢視個數

keys c*

Redis中使用scan替換keys

scan遍歷

<?php
$redis = new \Redis();
$redis->connect('127.0.0.1', 6379, 10);
$redis->select(2);
$iterator = null;
// 遍歷字首
$pattern = 'c*';
$count = 100;
// 務必設定,如果沒掃描到,繼續掃描,而不是返回空,否則while直接退出,遍歷就會不準確
$redis->setOption(\Redis::OPT_SCAN, \Redis::SCAN_RETRY);

$total = [];
$i = 0;

// $count可以不設定,非必需引數
while($arr = $redis->scan($iterator, $pattern, $count)) {
    $arrVal = $redis->mget($arr);
    $ret = array_combine($arr, $arrVal);
    $total = array_merge($total, $ret);
    $i++;
}

// var_dump($total);

var_dump($i);
echo count($total).PHP_EOL;

Redis中使用scan替換keys

當然你也可以不使用\Redis::OPT_SCAN, \Redis::SCAN_RETRY這兩個引數,自行迴圈,判斷返回值是不是false,也能遍歷成功。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

分享開發知識,歡迎交流。qq957042781

相關文章