Redis SCAN

SCAN cursor [MATCH pattern] [COUNT count]

可用版本: >= 2.8.0

時(shí)間復(fù)雜度:增量式迭代命令每次執(zhí)行的復(fù)雜度為 O(1) 怯疤, 對(duì)數(shù)據(jù)集進(jìn)行一次完整迭代的復(fù)雜度為 O(N) 颓哮, 其中 N 為數(shù)據(jù)集中的元素?cái)?shù)量挪鹏。

SCAN 命令及其相關(guān)的 SSCAN 命令、 HSCAN 命令和 ZSCAN 命令都用于增量地迭代(incrementally iterate)一集元素(a collection of elements):

  • SCAN 命令用于迭代當(dāng)前數(shù)據(jù)庫(kù)中的數(shù)據(jù)庫(kù)鍵崎页。
  • SSCAN 命令用于迭代集合鍵中的元素。
  • HSCAN 命令用于迭代哈希鍵中的鍵值對(duì)穷躁。
  • ZSCAN 命令用于迭代有序集合中的元素(包括元素成員和元素分值)四瘫。

以上列出的四個(gè)命令都支持增量式迭代汉嗽, 它們每次執(zhí)行都只會(huì)返回少量元素, 所以這些命令可以用于生產(chǎn)環(huán)境找蜜, 而不會(huì)出現(xiàn)像 KEYS 命令饼暑、 SMEMBERS 命令帶來(lái)的問(wèn)題 —— 當(dāng) KEYS 命令被用于處理一個(gè)大的數(shù)據(jù)庫(kù)時(shí), 又或者 SMEMBERS 命令被用于處理一個(gè)大的集合鍵時(shí)锹杈, 它們可能會(huì)阻塞服務(wù)器達(dá)數(shù)秒之久撵孤。

不過(guò), 增量式迭代命令也不是沒(méi)有缺點(diǎn)的: 舉個(gè)例子竭望, 使用 SMEMBERS 命令可以返回集合鍵當(dāng)前包含的所有元素, 但是對(duì)于 SCAN 這類增量式迭代命令來(lái)說(shuō)裕菠, 因?yàn)樵趯?duì)鍵進(jìn)行增量式迭代的過(guò)程中咬清, 鍵可能會(huì)被修改, 所以增量式迭代命令只能對(duì)被返回的元素提供有限的保證 (offer limited guarantees about the returned elements)奴潘。

因?yàn)?SCAN 旧烧、 SSCANHSCANZSCAN 四個(gè)命令的工作方式都非常相似画髓, 所以這個(gè)文檔會(huì)一并介紹這四個(gè)命令掘剪, 但是要記住:

  • SSCAN 命令奈虾、 HSCAN 命令和 ZSCAN 命令的第一個(gè)參數(shù)總是一個(gè)數(shù)據(jù)庫(kù)鍵夺谁。
  • SCAN 命令則不需要在第一個(gè)參數(shù)提供任何數(shù)據(jù)庫(kù)鍵 —— 因?yàn)樗氖钱?dāng)前數(shù)據(jù)庫(kù)中的所有數(shù)據(jù)庫(kù)鍵。

SCAN 命令的基本用法

SCAN 命令是一個(gè)基于游標(biāo)的迭代器(cursor based iterator): SCAN 命令每次被調(diào)用之后肉微, 都會(huì)向用戶返回一個(gè)新的游標(biāo)匾鸥, 用戶在下次迭代時(shí)需要使用這個(gè)新游標(biāo)作為 SCAN 命令的游標(biāo)參數(shù), 以此來(lái)延續(xù)之前的迭代過(guò)程碉纳。

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

以下是一個(gè) SCAN 命令的迭代過(guò)程示例:

<pre style="box-sizing: border-box; font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", Courier, monospace; font-size: 12px; white-space: pre; margin: 0px; padding: 12px; display: block; overflow: auto; line-height: 1.4;">redis 127.0.0.1:6379> scan 0

  1. "17"
    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"
    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"
      </pre>

在上面這個(gè)例子中, 第一次迭代使用 0 作為游標(biāo)铁孵, 表示開始一次新的迭代锭硼。

第二次迭代使用的是第一次迭代時(shí)返回的游標(biāo), 也即是命令回復(fù)第一個(gè)元素的值 —— 17 库菲。

從上面的示例可以看到账忘, SCAN 命令的回復(fù)是一個(gè)包含兩個(gè)元素的數(shù)組, 第一個(gè)數(shù)組元素是用于進(jìn)行下一次迭代的新游標(biāo), 而第二個(gè)數(shù)組元素則是一個(gè)數(shù)組鳖擒, 這個(gè)數(shù)組中包含了所有被迭代的元素溉浙。

在第二次調(diào)用 SCAN 命令時(shí), 命令返回了游標(biāo) 0 蒋荚, 這表示迭代已經(jīng)結(jié)束戳稽, 整個(gè)數(shù)據(jù)集(collection)已經(jīng)被完整遍歷過(guò)了。

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

SCAN 命令的保證(guarantees)

SCAN 命令颂郎, 以及其他增量式迭代命令, 在進(jìn)行完整遍歷的情況下可以為用戶帶來(lái)以下保證: 從完整遍歷開始直到完整遍歷結(jié)束期間容为, 一直存在于數(shù)據(jù)集內(nèi)的所有元素都會(huì)被完整遍歷返回乓序; 這意味著, 如果有一個(gè)元素坎背, 它從遍歷開始直到遍歷結(jié)束期間都存在于被遍歷的數(shù)據(jù)集當(dāng)中替劈, 那么 SCAN 命令總會(huì)在某次迭代中將這個(gè)元素返回給用戶。

然而因?yàn)樵隽渴矫顑H僅使用游標(biāo)來(lái)記錄迭代狀態(tài)得滤, 所以這些命令帶有以下缺點(diǎn):

  • 同一個(gè)元素可能會(huì)被返回多次陨献。 處理重復(fù)元素的工作交由應(yīng)用程序負(fù)責(zé), 比如說(shuō)懂更, 可以考慮將迭代返回的元素僅僅用于可以安全地重復(fù)執(zhí)行多次的操作上眨业。
  • 如果一個(gè)元素是在迭代過(guò)程中被添加到數(shù)據(jù)集的, 又或者是在迭代過(guò)程中從數(shù)據(jù)集中被刪除的膜蛔, 那么這個(gè)元素可能會(huì)被返回坛猪, 也可能不會(huì), 這是未定義的(undefined)皂股。

SCAN 命令每次執(zhí)行返回的元素?cái)?shù)量

增量式迭代命令并不保證每次執(zhí)行都返回某個(gè)給定數(shù)量的元素墅茉。

增量式命令甚至可能會(huì)返回零個(gè)元素, 但只要命令返回的游標(biāo)不是 0 呜呐, 應(yīng)用程序就不應(yīng)該將迭代視作結(jié)束就斤。

不過(guò)命令返回的元素?cái)?shù)量總是符合一定規(guī)則的, 在實(shí)際中:

  • 對(duì)于一個(gè)大數(shù)據(jù)集來(lái)說(shuō)蘑辑, 增量式迭代命令每次最多可能會(huì)返回?cái)?shù)十個(gè)元素洋机;
  • 而對(duì)于一個(gè)足夠小的數(shù)據(jù)集來(lái)說(shuō), 如果這個(gè)數(shù)據(jù)集的底層表示為編碼數(shù)據(jù)結(jié)構(gòu)(encoded data structure洋魂,適用于是小集合鍵绷旗、小哈希鍵和小有序集合鍵)喜鼓, 那么增量迭代命令將在一次調(diào)用中返回?cái)?shù)據(jù)集中的所有元素。

最后衔肢, 用戶可以通過(guò)增量式迭代命令提供的 COUNT 選項(xiàng)來(lái)指定每次迭代返回元素的最大值庄岖。

COUNT 選項(xiàng)

雖然增量式迭代命令不保證每次迭代所返回的元素?cái)?shù)量, 但我們可以使用 COUNT 選項(xiàng)角骤, 對(duì)命令的行為進(jìn)行一定程度上的調(diào)整隅忿。

基本上, COUNT 選項(xiàng)的作用就是讓用戶告知迭代命令邦尊, 在每次迭代中應(yīng)該從數(shù)據(jù)集里返回多少元素背桐。

雖然 COUNT 選項(xiàng)只是對(duì)增量式迭代命令的一種提示(hint), 但是在大多數(shù)情況下蝉揍, 這種提示都是有效的链峭。

  • COUNT 參數(shù)的默認(rèn)值為 10
  • 在迭代一個(gè)足夠大的又沾、由哈希表實(shí)現(xiàn)的數(shù)據(jù)庫(kù)熏版、集合鍵、哈希鍵或者有序集合鍵時(shí)捍掺, 如果用戶沒(méi)有使用 MATCH 選項(xiàng), 那么命令返回的元素?cái)?shù)量通常和 COUNT 選項(xiàng)指定的一樣再膳, 或者比 COUNT 選項(xiàng)指定的數(shù)量稍多一些挺勿。
  • 在迭代一個(gè)編碼為整數(shù)集合(intset,一個(gè)只由整數(shù)值構(gòu)成的小集合)喂柒、 或者編碼為壓縮列表(ziplist不瓶,由不同值構(gòu)成的一個(gè)小哈希或者一個(gè)小有序集合)時(shí)灾杰, 增量式迭代命令通常會(huì)無(wú)視 COUNT 選項(xiàng)指定的值蚊丐, 在第一次迭代就將數(shù)據(jù)集包含的所有元素都返回給用戶。

Note

并非每次迭代都要使用相同的 COUNT 值艳吠。

用戶可以在每次迭代中按自己的需要隨意改變 COUNT 值麦备, 只要記得將上次迭代返回的游標(biāo)用到下次迭代里面就可以了。

MATCH 選項(xiàng)

KEYS 命令一樣昭娩, 增量式迭代命令也可以通過(guò)提供一個(gè) glob 風(fēng)格的模式參數(shù)凛篙, 讓命令只返回和給定模式相匹配的元素, 這一點(diǎn)可以通過(guò)在執(zhí)行增量式迭代命令時(shí)栏渺, 通過(guò)給定 MATCH <pattern> 參數(shù)來(lái)實(shí)現(xiàn)呛梆。

以下是一個(gè)使用 MATCH 選項(xiàng)進(jìn)行迭代的示例:

<pre style="box-sizing: border-box; font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", Courier, monospace; font-size: 12px; white-space: pre; margin: 0px; padding: 12px; display: block; overflow: auto; line-height: 1.4;">redis 127.0.0.1:6379> sadd myset 1 2 3 foo foobar feelsgood
(integer) 6

redis 127.0.0.1:6379> sscan myset 0 match f*

  1. "0"
    1. "foo"
    2. "feelsgood"
    3. "foobar"
      </pre>

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

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

<pre style="box-sizing: border-box; font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", Courier, monospace; font-size: 12px; white-space: pre; margin: 0px; padding: 12px; display: block; overflow: auto; line-height: 1.4;">redis 127.0.0.1:6379> scan 0 MATCH 11

  1. "288"
    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"
    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"
  2. "key:211"
  3. "key:411"
  4. "key:115"
  5. "key:116"
  6. "key:114"
  7. "key:119"
  8. "key:811"
  9. "key:511"
  10. "key:11"
    </pre>

如你所見滞磺, 以上的大部分迭代都不返回任何元素升薯。

在最后一次迭代, 我們通過(guò)將 COUNT 選項(xiàng)的參數(shù)設(shè)置為 1000 雁刷, 強(qiáng)制命令為本次迭代掃描更多元素覆劈, 從而使得命令返回的元素也變多了。

并發(fā)執(zhí)行多個(gè)迭代

在同一時(shí)間沛励, 可以有任意多個(gè)客戶端對(duì)同一數(shù)據(jù)集進(jìn)行迭代责语, 客戶端每次執(zhí)行迭代都需要傳入一個(gè)游標(biāo), 并在迭代執(zhí)行之后獲得一個(gè)新的游標(biāo)目派, 而這個(gè)游標(biāo)就包含了迭代的所有狀態(tài)坤候, 因此, 服務(wù)器無(wú)須為迭代記錄任何狀態(tài)企蹭。

中途停止迭代

因?yàn)榈乃袪顟B(tài)都保存在游標(biāo)里面白筹, 而服務(wù)器無(wú)須為迭代保存任何狀態(tài), 所以客戶端可以在中途停止一個(gè)迭代谅摄, 而無(wú)須對(duì)服務(wù)器進(jìn)行任何通知徒河。

即使有任意數(shù)量的迭代在中途停止, 也不會(huì)產(chǎn)生任何問(wèn)題送漠。

使用錯(cuò)誤的游標(biāo)進(jìn)行增量式迭代

使用間斷的(broken)顽照、負(fù)數(shù)、超出范圍或者其他非正常的游標(biāo)來(lái)執(zhí)行增量式迭代并不會(huì)造成服務(wù)器崩潰闽寡, 但可能會(huì)讓命令產(chǎn)生未定義的行為代兵。

未定義行為指的是, 增量式命令對(duì)返回值所做的保證可能會(huì)不再為真爷狈。

只有兩種游標(biāo)是合法的:

  1. 在開始一個(gè)新的迭代時(shí)植影, 游標(biāo)必須為 0
  2. 增量式迭代命令在執(zhí)行之后返回的涎永, 用于延續(xù)(continue)迭代過(guò)程的游標(biāo)思币。

迭代終結(jié)的保證

增量式迭代命令所使用的算法只保證在數(shù)據(jù)集的大小有界(bounded)的情況下, 迭代才會(huì)停止土辩, 換句話說(shuō)支救, 如果被迭代數(shù)據(jù)集的大小不斷地增長(zhǎng)的話, 增量式迭代命令可能永遠(yuǎn)也無(wú)法完成一次完整迭代拷淘。

從直覺(jué)上可以看出各墨, 當(dāng)一個(gè)數(shù)據(jù)集不斷地變大時(shí), 想要訪問(wèn)這個(gè)數(shù)據(jù)集中的所有元素就需要做越來(lái)越多的工作启涯, 能否結(jié)束一個(gè)迭代取決于用戶執(zhí)行迭代的速度是否比數(shù)據(jù)集增長(zhǎng)的速度更快贬堵。

返回值

SCAN 命令恃轩、 SSCAN 命令、 HSCAN 命令和 ZSCAN 命令都返回一個(gè)包含兩個(gè)元素的 multi-bulk 回復(fù): 回復(fù)的第一個(gè)元素是字符串表示的無(wú)符號(hào) 64 位整數(shù)(游標(biāo))黎做, 回復(fù)的第二個(gè)元素是另一個(gè) multi-bulk 回復(fù)叉跛, 這個(gè) multi-bulk 回復(fù)包含了本次被迭代的元素。

SCAN 命令返回的每個(gè)元素都是一個(gè)數(shù)據(jù)庫(kù)鍵蒸殿。

SSCAN 命令返回的每個(gè)元素都是一個(gè)集合成員筷厘。

HSCAN 命令返回的每個(gè)元素都是一個(gè)鍵值對(duì),一個(gè)鍵值對(duì)由一個(gè)鍵和一個(gè)值組成宏所。

ZSCAN 命令返回的每個(gè)元素都是一個(gè)有序集合元素酥艳,一個(gè)有序集合元素由一個(gè)成員(member)和一個(gè)分值(score)組成。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末爬骤,一起剝皮案震驚了整個(gè)濱河市充石,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌霞玄,老刑警劉巖骤铃,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異坷剧,居然都是意外死亡惰爬,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門惫企,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)补鼻,“玉大人,你說(shuō)我怎么就攤上這事雅任。” “怎么了咨跌?”我有些...
    開封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵沪么,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我锌半,道長(zhǎng)禽车,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任刊殉,我火速辦了婚禮殉摔,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘记焊。我一直安慰自己逸月,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開白布遍膜。 她就那樣靜靜地躺著碗硬,像睡著了一般瓤湘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上恩尾,一...
    開封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天弛说,我揣著相機(jī)與錄音,去河邊找鬼翰意。 笑死木人,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的冀偶。 我是一名探鬼主播醒第,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蔫磨!你這毒婦竟也來(lái)了淘讥?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤堤如,失蹤者是張志新(化名)和其女友劉穎蒲列,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體搀罢,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蝗岖,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了榔至。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片抵赢。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖唧取,靈堂內(nèi)的尸體忽然破棺而出铅鲤,到底是詐尸還是另有隱情,我是刑警寧澤枫弟,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布邢享,位于F島的核電站,受9級(jí)特大地震影響淡诗,放射性物質(zhì)發(fā)生泄漏骇塘。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一韩容、第九天 我趴在偏房一處隱蔽的房頂上張望款违。 院中可真熱鬧,春花似錦群凶、人聲如沸插爹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)递惋。三九已至柔滔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間萍虽,已是汗流浹背睛廊。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留杉编,地道東北人超全。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像邓馒,于是被迫代替她去往敵國(guó)和親嘶朱。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • SCAN 命令及其相關(guān)的 SSCAN 命令光酣、 HSCAN 命令和 ZSCAN 命令都用于增量地迭代(increme...
    厭惡狡詐心機(jī)閱讀 1,258評(píng)論 0 0
  • SCAN命令是一個(gè)基于游標(biāo)的迭代器疏遏。這意味著命令每次被調(diào)用都需要使用上一次這個(gè)調(diào)用返回的游標(biāo)作為該次調(diào)用的游標(biāo)參數(shù)...
    yjwlyy閱讀 4,625評(píng)論 0 4
  • KEYS pattern 查找所有符合給定模式pattern的key。 keys * 匹配數(shù)據(jù)庫(kù)中所有的key...
    程序員牛牛閱讀 1,094評(píng)論 0 3
  • redis-scan命令 介紹&場(chǎng)景 redis中找到以某某開頭的key對(duì)這些key進(jìn)行操作救军。 問(wèn)題 使用keys...
    zhangsanzhu閱讀 835評(píng)論 0 2
  • 內(nèi)徑養(yǎng)生課筆記內(nèi)經(jīng)養(yǎng)生第二課主題:這個(gè)陰陽(yáng)平衡的世界筆記要點(diǎn)一:中醫(yī)是在天上看人體的觀念财异,看得全面,卻因?yàn)樘暧^唱遭,...
    伏羲媽媽舒青蓮閱讀 557評(píng)論 0 0