面试突击 | Redis 如何从海量数据中查询出某一个 Key?视频版
作者 | 王磊
面試突擊 | 第 001 期
1 考察知識(shí)點(diǎn)
本題考察的知識(shí)點(diǎn)有以下幾個(gè):
Keys 和 Scan 的區(qū)別
Keys 查詢的缺點(diǎn)
Scan 如何使用?
Scan 查詢的特點(diǎn)
2 解答思路
Keys 查詢存在的問題
Scan 的使用
Scan 的特點(diǎn)
3 Keys 使用相關(guān)
1)Keys 用法如下
2)Keys 存在的問題
此命令沒有分頁功能,我們只能一次性查詢出所有符合條件的 key 值,如果查詢結(jié)果非常巨大,那么得到的輸出信息也會(huì)非常多;
keys 命令是遍歷查詢,因此它的查詢時(shí)間復(fù)雜度是 o(n),所以數(shù)據(jù)量越大查詢時(shí)間就越長。
4 Scan 使用相關(guān)
我們先來模擬海量數(shù)據(jù),使用 Pipeline 添加 10w 條數(shù)據(jù),Java 代碼實(shí)現(xiàn)如下:
import redis.clients.jedis.Jedis; import redis.clients.jedis.Pipeline; import utils.JedisUtils;public class ScanExample {public static void main(String[] args) {// 添加 10w 條數(shù)據(jù)initData();}public static void initData(){Jedis jedis = JedisUtils.getJedis();Pipeline pipe = jedis.pipelined();for (int i = 1; i < 100001; i++) {pipe.set("user_token_" + i, "id" + i);}// 執(zhí)行命令pipe.sync();System.out.println("數(shù)據(jù)插入完成");} }我們來查詢用戶 id 為 9999* 的數(shù)據(jù),Scan 命令使用如下:?
127.0.0.1:6379> scan 0 match user_token_9999* count 10000 1) "127064" 2) 1) "user_token_99997" 127.0.0.1:6379> scan 127064 match user_token_9999* count 10000 1) "1740" 2) 1) "user_token_9999" 127.0.0.1:6379> scan 1740 match user_token_9999* count 10000 1) "21298" 2) 1) "user_token_99996" 127.0.0.1:6379> scan 21298 match user_token_9999* count 10000 1) "65382" 2) (empty list or set) 127.0.0.1:6379> scan 65382 match user_token_9999* count 10000 1) "78081" 2) 1) "user_token_99998"2) "user_token_99992" 127.0.0.1:6379> scan 78081 match user_token_9999* count 10000 1) "3993" 2) 1) "user_token_99994"2) "user_token_99993" 127.0.0.1:6379> scan 3993 match user_token_9999* count 10000 1) "13773" 2) 1) "user_token_99995" 127.0.0.1:6379> scan 13773 match user_token_9999* count 10000 1) "47923" 2) (empty list or set) 127.0.0.1:6379> scan 47923 match user_token_9999* count 10000 1) "59751" 2) 1) "user_token_99990"2) "user_token_99991"3) "user_token_99999" 127.0.0.1:6379> scan 59751 match user_token_9999* count 10000 1) "0" 2) (empty list or set)從以上的執(zhí)行結(jié)果,我們看出兩個(gè)問題:
查詢的結(jié)果為空,但游標(biāo)值不為 0,表示遍歷還沒結(jié)束;
設(shè)置的是 count 10000,但每次返回的數(shù)量都不是 10000,且不固定,這是因?yàn)?count 只是限定服務(wù)器單次遍歷的字典槽位數(shù)量 (約等于),而不是規(guī)定返回結(jié)果的 count 值。
相關(guān)語法:scan cursor [MATCH pattern] [COUNT count]
其中:
cursor:光標(biāo)位置,整數(shù)值,從 0 開始,到 0 結(jié)束,查詢結(jié)果是空,但游標(biāo)值不為 0,表示遍歷還沒結(jié)束;
match pattern:正則匹配字段;
count:限定服務(wù)器單次遍歷的字典槽位數(shù)量 (約等于),只是對(duì)增量式迭代命令的一種提示 (hint),并不是查詢結(jié)果返回的最大數(shù)量,它的默認(rèn)值是 10。
5 Scan 代碼實(shí)戰(zhàn)
本文我們使用 Java 代碼來實(shí)現(xiàn) Scan 的查詢功能,代碼如下:
import redis.clients.jedis.Jedis; import redis.clients.jedis.Pipeline; import redis.clients.jedis.ScanParams; import redis.clients.jedis.ScanResult; import utils.JedisUtils;public class ScanExample {public static void main(String[] args) {Jedis jedis = JedisUtils.getJedis();// 定義 match 和 count 參數(shù)ScanParams params = new ScanParams();params.count(10000);params.match("user_token_9999*");// 游標(biāo)String cursor = "0";while (true) {ScanResult<String> res = jedis.scan(cursor, params);if (res.getCursor().equals("0")) {// 表示最后一條break;}cursor = res.getCursor(); // 設(shè)置游標(biāo)for (String item : res.getResult()) {// 打印查詢結(jié)果System.out.println("查詢結(jié)果:" + item);}}} }以上程序執(zhí)行結(jié)果如下:
查詢結(jié)果:user_token_99997
查詢結(jié)果:user_token_9999
查詢結(jié)果:user_token_99996
查詢結(jié)果:user_token_99998
查詢結(jié)果:user_token_99992
查詢結(jié)果:user_token_99994
查詢結(jié)果:user_token_99993
查詢結(jié)果:user_token_99995
查詢結(jié)果:user_token_99990
查詢結(jié)果:user_token_99991
查詢結(jié)果:user_token_99999
6 總結(jié)
通過本文我們了解到,Redis 中如果要在海量的數(shù)據(jù)數(shù)據(jù)中,查詢某個(gè)數(shù)據(jù)應(yīng)該使用 Scan,Scan?具有以下特征:
Scan 可以實(shí)現(xiàn) keys 的匹配功能;
Scan 是通過游標(biāo)進(jìn)行查詢的不會(huì)導(dǎo)致 Redis 假死;
Scan 提供了 count 參數(shù),可以規(guī)定遍歷的數(shù)量;
Scan 會(huì)把游標(biāo)返回給客戶端,用戶客戶端繼續(xù)遍歷查詢;
Scan 返回的結(jié)果可能會(huì)有重復(fù)數(shù)據(jù),需要客戶端去重;
單次返回空值且游標(biāo)不為 0,說明遍歷還沒結(jié)束;
Scan 可以保證在開始檢索之前,被刪除的元素一定不會(huì)被查詢出來;
在迭代過程中如果有元素被修改, Scan 不保證能查詢出相關(guān)的元素。
7 視頻版
【END】
近期熱文
阿里巴巴2020招聘正式啟動(dòng)!附內(nèi)推和微信聯(lián)系信息
面試珍藏:最常見的200多道Java面試題(2019年最新版)
阿里面試官給你的一些忠告,這樣做肯定錯(cuò)不了!附視頻
Java面試詳解(2020版):500+ 面試題和核心知識(shí)點(diǎn)詳解
關(guān)注下方二維碼,訂閱更多精彩內(nèi)容
朕已閱?
總結(jié)
以上是生活随笔為你收集整理的面试突击 | Redis 如何从海量数据中查询出某一个 Key?视频版的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java 200+ 面试题补充③ Dub
- 下一篇: 面试突击第 3 期 | Redis 如何