redis 用scan 代替keys,hgetAll


轉載自:https://blog.csdn.net/w05980598/article/details/80264568

 

 

 

 眾所周知,當redis中key數量越大,keys 命令執行越慢,而且最重要的會阻塞服務器,對單線程的redis來說,簡直是災難,終於找到了替代命令scan。

      

SCAN cursor [MATCH pattern] [COUNT count]

SCAN 命令及其相關的 SSCAN 命令、 HSCAN 命令和 ZSCAN 命令都用於增量地迭代(incrementally iterate)一集元素(a collection of elements):

  • SCAN 命令用於迭代當前數據庫中的數據庫鍵。
  • SSCAN 命令用於迭代集合鍵中的元素。
  • HSCAN 命令用於迭代哈希鍵中的鍵值對。
  • ZSCAN 命令用於迭代有序集合中的元素(包括元素成員和元素分值)。

以上列出的四個命令都支持增量式迭代, 它們每次執行都只會返回少量元素, 所以這些命令可以用於生產環境, 而不會出現像 KEYS命令、 SMEMBERS 命令帶來的問題 —— 當 KEYS 命令被用於處理一個大的數據庫時, 又或者 SMEMBERS 命令被用於處理一個大的集合鍵時, 它們可能會阻塞服務器達數秒之久。

不過, 增量式迭代命令也不是沒有缺點的: 舉個例子, 使用 SMEMBERS 命令可以返回集合鍵當前包含的所有元素, 但是對於 SCAN 這類增量式迭代命令來說, 因為在對鍵進行增量式迭代的過程中, 鍵可能會被修改, 所以增量式迭代命令只能對被返回的元素提供有限的保證 (offer limited guarantees about the returned elements)。

因為 SCAN 、 SSCAN 、 HSCAN 和 ZSCAN 四個命令的工作方式都非常相似, 所以這個文檔會一並介紹這四個命令, 但是要記住:

  • SSCAN 命令、 HSCAN 命令和 ZSCAN 命令的第一個參數總是一個數據庫鍵。
  • 而 SCAN 命令則不需要在第一個參數提供任何數據庫鍵 —— 因為它迭代的是當前數據庫中的所有數據庫鍵。
scan 0 默認返回10條數據。
127.0.0.1:6379> scan 0
1) "81920"
2)  1) "CMD:1000004739:4"
    2) "CMD:1000010475:2"
    3) "CMD:380071400001208:766"
    4) "CMD:1000006866:LIST"
    5) "CMD:380071400001208:20415"
    6) "CMD:380071400001231:21530"
    7) "CMD:380071400001208:21780"
    8) "CMD:7485630165:LIST"
    9) "CMD:1000001545:2"
   10) "CMD:380071400001231:4387"
 
可以用count 參數指定返回數據量:
127.0.0.1:6379> scan 0 count 100
1) "104448"
2)   1) "CMD:1000004739:4"
     2) "CMD:1000010475:2"
     3) "CMD:380071400001208:766"
     4) "CMD:1000006866:LIST"
     5) "CMD:380071400001208:20415"
     6) "CMD:380071400001231:21530"
     7) "CMD:380071400001208:21780"
     8) "CMD:7485630165:LIST"
     9) "CMD:1000001545:2"
    10) "CMD:380071400001231:4387"
    ......
    94) "CMD:201610200062:6"
    95) "CMD:VF3748211006:3"
    96) "CMD:1000009121:4"
    97) "CMD:380071400001231:6563"
    98) "CMD:1000010252:ID"
    99) "CMD:1000005261:5"
   100) "SERVER:45568_0"
 
使用match 參數來匹配模式:
127.0.0.1:6379> scan 0 match CMD* count 100
1) "104448"
2)  1) "CMD:1000004739:4"
    2) "CMD:1000010475:2"
    3) "CMD:380071400001208:766"
    4) "CMD:1000006866:LIST"
    5) "CMD:380071400001208:20415"
    6) "CMD:380071400001231:21530"
    7) "CMD:380071400001208:21780"
    8) "CMD:7485630165:LIST"
    9) "CMD:1000001545:2"
   10) "CMD:380071400001231:4387"
   ......
   86) "CMD:201610200062:6"
   87) "CMD:VF3748211006:3"
   88) "CMD:1000009121:4"
   89) "CMD:380071400001231:6563"
   90) "CMD:1000010252:ID"
   91) "CMD:1000005261:5"
最重要的是scan不會阻塞服務器,現網環境也可以用,真方便。
 
 
 
官方文檔:http://redisdoc.com/key/scan.html#scan
 
 
上java 代碼 
 
    /**
     *  
     * HSCAN 命令用於迭代哈希鍵中的鍵值對。
     * @Title: getSortedSetSize
     * @Description:
     * @param key
     * @return
     * @return long
     * @author   2019-1-16 上午10:17:03
     */
    public static Map<String, String> hscan(int dbIndex,String key,int pageSize){
        Map<String, String> map = new HashMap<String, String>();
        Jedis jedis = null;        
        try {
            jedis = getJedis();
            jedis.select(dbIndex);
            ScanParams sp = new ScanParams();
              sp.count(pageSize);//每次多少條  //可以設置模糊查詢             
              loop(map, key, jedis, "0", sp);    
        } catch (Exception e) {
            logger_xt_err.error(e.getMessage());
            return null;
        }finally{
            // 返還到連接池
            if(jedis!=null)close(jedis); 
        }
        return map;
    } 
    
    
    public static Map<String, String> loop(Map<String, String> mapList, String key, Jedis jedis, String cursor,
            ScanParams sp) {
        try {
            ScanResult<Entry<String, String>> map = jedis.hscan(key, cursor, sp);
            cursor = map.getStringCursor();
            for (Entry<String, String> en : map.getResult()) {
                mapList.put(en.getKey(), en.getValue());
            }
            System.out.println("cursor:" + cursor);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

        if (!"0".equals(cursor)) {
            loop(mapList, key, jedis, cursor, sp);
        }
        return mapList;
    }

 

使用的jar包:jedis-2.9.0.jar,commons-pool2-2.4.2.jar
 
 
 
 
 
 
 


免責聲明!

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



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