1. 程式人生 > 其它 >Redis如何模糊匹配Key值

Redis如何模糊匹配Key值

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 數量的槽位上掛

接的所有連結串列元素進行模式匹配過濾後,一次性返回給客戶端。