您好,登錄后才能下訂單哦!
這期內容當中小編將會給大家帶來有關Scan命令怎么在Redis 中使用,文章內容豐富且以專業的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
1. 概述
SCAN 命令以及比較相近的 SSCAN、HSCAN 和 ZSCAN 命令都用于增量迭代數據集元素:
SCAN 命令用于迭代當前數據庫中的數據庫鍵。
SSCAN 命令用于迭代集合(Set)中的元素。
HSCAN 命令用于迭代哈希(Hash)中的字段以及對應的值。
ZSCAN 命令用于迭代有序集合(Sorted Set)中的元素以及對應的得分。
由于這些命令都可以增量迭代,每次調用都只會返回少量元素,所以這些命令可以用于生產環境中,不用擔心像使用 KEYS、SMEMBERS 命令帶來的問題。在鍵或元素的大數據集上調用這些命令可能會長時間(甚至幾秒鐘)阻塞服務器。像 SMEMBERS 這樣的阻塞命令能夠在給定的時間內提供數據集中所有的元素,但 SCAN 系列命令僅對返回的元素提供有限的保證,因為數據集在我們增量迭代時可能會發生改變。
SCAN,SSCAN,HSCAN 以及 ZSCAN 命令工作原理都非常類似,因此這篇文章會涵蓋這四個命令。區別在于 SSCAN,HSCAN 以及 ZSCAN 命令,第一個參數是保存 Set,Hash或 Sorted Set 值的鍵的名稱。SCAN命令不需要任何鍵名參數,因為它會迭代當前數據庫中所有的鍵,因此迭代的對象是數據庫本身。
2. 基本用法
SCAN 是基于游標的迭代器。這意味著在每次調用該命令時,服務器都會返回一個更新后的新游標,用戶需要在下一次調用中將這個新游標作為 SCAN 命令的游標參數。當 SCAN 命令的游標參數被設置為 0 時, 服務器將開始一次新的迭代,而當服務器向用戶返回的新游標為 0 時會終止迭代。以下是 SCAN 迭代的示例:
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"
在上面的示例中,第一次調用使用 0 作為游標來開始一次新的迭代。第二次調用時使用上一次調用返回的游標,即命令回復的第一個元素值,即17。從上面的示例可以看到,SCAN 命令返回值是兩個值的數組:第一個值是下一次調用中將要使用的新游標,第二個值是包含返回元素的數組。
由于在第二次調用中返回的游標為 0,因此服務器向調用者發送信號,告知迭代已完成,并且遍歷完數據集。從游標值 0 開始迭代,然后調用 SCAN 直到返回的游標再次為 0,表示一個完整迭代。
3. 保證
SCAN 命令,以及其他增量迭代命令,在整個完整迭代過程中可以為用戶提供一系列的保證:
在完整迭代開始直到完整迭代結束期間內的所有元素都會被遍歷返回;這意味著,如果某個給定元素在開始迭代時位于數據集內,并且在終止迭代時仍然存在,那么 SCAN 會在某次迭代時返回給用戶。
在完整迭代開始直到完整迭代結束期間內不存在的元素永遠都不會被返回;因此,如果某個元素在迭代開始之前就被刪除,并且在后續的迭代過程中從未添加回數據集中,那么 SCAN 永遠都不會返回該元素 。
但是,由于 SCAN 只有很少的關聯狀態(僅有游標),因此具有以下缺點:
同一個元素可能會被返回多次。重復元素的問題需要我們自己的應用程序處理, 例如,可以考慮將迭代返回的元素用于冪等操作(可以重復執行多次操作)上。
如果一個元素是在迭代過程中被添加到數據集的,又或者是在迭代過程中從數據集中被刪除的,那么這個元素可能會被返回,也可能不會。
4. 每次執行返回數量
SCAN 系列的函數不能保證每次調用返回的元素數量會在給定范圍內。每次調用可能會返回 0 個元素,但只要返回的游標不為 0,客戶端就認為迭代沒有結束(即使返回了 0 個元素也不能表示迭代的結束)。返回的元素數量會符合一定的規則:
在迭代大型數據集時,SCAN 最多可能會返回幾十個元素。
在迭代小的數據集并且內部為編碼數據結構時(小的 Set、Hashe 以及 Sorted Set),單次調用就可以返回數據集的所有元素。
但是,用戶可以使用 COUNT 參數來調整每次調用返回的元素的數量級。
5. COUNT參數
雖然 SCAN 不能保證每次迭代返回的元素數量,但是可以使用 COUNT 參數根據經驗進行調整。基本上,COUNT 參數的作用就是讓用戶告知迭代命令,在每次迭代中應該從數據集里返回多少元素。雖然 COUNT 參數只是迭代命令實現上的一種提示(hint),但是在大多數情況下,這種提示是能滿足我們的預期:
COUNT 默認值為 10。
在迭代一個足夠大、由哈希表實現的數據庫、Set、Hash 或者 Sorted Set 時,如果用戶沒有使用 MATCH 參數,那么每次調用返回 COUNT 個元素,或者比 COUNT 稍多的元素。
在迭代一個編碼為 IntSet (一個只由整數值構成的小數據集) 或 Hash 的 Set 以及編碼為 ZipList (由不同值構成的小的 Hash 或者 Set) 的 Sorted Set 時,通常會無視 COUNT 參數指定的值,并在第一次調用時就將數據集包含的所有元素都返回給用戶。
沒有必要每次迭代都要使用相同的 COUNT 值。用戶可以在每次迭代中按自己的需要隨意改變 COUNT 值,只要記得將上次迭代返回的游標用到下次迭代里面就可以了。
6. MATCH參數
我們也可以通過匹配一個 Glob 風格的模式來迭代元素,類似于 KEYS 命令。我們只需要在 SCAN 命令后面追加 MATCH <pattern> 參數即可實現。
以下是一個使用 MATCH 參數進行迭代的示例:
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" 2) 1) "foo" 2) "feelsgood" 3) "foobar" redis 127.0.0.1:6379>
我們需要注意的是 MATCH 過濾器是在從數據集中檢索出元素之后,在將數據返回給客戶端之前應用的。這意味著,如果模式匹配到數據集中很少的元素,則 SCAN 命令在很多次迭代中可能不返回元素。一個例子如下所示:
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 為1000,強制命令對該迭代進行更多掃描,從而使得命令返回的元素也變多了。
7. TYPE參數
從 6.0 版開始,我們可以使用此參數要求 SCAN 命令僅返回與給定類型匹配的對象,從而允許我們遍歷數據庫以查找特定類型的鍵。SCAN 可以使用 TYPE 參數,但 HSCAN 或 ZSCAN 等不可用。
type 參數與 TYPE 命令返回的字符串名稱相同。需要我們注意的是某些 Redis 類型(例如GeoHashes、HyperLogLogs、Bitmap 以及 Bitfields 等)其內部是使用其他 Redis 類型(例如 String 或 Zset)來實現的,因此 SCAN 命令無法將其與相同類型的其他鍵區分開。例如,ZSET 和 GEOHASH:
redis 127.0.0.1:6379> GEOADD geokey 0 0 value (integer) 1 redis 127.0.0.1:6379> ZADD zkey 1000 value (integer) 1 redis 127.0.0.1:6379> TYPE geokey zset redis 127.0.0.1:6379> TYPE zkey zset redis 127.0.0.1:6379> SCAN 0 TYPE zset 1) "0" 2) 1) "geokey" 2) "zkey"
重要的是,TYPE 過濾器是在從數據庫中檢索元素之后應用的,因此該參數不會降低服務器完成完整迭代所需的負載,對于稀有類型,我們可能不會收到任何元素。
8. 多次并行迭代
不同客戶端可能在同一時間迭代同一數據集,客戶端每次執行迭代都需要傳入一個游標,并在迭代結束之后獲得一個新的游標,而這個游標就包含了迭代的所有狀態,因此,服務器無須為迭代記錄任何狀態。
9. 在中間終止迭代
由于服務器端不會記錄狀態,迭代的所有狀態都保存在游標中,因此調用方可以自由地中途終止迭代,不用向服務器發送通知。An infinite number of iterations can be started and never terminated without any issue.
10. 使用錯誤的游標調用SCAN
使用錯誤的,負數的,超出范圍的游標或其他無效的游標來調用 SCAN,會導致未定義的行為,但絕不會導致崩潰。未定義的是指 SCAN 將不再確保返回元素的保證。
唯一有效的游標是:
開始迭代時的游標值為0。
上一次調用 SCAN 返回的游標,以便繼續迭代。
11. 終止保證
只有在保證迭代的數據集大小始終保持在給定的最大上限內時(大小恒定),才能保證 SCAN 算法能終止;否則,對一直增長的數據集進行迭代可能會導致 SCAN 永遠不會終止迭代(死循環)。
這很容易直觀地看出:如果數據集不斷增長,為了訪問所有可能出現的元素,將需要做越來越多的工作,而能否結束一個迭代取決于對 SCAN 的調用次數、COUNT 參數值以及數據集的增長速度。
12. 返回值
SCAN,SSCAN,HSCAN 以及 ZSCAN 命令都返回一個包含兩個元素的回復,第一個元素表示游標的無符號64位整數,第二個元素是迭代出的元素數組:
SCAN 元素數組是鍵的列表。
SSCAN 元素數組是 Set 成員的列表。
HSCAN 元素數組包含兩個元素,即字段和值,對應 Hash 的每個返回元素。
ZSCAN 元素數組包含兩個元素,即一個成員及其關聯的分數,對應 Sorted Set 中的每個返回元素。
上述就是小編為大家分享的Scan命令怎么在Redis 中使用了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。