Spring RedisTemplate實現scan操作


老生常談,keys不安全,因為

  • keys的操作會導致數據庫暫時被鎖住,其他的請求都會被堵塞;業務量大的時候會出問題

Spring RedisTemplate實現scan

1. hscan sscan zscan

  • 例子中的"field"是值redis的key,即從key為"field"中的hash中查找
  • redisTemplate的opsForHash,opsForSet,opsForZSet 可以 分別對應 sscan、hscan、zscan
  • 也可以使用 (JedisCommands) connection.getNativeConnection() 的 hscan、sscan、zscan 方法實現cursor遍歷,參照下文2.2章節
try {
    Cursor<Map.Entry<Object,Object>> cursor = redisTemplate.opsForHash().scan("field",
    ScanOptions.scanOptions().match("*").count(1000).build());
    while (cursor.hasNext()) {
        Map.Entry<Object,Object> entry = cursor.next();
        Object key = entry.getKey();
        Object valueSet = entry.getValue();
    }
    //關閉cursor
    cursor.close();
} catch (IOException e) {
    e.printStackTrace();
}

 

  • cursor.close(); 游標一定要關閉,不然連接會一直增長;可以使用client lists info clients info stats 命令查看客戶端連接狀態,會發現scan操作一直存在
  • 我們平時使用的redisTemplate.execute 是會主動釋放連接的,可以查看源碼確認
  • 代碼雖然只是調用一次scan方法,但是spring-data-redis已經對scan做了封裝,這個scan結合cursor.hasNext會多次redis scan,最終拿到所有match的結果

2. scan

2.1 使用spring-data-redis封裝好的scan方法

    public Set<String> scan(String matchKey) {
        Set<String> keys = 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; }

 

  項目中我用的就是這種方法來代替 

Set keys = redisTemplate.keys(uploadTag + entity.getCaseNo() + ":*");

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM