溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何在Redis中遍歷所有key

發(fā)布時(shí)間:2021-04-12 15:25:05 來源:億速云 閱讀:217 作者:Leah 欄目:開發(fā)技術(shù)

本篇文章給大家分享的是有關(guān)如何在Redis中遍歷所有key,小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

當(dāng)我們需要遍歷Redis所有key或者指定模式的key時(shí),首先想到的是KEYS命令:

KEYS pattern

官網(wǎng)對(duì)于KEYS命令有一個(gè)提示:  KEYS 的速度非???,例如,Redis在一個(gè)有1百萬個(gè)key的數(shù)據(jù)庫里面執(zhí)行一次查詢需要的時(shí)間是40毫秒 。但在一個(gè)大的數(shù)據(jù)庫中使用它仍然可能造成性能問題,如果你需要從一個(gè)數(shù)據(jù)集中查找特定的  KEYS , 你最好還是用 Redis 的集合結(jié)構(gòu)  SETS  來代替。
KEYS命令使用很簡(jiǎn)單。

redis> MSET one 1 two 2 three 3 four 4
OK
redis> KEYS *o*
1) "four"
2) "one"
3) "two"
redis> KEYS t??
1) "two"
redis> KEYS *
1) "four"
2) "three"
3) "one"
4) "two"
redis>

但由于KEYS命令一次性返回所有匹配的key,所以,當(dāng)redis中的key非常多時(shí),對(duì)于內(nèi)存的消耗和redis服務(wù)器都是一個(gè)隱患,
對(duì)于Redis 2.8以上版本給我們提供了一個(gè)更好的遍歷key的命令 SCAN 該命令的基本格式:

SCAN cursor [MATCH pattern] [COUNT count]

SCAN  每次執(zhí)行都只會(huì)返回少量元素,所以可以用于生產(chǎn)環(huán)境,而不會(huì)出現(xiàn)像 KEYS 或者 SMEMBERS 命令帶來的可能會(huì)阻塞服務(wù)器的問題。

SCAN命令是一個(gè)基于游標(biāo)的迭代器。這意味著命令每次被調(diào)用都需要使用上一次這個(gè)調(diào)用返回的游標(biāo)作為該次調(diào)用的游標(biāo)參數(shù),以此來延續(xù)之前的迭代過程

當(dāng)SCAN命令的游標(biāo)參數(shù)(即cursor)被設(shè)置為 0 時(shí), 服務(wù)器將開始一次新的迭代, 而當(dāng)服務(wù)器向用戶返回值為 0 的游標(biāo)時(shí), 表示迭代已結(jié)束。

簡(jiǎn)單的迭代演示:

redis 127.0.0.1:6379> scan 0
1) "17"
2)  1) "key:12"
    2) "key:8"
    3) "key:4"
    4) "key:14"
    5) "key:16"
    6) "key:17"
    7) "key:15"
    8) "key:10"
    9) "key:3"
   10) "key:7"
   11) "key:1"
redis 127.0.0.1:6379> scan 17
1) "0"
2) 1) "key:5"
   2) "key:18"
   3) "key:0"
   4) "key:2"
   5) "key:19"
   6) "key:13"
   7) "key:6"
   8) "key:9"
   9) "key:11"

在上面這個(gè)例子中, 第一次迭代使用 0 作為游標(biāo), 表示開始一次新的迭代。第二次迭代使用的是第一次迭代時(shí)返回的游標(biāo) 17 ,作為新的迭代參數(shù) 。

顯而易見,SCAN命令的返回值 是一個(gè)包含兩個(gè)元素的數(shù)組, 第一個(gè)數(shù)組元素是用于進(jìn)行下一次迭代的新游標(biāo), 而第二個(gè)數(shù)組元素則又是一個(gè)數(shù)組, 這個(gè)數(shù)組中包含了所有被迭代的元素。

注意:返回的游標(biāo)不一定是遞增的,可能后一次返回的游標(biāo)比前一次的小。
在第二次調(diào)用 SCAN 命令時(shí), 命令返回了游標(biāo) 0 , 這表示迭代已經(jīng)結(jié)束, 整個(gè)數(shù)據(jù)集已經(jīng)被完整遍歷過了。

full iteration :以 0 作為游標(biāo)開始一次新的迭代, 一直調(diào)用 SCAN 命令, 直到命令返回游標(biāo) 0 , 我們稱這個(gè)過程為一次完整遍歷。

SCAN增量式迭代命令并不保證每次執(zhí)行都返回某個(gè)給定數(shù)量的元素,甚至可能會(huì)返回零個(gè)元素, 但只要命令返回的游標(biāo)不是 0 , 應(yīng)用程序就不應(yīng)該將迭代視作結(jié)束。

不過命令返回的元素?cái)?shù)量總是符合一定規(guī)則的, 對(duì)于一個(gè)大數(shù)據(jù)集來說, 增量式迭代命令每次最多可能會(huì)返回?cái)?shù)十個(gè)元素;而對(duì)于一個(gè)足夠小的數(shù)據(jù)集來說,可能會(huì)一次迭代返回所有的key

COUNT選項(xiàng)

對(duì)于增量式迭代命令不保證每次迭代所返回的元素?cái)?shù)量,我們可以使用COUNT選項(xiàng), 對(duì)命令的行為進(jìn)行一定程度上的調(diào)整。COUNT 選項(xiàng)的作用就是讓用戶告知迭代命令, 在每次迭代中應(yīng)該從數(shù)據(jù)集里返回多少元素。使用COUNT 選項(xiàng)對(duì)于對(duì)增量式迭代命令相當(dāng)于一種提示, 大多數(shù)情況下這種提示都比較有效的控制了返回值的數(shù)量。

注意:COUNT選項(xiàng)并不能嚴(yán)格控制返回的key數(shù)量,只能說是一個(gè)大致的約束。并非每次迭代都要使用相同的 COUNT 值,用戶可以在每次迭代中按自己的需要隨意改變 COUNT 值, 只要記得將上次迭代返回的游標(biāo)用到下次迭代里面就可以了。

MATCH 選項(xiàng)

類似于KEYS 命令,增量式迭代命令通過給定 MATCH 參數(shù)的方式實(shí)現(xiàn)了通過提供一個(gè) glob 風(fēng)格的模式參數(shù), 讓命令只返回和給定模式相匹配的元素。

MATCH 選項(xiàng)對(duì)元素的模式匹配工作是在命令從數(shù)據(jù)集中取出元素后和向客戶端返回元素前的這段時(shí)間內(nèi)進(jìn)行的, 所以如果被迭代的數(shù)據(jù)集中只有少量元素和模式相匹配, 那么迭代命令或許會(huì)在多次執(zhí)行中都不返回任何元素。

以下是這種情況的一個(gè)例子:

redis 127.0.0.1:6379> scan 0 MATCH *11*
1) "288"
2) 1) "key:911"
redis 127.0.0.1:6379> scan 288 MATCH *11*
1) "224"
2) (empty list or set)
redis 127.0.0.1:6379> scan 224 MATCH *11*
1) "80"
2) (empty list or set)
redis 127.0.0.1:6379> scan 80 MATCH *11*
1) "176"
2) (empty list or set)
redis 127.0.0.1:6379> scan 176 MATCH *11* COUNT 1000
1) "0"
2)  1) "key:611"
    2) "key:711"
    3) "key:118"
    4) "key:117"
    5) "key:311"
    6) "key:112"
    7) "key:111"
    8) "key:110"
    9) "key:113"
   10) "key:211"
   11) "key:411"
   12) "key:115"
   13) "key:116"
   14) "key:114"
   15) "key:119"
   16) "key:811"
   17) "key:511"
   18) "key:11"
redis 127.0.0.1:6379>

可以看出,以上的大部分迭代都不返回任何元素。在最后一次迭代, 我們通過將 COUNT 選項(xiàng)的參數(shù)設(shè)置為 1000 , 強(qiáng)制命令為本次迭代掃描更多元素, 從而使得命令返回的元素也變多了。

基于SCAN的這種安全性,建議大家在生產(chǎn)環(huán)境都使用SCAN命令來代替KEYS,不過注意,該命令是在2.8.0版本之后加入的,如果你的Redis低于這個(gè)版本,則需要升級(jí)Redis。

下面用PHP代碼演示SCAN命令的使用:

<?php
 
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
/* 設(shè)置遍歷的特性為不重復(fù)查找,該情況下擴(kuò)展只會(huì)scan一次,所以可能會(huì)返回空集合 */
$redis->setOption(Redis::OPT_SCAN, Redis::SCAN_NORETRY);
$it = NULL;
$pattern = '*';
$count = 50;  // 每次遍歷50條,注意是遍歷50條,遍歷出來的50條key還要去匹配你的模式,所以并不等于就能夠取出50條key
do
{
    $keysArr = $redis->scan($it, $pattern, $count);
    if ($keysArr)
    {
        foreach ($keysArr as $key)
        {
            echo $key . "\n";
        }
    }
} while ($it > 0);   //每次調(diào)用 Scan會(huì)自動(dòng)改變 $it 值,當(dāng)$it = 0時(shí) 這次遍歷結(jié)束 退出循環(huán)
echo '---------------------------------------------------------------------------------' . "\n";
/* 設(shè)置擴(kuò)展在一次scan沒有查找出記錄時(shí) 進(jìn)行重復(fù)的scan 直到查詢出結(jié)果或者遍歷結(jié)束為止 */
$redis->setOption(Redis::OPT_SCAN, Redis::SCAN_RETRY);
//這種用法下我們只需要簡(jiǎn)單判斷返回結(jié)果是否為空即可, 如果為空說明遍歷結(jié)束
while ($keysArr = $redis->scan($it, $pattern, $count))
    foreach ($keysArr as $key)
        echo $key . "\n";
}

執(zhí)行結(jié)果:

[root@localhost php]# /usr/local/php/bin/php scan.php
bm
bm2
h2
name
bit
bm1
places
cities
hhl
---------------------------------------------------------------------------------
bm
bm2
h2
name
bit
bm1
places
cities
hhl

以上就是如何在Redis中遍歷所有key,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見到或用到的。希望你能通過這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI