redis的hscan写法``
HSCAN key cursor [MATCH pattern] [COUNT count]
这里明明是有cursor参数,为何spring的redistemplate客户端中不提供该起始游标的参数?
RedisTemplate rt;
rt.opsForHash().scan("key", ScanOptions.scanOptions().count(100).match("*").build());
ScanOptions该方法只有两个参数:
public class ScanOptions {
/**
* Constant to apply default {@link ScanOptions} without setting a limit or matching a pattern.
*/
public static ScanOptions NONE = new ScanOptions(null, null);
private final @Nullable Long count;
private final @Nullable String pattern;
那么问题来了,开始的游标的参数在哪里呢?于是乎有人就这样误用这个方法了
错误使用示例:
RedisTemplate rt;
rt.opsForHash().scan("key", ScanOptions.scanOptions().count(Integer.MAX_VALUE).match("*").build());
一次拿完所有的的值,这样使用这个方法的意义就没有了,这个方法的本意是分批小段遍历,这样一次取出来和直接hkeys全部没有任何区别,时间复杂度都是O(n),那这个方法的count参数应该传什么值?答案就是一般传某一分页大小的值(其实这个值是不能用来分页的,因为这个值只是个大概值,redis不保证传回的数量是多少,这是另一个问题,不在这里引申出去了).
那疑问又来了,如果count传分页大小比如100,那他是怎么获取到这个hash结构下所有的field的?
答案是redisTemplate帮我们封装好了。其实你调用以下代码的时候
Cursor cursor = rt.opsForHash().scan("key", ScanOptions.scanOptions().count(Integer.MAX_VALUE).match("*").build());
while(cursor.hasNext()){
cursor.next()
}
驱动第二次调用底层原生scan代码的方法是cursor.hasNext,当发现上一次底层原生scan返回的值已经遍及完的时候,他会再次执行scan方法去redis获取数据,而起始的游标Id就是上一次scan返回的游标值,直到遍历结束,这样就达到了分批遍历的目的