【Redis ScanOptions游标操作redis查询】

项目场景:

今日看MallChat业务代码中的RedisUtil工具类,看到没见过的方法,记录一下。


ScanOptions

平时操作Redis都是使用redisTemplate等操作。今天看到使用ScanOptions操作便查询了一下这个东西的使用场景。正常查询redis一些key的时候之前一般都用Keys * 这个方法去查询符合条件的key 。但是这个命令影响性能。如果生产环境的key很多,那么keys * 会很慢,因为redis是单线程的,这个keys 命令会导致redis卡顿,所以一般来说keys 命令都是禁用的。 所以redis后面出现了scan这个命令。这个命令类似分页查询,一次不会把全部key返回给你,而是返回一个游标Cursor。游标从0开始遍历,再回到0便利结束。
命令格式:

SCAN cursor [MATCH pattern] [COUNT count]
下面贴上RedisUtil里面的scan方法业务代码

  /**
     * 查找匹配key
     *
     * @param pattern key
     * @return /
     */
    public static List<String> scan(String pattern) {
        ScanOptions options = ScanOptions.scanOptions().match(pattern).build();
        RedisConnectionFactory factory = stringRedisTemplate.getConnectionFactory();
        RedisConnection rc = Objects.requireNonNull(factory).getConnection();
        Cursor<byte[]> cursor = rc.scan(options);
        List<String> result = new ArrayList<>();
        while (cursor.hasNext()) {
            result.add(new String(cursor.next()));
        }
        try {
            RedisConnectionUtils.releaseConnection(rc, factory);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return result;
    }

可以看到使用ScanOptions.scanOptions()创建builder,然后将表达式传入match方法。在调用build方法获得ScanOptions。然后通过链接工厂获得Redis的Connection。核心就是调用RedisConnection.scan()方法执行scan命令,然后返回游标cursor 。然后固定写法迭代器判断下一个还有没有值,然后取出就行。最后try catch释放连接。

原因分析:

这种写法在数据量小的时候没有问题,但是在key很多的时候就会出现卡死的问题。原因是scan是一个基于游标的迭代器,它的时间复杂度为O(n)相比于Keys命令来说有一个优点是不会阻塞redis,但在某条语句中如果不是异步调用的话会阻塞我们的程序执行,相当于分页查找redis中的所有key每拿出一页才会再次去拿下一页,spring内置的jedis默认页面大小是10。当你不用count()指定页面大小时,一页默认10条,当key数量大时就要频繁的通讯。


解决方案:

因此当数据量大时就要指定页面大小,防止多次通讯

ScanOptions options = ScanOptions.scanOptions().match(pattern).count(1000).build();
  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值