Spring RedisTemplate实现scan操作


老生常谈,keys不安全,因为

  • keys的操作会导致数据库暂时被锁住,其他的请求都会被堵塞;业务量大的时候会出问题

Spring RedisTemplate实现scan

1. hscan sscan zscan

  • 例子中的"field"是值redis的key,即从key为"field"中的hash中查找
  • redisTemplate的opsForHash,opsForSet,opsForZSet 可以 分别对应 sscan、hscan、zscan
  • 也可以使用 (JedisCommands) connection.getNativeConnection() 的 hscan、sscan、zscan 方法实现cursor遍历,参照下文2.2章节
try {
    Cursor<Map.Entry<Object,Object>> cursor = redisTemplate.opsForHash().scan("field",
    ScanOptions.scanOptions().match("*").count(1000).build());
    while (cursor.hasNext()) {
        Map.Entry<Object,Object> entry = cursor.next();
        Object key = entry.getKey();
        Object valueSet = entry.getValue();
    }
    //关闭cursor
    cursor.close();
} catch (IOException e) {
    e.printStackTrace();
}

 

  • cursor.close(); 游标一定要关闭,不然连接会一直增长;可以使用client lists info clients info stats 命令查看客户端连接状态,会发现scan操作一直存在
  • 我们平时使用的redisTemplate.execute 是会主动释放连接的,可以查看源码确认
  • 代码虽然只是调用一次scan方法,但是spring-data-redis已经对scan做了封装,这个scan结合cursor.hasNext会多次redis scan,最终拿到所有match的结果

2. scan

2.1 使用spring-data-redis封装好的scan方法

    public Set<String> scan(String matchKey) {
        Set<String> keys = redisTemplate.execute((RedisCallback<Set<String>>) connection -> {
            Set<String> keysTmp = new HashSet<>();
            Cursor<byte[]> cursor = connection.scan(new ScanOptions.ScanOptionsBuilder()
                            .match("*" + matchKey + "*").count(1000).build()); while (cursor.hasNext()) { keysTmp.add(new String(cursor.next())); } return keysTmp; }); return keys; }

 

  项目中我用的就是这种方法来代替 

Set keys = redisTemplate.keys(uploadTag + entity.getCaseNo() + ":*");

 

  


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM