zoukankan      html  css  js  c++  java
  • 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
     
     
     
     
     
     
     
  • 相关阅读:
    C++ 17
    C++ 11
    mysql统计某一个数据库中有几张表
    poj2636---Electrical Outlets(插线板)
    poj2608---几个字母映射到同一个数字
    poj2583---Series Determination
    poj2578---三个数中找出第一个大于168的
    poj2521---lose money
    poj2538---字符匹配(映射)
    poj2509---抽k根烟就换一支,求能抽烟的总数
  • 原文地址:https://www.cnblogs.com/yangyang2018/p/10275671.html
Copyright © 2011-2022 走看看