?
本文檔使用 php中文網(wǎng)手冊 發(fā)布
SCAN cursor [MATCH pattern] [COUNT count]
自2.8.0起可用。
時間復雜度: O(1)用于每個呼叫。O(N)進行完整的迭代,包括足夠的命令調(diào)用以使游標返回0. N是集合中元素的數(shù)量。
使用 SCAN 命令和密切相關(guān)的命令 SSCAN,HSCAN 和 ZSCAN 來遞增地遍歷一組元素。
SCAN 迭代當前選定的 Redis 數(shù)據(jù)庫中的一組鍵。
SSCAN 迭代 Sets 類型的元素。
HSCAN 迭代哈希類型的字段及其關(guān)聯(lián)值。
ZSCAN 迭代 Sorted Set 類型的元素及其相關(guān)分數(shù)。
由于這些命令允許增量迭代,每次調(diào)用只返回少量元素,因此可以在生產(chǎn)中使用它們,而無需像 KEYS 或 SMEMBERS 這樣的命令可能會在被調(diào)用時長時間(甚至幾秒)阻塞服務(wù)器的缺點鍵或元素的大集合。
然而,盡管像 SMEMBERS 這樣的阻塞命令能夠在給定時刻提供集合中的所有元素,但 SCAN 系列命令僅對返回的元素提供有限的保證,因為我們遞增迭代的集合可能在迭代過程中發(fā)生更改。
請注意,SCAN,SSCAN,HSCAN 和 ZSCAN 的工作方式非常相似,因此本文檔涵蓋了所有四個命令。然而,一個明顯的區(qū)別是,對于SSCAN,HSCAN 和 ZSCAN,第一個參數(shù)是保存 Set,Hash 或 Sorted Set 值的密鑰的名稱。SCAN 命令不需要任何鍵名參數(shù),因為它在當前數(shù)據(jù)庫中迭代鍵,所以迭代對象就是數(shù)據(jù)庫本身。
SCAN 是一個基于游標的迭代器。這意味著在每次調(diào)用該命令時,服務(wù)器都會返回一個更新的游標,用戶需要在下一次調(diào)用中將其用作游標參數(shù)。
當光標設(shè)置為0時開始迭代,當服務(wù)器返回的光標為0時終止迭代。以下是 SCAN 迭代的示例:
redis 127.0.0.1:6379> scan 01) "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 171) "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"
在上面的例子中,第一個調(diào)用使用零作為游標,以開始迭代。第二次調(diào)用使用前一次調(diào)用返回的游標作為回復的第一個元素,即17。
正如你所看到的,SCAN返回值 是一個包含兩個值的數(shù)組:第一個值是下一次調(diào)用中使用的新游標,第二個值是元素數(shù)組。
由于在第二次調(diào)用中返回的游標是0,所以服務(wù)器向調(diào)用者發(fā)信號通知完成迭代,并且集合被完全探索。使用游標值0開始迭代,并調(diào)用 SCAN,直到返回的游標再次為0,稱為完整迭代。
SCAN 命令和 SCAN 系列中的其他命令能夠向用戶提供與完整迭代關(guān)聯(lián)的一組保證。
完整迭代總是從完整迭代的開始到結(jié)束檢索集合中存在的所有元素。這意味著如果迭代開始時給定元素位于集合內(nèi)部,并且在迭代終止時仍然存在,那么在某個點 SCAN 將其返回給用戶。
完整迭代從不會返回集合中不存在的任何元素,從完整迭代的開始到結(jié)束。因此,如果一個元素在迭代開始之前被移除,并且在迭代過程中永遠不會將其添加回集合中,SCAN可以確保這個元素永遠不會被返回。
但是由于 SCAN 只有很少的狀態(tài)相關(guān)(只是光標),它有以下缺點:
給定的元素可能會多次返回。應(yīng)用程序可以處理重復元素的情況,例如僅使用返回的元素來執(zhí)行多次重新應(yīng)用時安全的操作。
在整個迭代過程中并不總是出現(xiàn)在集合中的元素可能被返回或不被返回:它是未定義的。
SCAN 家族功能不保證每次通話返回的元素數(shù)量都在給定的范圍內(nèi)。這些命令還允許返回零個元素,并且只要返回的游標不為零,客戶端就不應(yīng)該考慮迭代完成。
然而,返回的元素的數(shù)量是合理的,也就是說,實際上,SCAN 可能會在迭代大集合時返回數(shù)十個元素的最大數(shù)量的元素,或者可能會將集合中的所有元素一次返回當?shù)献銐蛐∫员阍趦?nèi)部表示為編碼數(shù)據(jù)結(jié)構(gòu)(這發(fā)生在小集合,散列和有序集合)時調(diào)用。
但是,用戶可以使用 COUNT 選項調(diào)整每次呼叫返回元素數(shù)量級的順序。
雖然 SCAN 不提供有關(guān)每次迭代返回的元素數(shù)量的保證,但可以使用 COUNT 選項憑經(jīng)驗調(diào)整 SCAN 的行為?;旧嫌? COUNT,用戶指定了每次調(diào)用應(yīng)該完成的工作量,以便從集合中檢索元素。這只是實現(xiàn)的一個暗示,但是一般來說,這是您實施過程中大部分時間所期望的。
COUNT 的默認值是10。
當?shù)荑€空間,或者一個足夠大的集合,哈?;蚺判蚣?,以便用哈希表表示時(假設(shè)沒有使用 MATCH 選項),服務(wù)器通常會返回計數(shù)或比每次調(diào)用的計數(shù)元素多一點。
迭代編碼為 intsets 的集合(由整數(shù)組成的小集合)或編碼為 ziplists 的哈希和排序集(小哈希和由小個別值組成的集合)時,通常所有元素都在第一個 SCAN 調(diào)用中返回,而不管 COUNT 值。
重要提示:每次迭代都不需要使用相同的 COUNT 值。調(diào)用者可以根據(jù)需要自由地將計數(shù)從一次迭代更改為另一次迭代,只要在下次調(diào)用中傳遞的游標是在先前對該命令的調(diào)用中獲得的游標。
只能迭代匹配給定全局樣式模式的元素,類似于只將模式作為參數(shù)的 KEYS 命令的行為。
為此,只需MATCH <pattern>
在 SCAN 命令末尾附加參數(shù)(它可與所有 SCAN 系列命令一起使用)。
這是一個使用 MATCH 進行迭代的例子:
redis 127.0.0.1:6379> sadd myset 1 2 3 foo foobar feelsgood(integer) 6redis 127.0.0.1:6379> sscan myset 0 match f*1) "0"2) 1) "foo" 2) "feelsgood" 3) "foobar"redis 127.0.0.1:6379>
重要的是要注意,在將數(shù)據(jù)返回給客戶端之前,在從集合中檢索元素之后應(yīng)用 MATCH 過濾器。這意味著如果模式匹配集合中很少的元素,SCAN 很可能在大多數(shù)迭代中都不返回元素。一個例子如下所示:
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 10001) "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>
正如您所看到的,大部分調(diào)用都返回了零個元素,但是最后一次調(diào)用的 COUNT 為1000,以強制命令為該迭代執(zhí)行更多掃描。
無限數(shù)量的客戶端可能會同時迭代同一個集合,因為迭代器的完整狀態(tài)在游標中,每次調(diào)用都會獲取并返回給客戶端。服務(wù)器端根本沒有狀態(tài)。
由于沒有狀態(tài)服務(wù)器端,但全狀態(tài)由光標捕獲,因此調(diào)用者可以自由地在半途中終止一次迭代,而無需以任何方式將此信號通知給服務(wù)器。無限次的迭代可以開始,并且不會在沒有任何問題的情況下終止。
調(diào)用帶有破損,負值,超范圍或其他無效光標的 SCAN 將導致未定義的行為,但不會導致崩潰。未定義的是,對于返回元素的保證不能再由 SCAN 實現(xiàn)來保證。
唯一有效的游標是:
開始迭代時光標值為0。
前一次調(diào)用 SCAN 返回的光標為了繼續(xù)迭代。
SCAN 算法只有在迭代集合的大小保持限定為給定的最大大小時才被保證終止,否則迭代總是增長的集合可能導致 SCAN 永遠不會終止完整迭代。
這很容易直觀地看到:如果集合增長,為了訪問所有可能的元素需要做更多的工作,并且終止迭代的能力取決于 SCAN 調(diào)用的次數(shù)和它的 COUNT 選項值,與收藏增長的速度。
SCAN,SSCAN,HSCAN 和 ZSCAN 返回一個雙元素多批量回復,其中第一個元素是一個表示無符號64位數(shù)字(游標)的字符串,第二個元素是具有元素數(shù)組的多個批量。
SCAN 數(shù)組元素是一個鍵列表。
SSCAN 元素數(shù)組是 Set 成員的列表。
對于 Hash 的每個返回元素,HSCAN 元素數(shù)組包含兩個元素,一個字段和一個值。
對于有序集合的每個返回元素,ZSCAN 元素數(shù)組包含兩個元素,一個成員及其相關(guān)分數(shù)。
迭代一個哈希值。
redis 127.0.0.1:6379> hmset hash name Jack age 33 OK redis 127.0.0.1:6379> hscan hash 0 1) "0" 2) 1) "name" 2) "Jack" 3) "age" 4) "33"