精华内容
下载资源
问答
  • Redis 模糊查询Key

    万次阅读 2019-12-04 11:14:47
    有时候需要模糊匹配查询redis中的所有key,比如:当采用redis做数据缓存,需要定时根据数据库中的数据更新redis缓存,为了避免遗漏数据,通常是先删除redis中的数据,再从数据库中查出后写入redis。在删除redis数据...

    有时候需要模糊匹配查询redis中的所有key,比如:当采用redis做数据缓存,需要定时根据数据库中的数据更新redis缓存,为了避免遗漏数据,通常是先删除redis中的数据,再从数据库中查出后写入redis。在删除redis数据时,需要指定key,如果此时key的数量较大,并满足一定的格式,就可以通过模糊匹配先查询出所有key。

    前置条件

    本文基于如下环境开发、调试:

    1. spring-boot:2.1.8.RELEASE
    2. spring-boot-starter-data-redis:2.1.8.RELEASE
      间接依赖:
      spring-data-redis:2.1.10.RELEASE
      io.lettuce:lettuce-core:5.1.8.RELEASE
    3. Redis Server 5.0.5

    Keys 命令

    https://redis.io/commands/keys
    查询redis key 最简单粗暴的方法,支持glob-style patterns(通配符匹配),分别是:*,?,[]

    其中:

    *:通配任意多个字符

    ?:通配单个字符

    []:通配括号内的某一个字符
    例如:
    h?llo matches hello, hallo and hxllo
    h*llo matches hllo and heeeello
    h[ae]llo matches hello and hallo, but not hillo
    h[^e]llo matches hallo, hbllo, … but not hello
    h[a-b]llo matches hallo and hbllo
    Spring 中通过调用RedisTemplate.keys() api可以实现:

    public interface RedisOperations<K, V> {
    	/**
    	 * Find all keys matching the given {@code pattern}.
    	 *
    	 * @param pattern must not be {@literal null}.
    	 * @return {@literal null} when used in pipeline / transaction.
    	 * @see <a href="https://redis.io/commands/keys">Redis Documentation: KEYS</a>
    	 */
    	@Nullable
    	Set<K> keys(K pattern);
    }
    

    为什么说简单粗暴

    这个命令优点是简单,初学者拿来即用。(但通常运维大神会在redis服务端禁用该命令),缺点是可能会直接导致redis服务宕机。由于redis服务是单线程工作,每一条到达的指令都是串行执行,而Keys 命令会全量遍历缓存中的所有key,直到结束,此刻请求redis服务的其它指令都将被阻塞,后台服务可能会因为超时而报错。这也是为什么会禁用该命令。

    Scan

    为了解决Keys命令的痛点,Redis2.8版本中加入了Scan指令,特点是迭代遍历,并可以指定返回数据的条数。
    https://redis.io/commands/scan
    SCAN cursor [MATCH pattern] [COUNT count] [TYPE type]

    • cursor:游标,当次遍历的起始位置
    • pattern:与Keys命令中的patterns相同,支持通配符匹配
    • count:返回数据条数,但只是一个hint(暗示),具体返回条数可多可少。
    • type: Redis 6.0 支持的参数,指定返回Key的类型,类型可选值与 TYPE命令相同:string, list, set, zset, hash and stream。
      本文Redis Server 为5.0.5版本,暂不讨论 type 参数。
      例如:查找匹配"DBAS_ORG_LINE*"格式的key,建议最大返回10条,格式如下:
      Scan
      返回两组数据,第一个数字是下次迭代的游标位置,第二组是满足规则的key列表

    什么时候结束迭代

    返回游标为 0,如下
    Scan结束
    通过迭代遍历,解决了keys命令全量遍历导致的Redis Server阻塞问题,大大提高的服务的可用性。

    Spring 中使用Scan,法一

    @SuppressWarnings("unchecked")
        public static List<String> scanKeysSimple(RedisTemplate redisTemplate, String pattern) {
            List<String> keys = (List<String>) redisTemplate.execute(connection -> {
                RedisKeyCommands keyCmds = connection.keyCommands();
                ScanOptions scanOpts = ScanOptions.scanOptions().match(pattern).count(1000L).build();
                Cursor<byte[]> cursor = keyCmds.scan(scanOpts);
                Set<String> set = new HashSet<>();
                while (cursor.hasNext()) {
                    byte[] bytes = cursor.next();
                    set.add(new String(bytes, StandardCharsets.UTF_8));
                }
                return new ArrayList<>(set);
            }, true);
            log.info("SCAN KEYS RETURN {} COUNT", CollectionUtils.isNotEmpty(keys) ? keys.size() : 0);
            return keys;
        }
    

    核心是调用 org.springframework.data.redis.connection.RedisKeyCommands#scan

    /**
    	 * Use a {@link Cursor} to iterate over keys.
    	 *
    	 * @param options must not be {@literal null}.
    	 * @return never {@literal null}.
    	 * @since 1.4
    	 * @see <a href="http://redis.io/commands/scan">Redis Documentation: SCAN</a>
    	 */
    	Cursor<byte[]> scan(ScanOptions options);
    

    通过org.springframework.data.redis.core.ScanOptions 指定匹配的模式字符串(pattern)和返回数据条数(count):

    ScanOptions scanOpts = ScanOptions.scanOptions().match(pattern).count(1000L).build();
    

    法一的缺陷

    spring 对Scan命令进行了封装,直接返回了满足条件的key列表,并没有告诉调用者下次迭代遍历的游标,可能此次迭代并未结束(返回游标不为 0 )。有人说可以把count值取大,比如 Long.MAX_VALUE,这样可以保证一次迭代既结束,不用考虑下次迭代。那么,这和Keys 命令又有什么区别呢,不如直接用 Keys。
    这种方法的适用场景是,不需要获取匹配指定格式的全量数据,类似抽样查询。

    Spring 中使用Scan,法二

    /**
         * 获取 指定格式的所有key
         * 迭代执行 SCAN 0 MATCH {pattern} COUNT 10000
         *
         * @param redisTemplate redisTemplate
         * @param pattern       匹配规则
         * @return 指定格式的所有key
         */
        public static List<String> scanKeys(RedisTemplate redisTemplate, String pattern) {
            //SCAN 0 MATCH {pattern} COUNT 10000
            return (List<String>) redisTemplate.execute(connection -> {
                //scan 迭代遍历键,返回的结果可能会有重复,需要客户端去重复
                Set<String> redisKeys = new HashSet<>();
                //lettuce 原生api
                RedisAsyncCommands conn = (RedisAsyncCommands) connection.getNativeConnection();
                //游标
                ScanCursor curs = ScanCursor.INITIAL;
                try {
                    //采用 SCAN 命令,迭代遍历所有key
                    while (!curs.isFinished()) {
                        long count = 10000L;
                        ScanArgs args = ScanArgs.Builder.matches(pattern).limit(count);
                        log.info("SCAN {} MATCH {} COUNT {}", curs.getCursor(), pattern, count);
                        RedisFuture<KeyScanCursor<byte[]>> future = conn.scan(curs, args);
                        KeyScanCursor<byte[]> keyCurs = future.get();
                        List<byte[]> ks = keyCurs.getKeys();
                        Set<String> set = ks.stream().map(bytes -> new String(bytes, StandardCharsets.UTF_8)).collect(Collectors.toSet());
                        log.info("return size:{}", set.size());
                        redisKeys.addAll(set);
                        curs = keyCurs;
                    }
                } catch (InterruptedException | ExecutionException e) {
                    throw new RuntimeException(e);
                }
                return new ArrayList<>(redisKeys);
            }, true);
        }
    

    核心是采用 lettuce 原生api。spring-boot-starter-data-redis 2.0以后,redis客户端由Jedis 改成了 Lettuce。此文基于spring-boot-starter-data-redis:2.1.8.RELEASE,故采用lettuce api。Jedis客户端也有类似的实现。
    io.lettuce.core.api.async.RedisAsyncCommands#scan()

    /**
         * Incrementally iterate the keys space.
         *
         * @param scanCursor cursor to resume from a previous scan, must not be {@literal null}
         * @param scanArgs scan arguments
         * @return KeyScanCursor&lt;K&gt; scan cursor.
         */
        RedisFuture<KeyScanCursor<K>> scan(ScanCursor scanCursor, ScanArgs scanArgs);
    
    • io.lettuce.core.ScanCursor 是迭代遍历的游标
    • io.lettuce.core.ScanArgs 是Scan的参数,包括count和pattern字符串。
    • io.lettuce.core.KeyScanCursor 是每次迭代后的返回数据,包含下次迭代的游标和此次迭代返回的keys列表。
      原生api可以获取到每次迭代后下次迭代的游标,便于采用轮询的方式实现真正的迭代遍历

    Tips

    采用scan 迭代遍历键,返回的结果可能会有重复,需要客户端去重复。
    代码中用 Set,存储每次迭代的key列表,可实现去重。

    源码地址

    https://gitee.com/thanksm/redis_learn/tree/master/redis_common

    展开全文
  • 需求:Redis hash类型模糊查询,同时对结果进行分页 首先是Redis hash类型模糊查询 //Cusor中存储的是查询key对应的Map Cursor<Map.Entry<String,String>> cursor = redisTemplate .opsForHash() ....

    今天在进行项目的时候需要Redis实现一个功能

    需求:Redis hash类型模糊查询,同时对结果进行分页

    首先是Redis hash类型模糊查询

    //Cusor中存储的是查询key对应的Map
    Cursor<Map.Entry<String,String>> cursor = redisTemplate
        .opsForHash()
        .scan("zhDicGoods", ScanOptions.scanOptions()       //绑定模糊查询的hash的key
              .match(name+"*")                                 //模糊查询规则
              .count(10000).build());
    

    其中关于match参数pattern

    *:通配任意多个字符

    ?:通配单个字符

    []:通配括号内的某一个字符

    再此遇到了一个问题,就是在模糊查询的时候**“查询内容+*”**可能查询不到,原因是redis默认的导入数据的时候可能存在乱码的问题

    就是遇到\xca\xed加上你key之类的乱码!

    你需要重新定义你导入key的内容

    在启动类中加入一个Bean

    @Bean  
        public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {  
           RedisTemplate<String, String> redisTemplate = new RedisTemplate<String, String>();  
           redisTemplate.setConnectionFactory(factory);  
     
           //key序列化方式;(不然会出现乱码;),但是如果方法上有Long等非String类型的话,会报类型转换错误;  
           //所以在没有自己定义key生成策略的时候,以下这个代码建议不要这么写,可以不配置或者自己实现ObjectRedisSerializer  
           //或者JdkSerializationRedisSerializer序列化方式;  
         RedisSerializer<String> redisSerializer = new StringRedisSerializer();//Long类型不可以会出现异常信息;  
         redisTemplate.setKeySerializer(redisSerializer);  
         redisTemplate.setHashKeySerializer(redisSerializer);  
     
           return redisTemplate;  
    

    以上解决了redis模糊查询的问题,接下来就是模糊查询的结果返回分页

    此处引用网上的资料,我会在末尾标注出来

    利用ZSET及HASH结构存储数据实现redis分页。

    1.  首先利用ZSET将表A中的id以value形式进行存储,以及利用ZSET中score进行排序处理;
    2.  将表A中数据以HASH结构进行存储,id作为HASH中key;
    3.  利用redis中的zRangeByScore进行ZSET分页取出id列表,然后即可取出HASH中分页后的数据。
    

    先创建一个pageUtil

    @Component
    public class PageUtil {
        @Autowired
        private RedisTemplate redisTemplate;
        /**
         * 存放单个hash缓存
         * @param key 键
         * @param hkey 键
         * @param value 值
         * @return
         */
        public boolean hput(String key, String hkey, Object value) {
            try {
                redisTemplate.opsForHash().put(key, hkey, value);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return false;
        }
    
        /**
         * 分页存取数据
         * @param key  hash存取的key
         * @param hkey hash存取的hkey
         * @param score 指定字段排序
         * @param value
         * @return
         */
        public boolean setPage(String key, String hkey, double score, String value){
            boolean result = false;
            try {
                result=redisTemplate.opsForZSet().add(key + ":page", hkey, score);
                //result = hput(key, hkey, value);
            } catch (Exception e) {
                e.printStackTrace();
            }
            //设置辅助分页的过期时间
            redisTemplate.expire(key+":page",1800000 , TimeUnit.MILLISECONDS);
            //redisTemplate.expire(key,60000 , TimeUnit.MILLISECONDS);
            return result;
        }
    
        /**
         * 分页取出 hash中hkey值
         * @param key
         * @param offset
         * @param count
         * @return
         */
        public  Set<String> getPage(String key, int offset, int count){
            Set<String> result = null;
            try {
                result = redisTemplate.opsForZSet().rangeByScore(key+":page", 1, 100000, (offset-1)*count, count);//1 100000代表score的排序氛围值,即从1-100000的范围
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result;
        }
    
        /**
         * 计算key值对应的数量
         * @param key
         * @return
         */
        public Integer getSize(String key){
            Integer num = 0;
            try {
                Long size = redisTemplate.opsForZSet().zCard(key+":page");
                return size.intValue();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return num;
        }
    }
    

    此处offset就是页码, count就是每页显示的条数

    调用就是在存储hash的时候存储一个对应的分页数据

    /**
         * 生成辅助分页
         * @param cursor
         * @param name:会在pageutil中自动加上:page
         */
    private void setPage(Cursor<Map.Entry<String,String>> cursor,String name,String tableName){
        //setPage初始化值,zset的sort值
        int i = 1;
        //遍历模糊查询结果,将模糊查询的结果生成分页数据,用zset存储模糊查询的数据排序
        //存储名称是查询name+:page,值是hash类型的key
        while (cursor.hasNext()){
            Map.Entry<String,String> result= cursor.next();
            //获取key
            String key = result.getKey();
            //获取value
            String value = result.getValue();
            //存储对应的辅助分页数据
            pageUtil.setPage(tableName+name,key,i,null);
            i++;
    
        }
    }
    

    然后就是查询数据的时候不从hash中查询,从zset中查询到hkey,然后在查询hash类型

    /**
         * 获取分页的总数据,并且加入到map中
         * @param name
         * @param currentPage
         * @param count
         * @param resultMap
         * @param result
         */
    private void getPageResult(String name,int currentPage, int count,Map resultMap,ArrayList result,String tableName,T t){
    
        //得到分页数据总条数
        Integer totalNumber = pageUtil.getSize(tableName+name);
        //得到对应分页的key数组
        Set<String> keyPages = pageUtil.getPage(tableName+name, currentPage, count);
        //遍历循环查询对应cout对应的数据,同时转为对象输入到List
        count =keyPages.size();
        for (String keyPage : keyPages) {
            //根据zset的key查询hash对应的数据
            String JSONObject = (String) redisTemplate.boundHashOps(tableName).get(keyPage);
            //转为对应的实体类
            T Object = (T) JSON.parseObject(JSONObject, (Type) t);
            result.add(Object);
        }
        //返回总页数
        Integer totalPage;
        if(totalNumber<=count){
            totalPage=1;
        }else {
            totalPage =totalNumber/10+1;
        }
    
        //加入返回实体类结果,总条数,起始页数,总条数
        resultMap.put("result",result);
        resultMap.put("totalNumber",totalNumber);
        resultMap.put("currentPage",currentPage);
        resultMap.put("count",count);
        resultMap.put("totalPage",totalPage);
    }
    

    模糊查询以及分页我设置了一个工具类,总的是

    @Component
    public class RedisFurryAndPageQueryUtil<T> {
        //插入辅助分页
        @Autowired
        private PageUtil pageUtil;
        //注入redis模板工具
        @Autowired
        private RedisTemplate redisTemplate;
    
    
        /**
         * 根据条件进行模糊查询查询并返回分页结果
         * @param name
         * @param currentPage
         * @param count
         * @return
         */
        public Map<String,Object> find(String name, int currentPage, int count,String tableName,T t) {
            //将传入的参数变为小写
            name = StringUtils.lowerCase(name);
            //map用来存储查询到的结果以及分页的总数据
            Map<String,Object> map = new HashMap<>();
            //用来存储查询到的ZhDicGoods
            ArrayList<ZhDicGoods> result = new ArrayList<>();
            //定义pageName用来查看redis中是否存在对应的辅助分页key-value
            String pageName = tableName+name + ":page";
            //是否存在对应的辅助分页辅助分页key-value
            Boolean ifExist = redisTemplate.hasKey(pageName);
            //如果不存在,生成辅助分页,同时查询
            if(!ifExist){
                try {
                    //如果传入参数为空则查询所有
                    if(name==null||"".equals(name)){
                        //模糊查询返回结果
                        //Cusor中存储的是查询key对应的Map
                        Cursor<Map.Entry<String,String>> cursor = redisTemplate
                                .opsForHash()
                                .scan(tableName, ScanOptions.scanOptions()       //绑定模糊查询的hash的key
                                        .match("*")                                      //模糊查询规则
                                        .count(1000).build());
                    }
                    //模糊查询返回结果
                    //Cusor中存储的是查询key对应的Map
                    Cursor<Map.Entry<String,String>> cursor = redisTemplate
                            .opsForHash()
                            .scan(tableName, ScanOptions.scanOptions()       //绑定模糊查询的hash的key
                                    .match(name+"*")                                 //模糊查询规则
                                    .count(10000).build());
                    //生成分页key-value
                    setPage(cursor,name,tableName);
                    //生成查询结果并且放入map中
                    getPageResult(name,currentPage,count,map,result,tableName,t);
                    cursor.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }else{
                //有辅助分页key-value,直接查询结果放入map中
                getPageResult(name,currentPage,count,map,result,tableName,t);
            }
            //返回result
            return map;
    
        }
    
    
        /**
         * 生成辅助分页
         * @param cursor
         * @param name:会在pageutil中自动加上:page
         */
        private void setPage(Cursor<Map.Entry<String,String>> cursor,String name,String tableName){
            //setPage初始化值,zset的sort值
            int i = 1;
            //遍历模糊查询结果,将模糊查询的结果生成分页数据,用zset存储模糊查询的数据排序
            //存储名称是查询name+:page,值是hash类型的key
            while (cursor.hasNext()){
                Map.Entry<String,String> result= cursor.next();
                //获取key
                String key = result.getKey();
                //获取value
                String value = result.getValue();
                //存储对应的辅助分页数据
                pageUtil.setPage(tableName+name,key,i,null);
                i++;
    
            }
        }
    
    
        /**
         * 获取分页的总数据,并且加入到map中
         * @param name
         * @param currentPage
         * @param count
         * @param resultMap
         * @param result
         */
        private void getPageResult(String name,int currentPage, int count,Map resultMap,ArrayList result,String tableName,T t){
    
            //得到分页数据总条数
            Integer totalNumber = pageUtil.getSize(tableName+name);
            //得到对应分页的key数组
            Set<String> keyPages = pageUtil.getPage(tableName+name, currentPage, count);
            //遍历循环查询对应cout对应的数据,同时转为对象输入到List
            count =keyPages.size();
            for (String keyPage : keyPages) {
                //根据zset的key查询hash对应的数据
                String JSONObject = (String) redisTemplate.boundHashOps(tableName).get(keyPage);
                //转为对应的实体类
                T Object = (T) JSON.parseObject(JSONObject, (Type) t);
                result.add(Object);
            }
            //返回总页数
            Integer totalPage;
            if(totalNumber<=count){
                totalPage=1;
            }else {
                totalPage =totalNumber/10+1;
            }
    
            //加入返回实体类结果,总条数,起始页数,总条数
            resultMap.put("result",result);
            resultMap.put("totalNumber",totalNumber);
            resultMap.put("currentPage",currentPage);
            resultMap.put("count",count);
            resultMap.put("totalPage",totalPage);
        }
    
    }
    

    以上就是此次工作的整体步骤

    查看的文档还有博客有

    spring中redisTemplate实现redis分页

    https://segmentfault.com/a/1190000020866225

    redis 模糊查询

    https://blog.csdn.net/zhaipengfei1231/article/details/80819454?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.edu_weight&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.edu_weight

    scan实现模糊查询redis数据

    https://blog.csdn.net/yuan_sun/article/details/102663986?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-9.edu_weight&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-9.edu_weight

    Springdataredis Api文档

    https://docs.spring.io/spring-data/redis/docs/2.2.4.RELEASE/api/

    一些小知识

    StringRedisTemplate/RedisTemplate设置过期时间

    https://blog.csdn.net/qq_35192741/article/details/91448395

    //redistemplate是否包含key
    public Boolean hasKey(K key)
    
    //子类继承父类的文档注释
    ctrl+O  弹出的窗口下面把 勾下 JavaDoc 就可以了
    
    展开全文
  • StackExchange.Redis模糊查询

    千次阅读 2018-10-10 17:05:22
    如果想做模糊查询,该怎么办?Redis Client那么强大,api不可能只限于此,查了查Redis官网,果然有大招,那就是LuaScript. 我们来先认识一下LuaScript,它是一个EVAL脚本。Redis2.6.0有内置的Lua编译器,EVAL就是...
    StackExchange.Redis用LuaScript执行代参命令

    Redis在查询上提供给.net的api方法,只有StringGet、StringGetBit、StringGetRange。如果想做模糊查询,该怎么办?Redis Client那么强大,api不可能只限于此,查了查Redis官网,果然有大招,那就是LuaScript.
    我们来先认识一下LuaScript,它是一个EVAL脚本。Redis2.6.0有内置的Lua编译器,EVAL就是用来在Lua编译器里执行脚本的。

    LuaScript的源生使用

    使用之前我们先来瞄一眼EVAL原貌,下图是命令示例:
    在这里插入图片描述

    1.EVAL 的第一个参数是Lua 5.1的脚本。脚本不需要定义Lua方法体(也不需要

    ),它只是一个即将运行在Redis服务器上下文中的Lua程序

    2.第二个参数是跟在脚本之后的指示Redis键名的个数,键可访问脚本中下标以1为基数的KEYS[n]变量。

    3.其他的参数以ARGV 来命名
    示例返回结果:

        1) "key1"
        2) "key2"
        3) "first"
        4) "second"
    

    以Lua脚本去调用Redis命令可以从用下两个不同的Lua函数,区别于出错处理方式:
    redis.call() 抛出错误给调用者
    redis.pcall() 以Lua表的形式返回结果

    C#中使用LuaScript

    言归正传,回到代码中来,Redis如何使用LuaScript呢?直接上代码实菜吧,写一个模糊查询key的方法,这里我已经实例好了一个cache单例,直接使用:

            /// <summary>
            /// 判断是否存在包含keyPattern的key
            /// </summary>
            /// <param name="keyPattern"></param>
            /// <returns></returns>
            public bool ExistPatternKey(string keyPattern) 
            {
                var script = "return redis.call('keys',@pattern)";
                var prepared = LuaScript.Prepare(script);
                var cacheResult= cache.ScriptEvaluate(prepared, new { pattern = keyPattern });
                if (cacheResult.IsNull)
                {
                    return false;
                }
                return ((string[])cacheResult).Length > 0;
            }
    
    展开全文
  • 1、模糊搜索查询redis 默认有16个DB , 0-15 ) Redis 模糊搜索 1、keys * 匹配数据库中所有 key 2、keys h?llo 匹配 hello , hallo 和 hxllo 等。 3、keys h*llo 匹配 hllo 和 heeello 等。 4、keys h[ae]llo...

    创建一条测试 数据 查询 (默认是 DB 0 )

    创建:
    set name xiaoming
    查询:
    get name 

    1、模糊搜索查询 (redis 默认有16个DB , 0-15 )

    Redis 模糊搜索
    1、keys *   匹配数据库中所有 key 
    2、keys h?llo   匹配 hello , hallo 和 hxllo 等。
    3、keys h*llo   匹配 hllo 和 heeello 等。
    4、keys h[ae]llo   匹配 hallo 和 hello ,但不匹配 hillo;特殊符号用 \ 隔开。
    redis> keys *o*
    1) "four"
    2) "two"
    3) "one"
    redis> keys t??
    1) "two"
    redis> keys t[w]*
    1) "two"
    redis> keys *    # 匹配数据库内所有 key
    1) "four"
    2) "three"
    3) "two"
    4) "one"
    redis-cli  进入默认是第一个DB 0 ; select 切换 DB 
    > select 2;

    2、删除指定key :

    # 删除所有以 user 开头的key 可以这样实现:

    先获取

    # redis-cli keys "user*"
    1) "user1"
    2) "user2"

    执行删除命令

    # redis-cli keys "user*" | xargs redis-cli del
    (integer) 2
    # 删除成功
    # 删除当前数据库中的所有Key 
    > flushdb 
    # 删除所有数据库中的key 
    > flushall
    # 删除单个 key
    redis> SET name zhangsan
    OK
    redis> DEL name
    (integer) 1
    
    # 删除一个不存在的 key
    redis> EXISTS lisi
    (integer) 0
    
    redis> DEL phone   # 失败,没有 key 被删除
    (integer) 0
    # 同时删除多个 key
    redis> SET name "redis"
    OK
    redis> SET type "key-value store"
    OK
    redis> SET website "redis.com"
    OK
    redis> DEL name type website
    (integer) 3
    # 批量删除匹配通配符的key用到了Linux中的管道和xargs参数:
    
    redis-cli keys "s*" | xargs redis-cli del
    # 如果需要制定数据库,需要用到 -n 数据库编号 参数,下面是删除 2数据库中 s开头的键:
    
    redis-cli -n 2 keys "s*" | xargs redis-cli -n 2 del
    
    redis-cli keys "*" | xargs redis-cli del 

     

    3、Redis Sortedset 数据查询

    redis sortedset 数据查询:
    
    172.16.12.36:6003> zrank qa:hall 103228953392713728
    (integer) 10021
    
    172.16.12.36:6003> ZCARD qa:hall
    (integer) 10022

     

    4、TTL key : 以秒为单位,返回给定 key 的剩余生存时间(TTL, time to live)。

    返回值:
    当 key 不存在时,返回 -2 。
    当 key 存在但没有设置剩余生存时间时,返回 -1 。
    否则,以秒为单位,返回 key 的剩余生存时间。
    在 Redis 2.8 以前,当 key 不存在,或者 key 没有设置剩余生存时间时,命令都返回 -1 。

    查询检测 ttl 值:

    # 不存在的 key
    redis> FLUSHDB
    OK
    redis> TTL key
    (integer) -2
    # key 存在,但没有设置剩余生存时间
    redis> SET key value
    OK
    redis> TTL key
    (integer) -1
    
    # 有剩余生存时间的 key
    redis> EXPIRE key 10086
    (integer) 1
    
    redis> TTL key
    (integer) 10010

     

    5、redis type key

    TYPE key : 返回 key 所储存的值的类型。

    返回值:
    none (key不存在)
    string (字符串)
    list (列表)
    set (集合)
    zset (有序集)
    hash (哈希表)
    # 字符串
    redis> SET weather "sunny"
    OK
    redis> TYPE weather
    string
    # 列表
    redis> LPUSH book_list "programming in scala"
    (integer) 1
    redis> TYPE book_list
    list
    # 集合
    redis> SADD pat "dog"
    (integer) 1
    redis> TYPE pat
    set

     


    原文链接:https://www.cnblogs.com/sharesdk/p/9203449.html

     

     

     

    展开全文
  • 封装scan方法进行redis模糊查询 public function redisScan($pattern, $count = 1000){ $redis = new \myredis\Datasource(); $myredis = $redis::getRedis('instance1'); $ret = []; $iterator = 0; while ...
  • springboot实现redis模糊查询

    千次阅读 2019-05-07 09:33:50
    --redis--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> 相关...
  • 我们在实际开发中,会遇到在redis模糊查询匹配的键值需求。主要有两种方式,第一:KEYS pattern 第二:SCAN 但是第一种方式的时间复杂度为O(N),其中N为数据库中密钥的数目。简单介绍下他的用法 一.KEYS pattern ...
  • StackExchange.Redis 模糊查询和删除

    千次阅读 2018-02-21 01:36:00
    Redis的keys模糊查询: " local res = redis.call('KEYS', @keypattern) " + " return res " ), new { @keypattern = pattern }); if (! redisResult.IsNull) {  _db.KeyDelete(( string [])...
  • MyBatis查询结果返回hashmap需要注意的问题 <select id="getMessageById" resultType="hashmap"> SELECT a.*,b.name,b.vipName,b.thumb FROM `user` b LEFT JOIN message a on b.id=a.creator where a.id...
  • StackExchange.Redis 使用LuaScript脚本模糊查询hash 原文:StackExchange.Redis 使用LuaScript脚本模糊查询hash 获取redis连接 public class RedisHelp...
  • redis key 模糊查询

    万次阅读 2017-08-07 14:31:43
    于是改一下方式,使用hash, (key hkey hvalue),把要模糊查询的值放到hkey上面。然后使用scan来模糊查询。效率上面没什么变化。 期间有一个问题花了不少时间: sacanBuider.match("*t*") 匹配hkey,而hkey...
  • redis 模糊删除keys

    千次阅读 2019-01-02 17:53:45
    由于在我们的项目中使用Spring Cached和Redis结合的...Redis keys命令支持模式匹配,但是del命令不支持模式匹配,有时候需要根据一定的模式来模糊删除key,这时只能结合shell命令来完成了。 具体命令是: redis-c...
  • 1.解释 2.保存 3.读取 4.设置过期时间 5.模糊查询
  • Redis命令:scan实现模糊查询

    万次阅读 多人点赞 2017-12-31 16:54:33
    Redis v2.8开始,SCAN命令已经可用,它允许使用游标从keyspace中检索键。 对比KEYS命令,虽然SCAN无法一次性返回所有匹配结果,但是却规避了阻塞系统这个高风险,从而也让一些操作可以放在主节点上执行。 2.SCAN...
  • redis 模糊查找keys

    2017-07-04 11:28:00
    redis可以通过命令Keys Match来进行键值的模糊匹配,借助StackExchange.Redis时,由于Dll内部没有实现Keys Match的操作,不过,StackExchange.Redis提供了直接执行Lua语句的入口: RedisResult ScriptE...
  • Redis工具类 package com.xd.common.server; import com.alibaba.fastjson.JSON; import lombok.extern.slf4j.Slf4j; import net.sf.jsqlparser.schema.*; import org.redisson.api.RedissonClient; import
  • Spring data redis模糊key,并删除数据

    千次阅读 2019-07-10 01:21:09
    1、使用spring data Redis 中的StringRedisTemplate模糊匹配key 模糊匹配的方法,源码如下: public Set<K> keys(K pattern) { final byte[] rawKey = rawKey(pattern); Set<byte[]> rawKeys = ...
  • 如果使用redis的频次较高,那么业务中经常会出现需要根据关键字进行批量查询,所以总结一下StackExchange中使用批量查询的方法(如果数据量很大,那么在redis模糊查询很耗时,请慎用!) 初始化redis连接对象: ...
  • 但是随着项目的使用量,数据,并发量日益庞大,连redis都开始成为瓶颈,这时候使用模糊查询会非常耗费资源,所以我研究了一下如何避免模糊查询来删除列表数据。 有两种思路 第一种是专门维护缓存的键名,比如建立...
  • StackExchange.Redis
  • SpringBoot系列12-redis-pipeline keys模糊查询替代方案 https://www.lskyf.com/post/68
  • 相比于keys命令,scan命令的优势: scan命令的时间复杂度虽然也是O(N),但它是分次进行的,不会阻塞线程。 scan命令提供了limit参数,可以控制每次返回结果的最大条数...redis 里存有数据:TEST:CODE:DEMO:key1、TE...
  • RedisRedis集群模糊匹配删除key

    千次阅读 2019-04-15 15:51:18
    而在Redis内我们如何进行模糊匹配呢?集群情况Redis Cluster的情况是否和单机一致呢?前段时间我对于这个议题进行了调查和研究。 单节点的情况 Jedis 参考stackoverflow上的解答,在Java内使用Jedis主要有如下2中...
  • Redis系列之模糊匹配查询

    千次阅读 2020-07-11 23:52:09
    概述,为何需要模糊查询;两种实现方式; keys/scan命令支持3个通配符:*,?,[] keys缺点;keys命令代码实例; 引入scan命令;scan代码实例; scan原理;

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,012
精华内容 2,404
关键字:

hashredis模糊查询

redis 订阅