Redis如何模糊匹配Key值
阿新 • • 發佈:2022-12-06
Redis模糊匹配Key值
使用Redis的scan代替Keys指令:
public Set<String> scan(String matchKey) { Set<String> keys = (Set<String>)redisTemplate.execute((RedisCallback<Set<String>>) connection -> { Set<String> keysTmp = new HashSet<>(); Cursor<byte[]> cursor = connection.scan(new ScanOptions.ScanOptionsBuilder() .match("*" + matchKey + "*").count(1000).build()); while (cursor.hasNext()) { keysTmp.add(new String(cursor.next())); } return keysTmp; }); return keys; }
為什麼不建議用Keys
對於生產環境上,有時我們需要從成千上萬的key中,找出我們指定的key,也就是模糊匹配出來的key,redis提供了一個簡單粗暴的命令:keys,它可以用來列出所有滿足特定正則字串規則的 key。
但是因為這個命令沒有offset、limit引數,一次性吐出所有滿足條件的key,假如有上百萬個key符合條件則會打崩Redis伺服器。
scan命令
特點如下:
- 複雜度和keys命令一樣,也是 O(n),但是它是通過遊標分步進行的,不會阻塞執行緒
- 提供limit引數,可以控制每次返回結果的最大條數,這裡是最大條數,而不是等於limit的條數,因為是匹配查詢,是在limit的範圍內匹配查詢
- 返回的結果可能會有重複
- 遍歷的過程中如果有資料修改,改動後的資料能不能遍歷到是不確定的;
- 單次返回的結果是空的並不意味著遍歷結束,而要看返回的遊標值是否為零;
scan優勢
Java中HashMap的底層實現結構,是陣列+連結串列的形式,在JDK1.7之後還加入了紅黑樹,在Redis當中,所有的
key都儲存在一個很大的字典中,這個字典結構就是一維陣列+二維連結串列的結構,scan指令返回的遊標就是第一維
陣列的位置索引,這個位置索引稱為槽 (slot)。 如果不考慮字典的擴容縮容,直接按陣列下標挨個遍歷就行了。
limit 引數就表示需要遍歷的槽位數,之所以返回的結果可能多可能少,是因為不是所有的槽位上都會掛接連結串列,
有些槽 位可能是空的,還有些槽位上掛接的連結串列上的元素可能會有多個。每一次遍歷都會將 limit 數量的槽位上掛
接的所有連結串列元素進行模式匹配過濾後,一次性返回給客戶端。