Spring Redis 模糊查询匹配key

背景

原方法在Redis内存储条数过多时效率较低,尝试进行改良。修改模糊查询方式后有效提高查询效率。

改良步骤

原方法

原模糊查询方法采用ScanOptions匹配key的前缀,但并未设置游标步进值,导致其实际效率可能跟使用keys命令相同。

改进

  1. 改用lettuce api RedisAsynCommands构建Redis连接。
  2. 加入游标步进值实现迭代查询。
  3. 由于scan命令可能得到重复的key,使用set进行去重。
参考代码
/**
     * 获取 指定格式的所有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);
    }

参考:
https://blog.csdn.net/drhrht/article/details/126489560

posted @ 2022-11-21 16:58  zjcfrancis  阅读(2582)  评论(0编辑  收藏  举报