Scan命令
Scan命令:從海量的 key 中找出滿足特定前綴的 key 列表
查詢key為某一類型的數據可能有很多方法,例如可以通過keys*或者是keys codehole*,查詢key前綴為codehole的redis緩沖數據,但是當緩沖數據量比較大時,該命令表耗費時間,效率比較慢,具體的缺點如下列所說那樣。
一、keys * 、keys codehole* 分別是查詢全部的key以及查詢前綴為codehole的key。特點太暴力,性能不好,搜索的是整個redis;
缺點:
1、沒有 offset、limit 參數,一次性吐出所有滿足條件的 key,萬一實例中有幾百 w 個 key 滿足條件,當你看到滿屏的字符串刷的沒有盡頭時,你就知道難受了。
2、keys 算法是遍歷算法,復雜度是 O(n),如果實例中有千萬級以上的 key,這個指令就會導致 Redis 服務卡頓,所有讀寫 Redis 的其它的指令都會被延后甚至會超時報錯,因為 Redis 是單線程程序,順序執行所有指令,其它指令必須等到當前的 keys 指令執行完了才可以繼續。
二、由於keys命令存在以上的缺點,所以redis引入以下scan命令,scan命令的特點:
1、復雜度雖然也是 O(n),但是它是通過游標分步進行的,不會阻塞線程;
2、提供 limit 參數,可以控制每次返回結果的最大條數,limit 只是一個 hint,返回的結果可多可少;
3、同 keys 一樣,它也提供模式匹配功能;
4、服務器不需要為游標保存狀態,游標的唯一狀態就是 scan 返回給客戶端的游標整數;
5、返回的結果可能會有重復,需要客戶端去重復,這點非常重要;
6、遍歷的過程中如果有數據修改,改動后的數據能不能遍歷到是不確定的;
7、單次返回的結果是空的並不意味着遍歷結束,而要看返回的游標值是否為零
三、scan命令具體用法:
1、scan提供3個參數:第一個是 cursor 整數值,第二個是 key 的正則模式,第三個是遍歷的 limit hint,例如:scan 0 match key99* count 1000 解釋:從0開始遍歷,匹配key99*,總數是1000 ,1000不是結果數量,是redis單次遍歷字典槽位數量(約等於),如下圖所示:
scan 參數提供了三個參數,第一個是 cursor 整數值,第二個是 key 的正則模式,第三
個是遍歷的 limit hint。第一次遍歷時,cursor 值為 0,然后將返回結果中第一個整數值作為
下一次遍歷的 cursor。一直遍歷到返回的 cursor 值為 0 時結束。
127.0.0.1:6379> scan 0 match key99* count 1000
1) "13976"
2) 1) "key9911"
2) "key9974"
3) "key9994"
4) "key9910"
5) "key9907"
6) "key9989"
7) "key9971"
8) "key99"
9) "key9966"
10) "key992"
11) "key9903"
12) "key9905"
127.0.0.1:6379> scan 13976 match key99* count 1000
1) "1996"
2) 1) "key9982"
2) "key9997"
3) "key9963"
4) "key996"
5) "key9912"
6) "key9999"
7) "key9921"
8) "key994"
9) "key9956"
10) "key9919"
127.0.0.1:6379> scan 1996 match key99* count 1000
1) "12594"
2) 1) "key9939"
2) "key9941"
3) "key9967"
4) "key9938"
5) "key9906"
6) "key999"
7) "key9909"
8) "key9933"
9) "key9992"
......
127.0.0.1:6379> scan 11687 match key99* count 1000
1) "0"
2) 1) "key9969"
2) "key998"
3) "key9986"
4) "key9968"
5) "key9965"
6) "key9990"
7) "key9915"
8) "key9928"
9) "key9908"
10) "key9929"
11) "key9944"
2、scan遍歷順序采用高位進位加法來遍歷,進位的方向是從高位到低位,原因是考慮到字典的擴容和縮容時避免槽位的遍歷重復和遺漏。
3、redis的擴容:舊的數據移動到新的新組下,redis采用漸進式 rehash,同時保留舊數組和新數組
4、定位大key:redis提供給了一個命令:redis-cli -h 127.0.0.1 -p 7001 –-bigkeys,如果擔心該指令會大幅提升redis的ops,可以增加一個休眠的參數:redis-cli -h 127.0.0.1 -p 7001 –-bigkeys -i 0.1