天天看點

SCAN cursor [MATCH pattern] [COUNT count]

指令及其相關的 SSCAN, HSCAN 和 ZSCAN 指令都用于增量疊代一個集合元素。

SCAN 指令用于疊代目前資料庫中的key集合。

SSCAN 指令用于疊代SET集合中的元素。

HSCAN 指令用于疊代Hash類型中的鍵值對。

ZSCAN 指令用于疊代SortSet集合中的元素和元素對應的分值

以上列出的四個指令都支援增量式疊代,它們每次執行都隻會傳回少量元素,是以這些指令可以用于生産環境,而不會出現像 KEYS 或者 SMEMBERS 指令帶來的可能會阻塞伺服器的問題。

不過,SMEMBERS 指令可以傳回集合鍵目前包含的所有元素, 但是對于SCAN這類增量式疊代指令來說,有可能在增量疊代過程中,集合元素被修改,對傳回值無法提供完全準确的保證。

因為 SCAN, SSCAN, HSCAN 和 ZSCAN 四個指令的工作方式都非常相似, 是以這個文檔會一并介紹這四個指令,需要注意的是SSCAN, HSCAN ,ZSCAN指令的第一個參數總是一個key; SCAN 指令則不需要在第一個參數提供任何key,因為它疊代的是目前資料庫中的所有key。

SCAN指令是一個基于遊标的疊代器。這意味着指令每次被調用都需要使用上一次這個調用傳回的遊标作為該次調用的遊标參數,以此來延續之前的疊代過程

當SCAN指令的遊标參數被設定為 0 時, 伺服器将開始一次新的疊代, 而當伺服器向使用者傳回值為 0 的遊标時, 表示疊代已結束。

以下是一個 SCAN 指令的疊代過程示例 :

在上面這個例子中, 第一次疊代使用 0 作為遊标, 表示開始一次新的疊代。第二次疊代使用的是第一次疊代時傳回的遊标 17 ,作為新的疊代參數 。

顯而易見,SCAN指令的傳回值 是一個包含兩個元素的數組, 第一個數組元素是用于進行下一次疊代的新遊标, 而第二個數組元素則是一個數組, 這個數組中包含了所有被疊代的元素。

在第二次調用 SCAN 指令時, 指令傳回了遊标 0 , 這表示疊代已經結束, 整個資料集已經被完整周遊過了。

full iteration :以 0 作為遊标開始一次新的疊代, 一直調用 SCAN 指令, 直到指令傳回遊标 0 , 我們稱這個過程為一次完整周遊。

SCAN指令以及其他增量式疊代指令, 在進行完整周遊的情況下可以為使用者帶來以下保證 :

從完整周遊開始直到完整周遊結束期間, 一直存在于資料集内的所有元素都會被完整周遊傳回; 這意味着, 如果有一個元素, 它從周遊開始直到周遊結束期間都存在于被周遊的資料集當中, 那麼 SCAN 指令總會在某次疊代中将這個元素傳回給使用者。

同樣,如果一個元素在開始周遊之前被移出集合,并且在周遊開始直到周遊結束期間都沒有再加入,那麼在周遊傳回的元素集中就不會出現該元素。

然而因為增量式指令僅僅使用遊标來記錄疊代狀态, 是以這些指令帶有以下缺點:

同一個元素可能會被傳回多次。 處理重複元素的工作交由應用程式負責, 比如說, 可以考慮将疊代傳回的元素僅僅用于可以安全地重複執行多次的操作上。

如果一個元素是在疊代過程中被添加到資料集的, 又或者是在疊代過程中從資料集中被删除的, 那麼這個元素可能會被傳回, 也可能不會。

SCAN增量式疊代指令并不保證每次執行都傳回某個給定數量的元素,甚至可能會傳回零個元素, 但隻要指令傳回的遊标不是 0 , 應用程式就不應該将疊代視作結束。

不過指令傳回的元素數量總是符合一定規則的, 對于一個大資料集來說, 增量式疊代指令每次最多可能會傳回數十個元素;而對于一個足夠小的資料集來說, 如果這個資料集的底層表示為編碼資料結構(小的sets, hashes and sorted sets), 那麼增量疊代指令将在一次調用中傳回資料集中的所有元素。

如果需要的話,使用者可以通過增量式疊代指令提供的COUNT選項來指定每次疊代傳回元素的最大值。

對于增量式疊代指令不保證每次疊代所傳回的元素數量,我們可以使用COUNT選項, 對指令的行為進行一定程度上的調整。COUNT 選項的作用就是讓使用者告知疊代指令, 在每次疊代中應該從資料集裡傳回多少元素。使用COUNT 選項對于對增量式疊代指令相當于一種提示, 大多數情況下這種提示都比較有效的控制了傳回值的數量。

COUNT 參數的預設值為 10 。

資料集比較大時,如果沒有使用MATCH 選項, 那麼指令傳回的元素數量通常和 COUNT 選項指定的一樣, 或者比 COUNT 選項指定的數量稍多一些。

在疊代一個編碼為整數集合(intset,一個隻由整數值構成的小集合)、 或者編碼為壓縮清單(ziplist,由不同值構成的一個小哈希或者一個小有序集合)時, 增量式疊代指令通常會無視 COUNT 選項指定的值, 在第一次疊代就将資料集包含的所有元素都傳回給使用者。

注意: **并非每次疊代都要使用相同的 COUNT 值 **,使用者可以在每次疊代中按自己的需要随意改變 COUNT 值, 隻要記得将上次疊代傳回的遊标用到下次疊代裡面就可以了。

類似于KEYS 指令,增量式疊代指令通過給定 MATCH 參數的方式實作了通過提供一個 glob 風格的模式參數, 讓指令隻傳回和給定模式相比對的元素。

以下是一個使用 MATCH 選項進行疊代的示例:

MATCH功能對元素的模式比對工作是在指令從資料集中取出元素後和向用戶端傳回元素前的這段時間内進行的, 是以如果被疊代的資料集中隻有少量元素和模式相比對, 那麼疊代指令或許會在多次執行中都不傳回任何元素。

以下是這種情況的一個例子:

可以看出,以上的大部分疊代都不傳回任何元素。在最後一次疊代, 我們通過将 COUNT 選項的參數設定為 1000 , 強制指令為本次疊代掃描更多元素, 進而使得指令傳回的元素也變多了。

在同一時間, 可以有任意多個用戶端對同一資料集進行疊代, 用戶端每次執行疊代都需要傳入一個遊标, 并在疊代執行之後獲得一個新的遊标, 而這個遊标就包含了疊代的所有狀态, 是以, 伺服器無須為疊代記錄任何狀态。

因為疊代的所有狀态都儲存在遊标裡面, 而伺服器無須為疊代儲存任何狀态, 是以用戶端可以在中途停止一個疊代, 而無須對伺服器進行任何通知。即使有任意數量的疊代在中途停止, 也不會産生任何問題。

使用SCAN 指令傳入間斷的(broken)、負數、超出範圍或者其他非正常的遊标來執行增量式疊代并不會造成伺服器崩潰, 但可能會讓指令産生未定義的行為。未定義行為指的是, 增量式指令對傳回值所做的保證可能會不再為真。 隻有兩種遊标是合法的:

在開始一個新的疊代時, 遊标必須為 0 。

增量式疊代指令在執行之後傳回的, 用于延續疊代過程的遊标。

增量式疊代指令所使用的算法隻保證在資料集的大小有界的情況下, 疊代才會停止, 換句話說, 如果被疊代資料集的大小不斷地增長的話, 增量式疊代指令可能永遠也無法完成一次完整疊代。

從直覺上可以看出, 當一個資料集不斷地變大時, 想要通路這個資料集中的所有元素就需要做越來越多的工作, 能否結束一個疊代取決于使用者執行疊代的速度是否比資料集增長的速度更快。

SCAN, SSCAN, HSCAN 和 ZSCAN 指令都傳回一個包含兩個元素的 multi-bulk 回複: 回複的第一個元素是字元串表示的無符号 64 位整數(遊标), 回複的第二個元素是另一個 multi-bulk 回複, 包含了本次被疊代的元素。

SCAN 指令傳回的每個元素都是一個key。

SSCAN 指令傳回的每個元素都是一個集合成員。

HSCAN 指令傳回的每個元素都是一個鍵值對,一個鍵值對由一個鍵和一個值組成。

ZSCAN指令傳回的每個元素都是一個有序集合元素,一個有序集合元素由一個成員(member)和一個分值(score)組成。

疊代hash中的鍵值對:

本文作者:陳群

本文來自雲栖社群合作夥伴rediscn,了解相關資訊可以關注redis.cn網站。