在巨大的數據量的狀況下,作查找符合某種規則的Key的信息,這裏就有兩種方式:java
都是用於增量迭代集合元素。正則表達式
以後的例子會以sscan爲例redis
redis 127.0.0.1:6379> SSCAN key cursor [MATCH pattern] [COUNT count]
複製代碼
Key:查詢的相關集合名稱數據庫
cursor: 遊標值,第一次迭代使用 0 做爲遊標,表示開始一次新的迭代數組
[MATCH pattern] : 模糊匹配服務器
[COUNT count] :每次的查詢條數,默認值爲 10spa
在上面這個例子中, 第一次迭代使用 0 做爲遊標,表示開始一次新的迭代。線程
第二次迭代使用的是第一次迭代時返回的遊標, 也便是命令回覆第一個元素的值 —— 3 。code
以 0 做爲遊標開始一次新的迭代, 一直調用 SCAN 命令, 直到命令返回遊標 0 , 咱們稱這個過程爲一次完整遍歷(full iteration)。cdn
在同一時間, 能夠有任意多個客戶端對同一數據集進行迭代, 客戶端每次執行迭代都須要傳入一個遊標, 並在迭代執行以後得到一個新的遊標, 而這個遊標就包含了迭代的全部狀態, 所以, 服務器無須爲迭代記錄任何狀態,一樣也不會阻塞線程
match: 經過提供一個 glob 風格的模式參數,讓命令只返回和給定模式相匹配的元素。
前方高能預警:match的底層操做是在從數據集中取出元素以後,向客戶端返回元素以前的這段時間內進行的, 若是返回的結果集中沒有匹配,那麼可能會在屢次執行中都不返回任何元素。
因此單次返回的結果是空的並不意味着遍歷結束,而要看返回的遊標值是否爲零;
count:能夠控制每次返回結果的最大條數,count只是一個 hint,返回的結果可多可少.
在線上有時候須要對大量key進行刪除操做,有幾個風險點:
可是經過用scan,咱們就能夠指定有共性的key,並指定一次性查詢條件。
for (String cacheName : cacheNames) {
String keyPrefix = new String(cachePrefix.prefix(cacheName)); //拼接咱們的
ScanParams scanParams = new ScanParams().match(keyPrefix.concat("*")).count(200); //指定規則
String cur = ScanParams.SCAN_POINTER_START; //遊標初始值爲0
boolean hasNext = true;
int count = 0;
while (hasNext) {
count++;
ScanResult<String> scanResult = jedisCluster.scan(cur, scanParams); //key的正則表達式
List<String> keys = scanResult.getResult();
for (String key : keys) {
jedisCluster.del(key);
}
cur = scanResult.getStringCursor(); //返回用於下次遍歷的遊標
if (StringUtils.equals("0", cur)) { //說明遍歷已結束
hasNext = false;
}
}
log.info("redis cache evict {} {}", cacheName, count);
}
}
複製代碼