Redis之Key遍历
Redis Key遍历一.Keys命令:当数据量较小时,可以使用Keys命令返回所有满足条件的Key集合.但是当数据量较大时,由于此命令通过遍历匹配key所以很容易阻塞Redis服务;另外由于不能使用limit命令,Keys命令会返回所有匹配数据,导致输出过多,所以生产环境一般不使用此命令.二.Scan命令:1.优点:scan命令的时间复杂度虽然也是O(N),但它是分次进行的,不会阻塞线程.sca
Redis Key遍历
一.Keys命令:
当数据量较小时,可以使用Keys命令返回所有满足条件的Key集合.但是当数据量较大时,由于此命令通过遍历匹配key所以很容易阻塞Redis服务;另外由于不能使用limit命令,Keys命令会返回所有匹配数据,导致输出过多,所以生产环境一般不使用此命令。
二.Scan命令:
1.优点:
scan命令的时间复杂度虽然也是O(N),但它是分次进行的,不会阻塞线程.
scan命令提供了limit参数,可以控制每次返回结果的最大条数.
2.缺点:
scan返回的数据可能重复(缩容导致的rehash可能重复扫描数据).
3.Redis Key存储结构:
Redis底层key的存储结构就是类似于HashMap那样数组+链表的结构.scan命令就是对这个一维数 组进行遍历。每次返回的游标值也都是这个数组的索引。limit参数表示遍历多少个数组的元素,将这些元素下挂接的符合条件的结果都返回。因为每个元素下挂接的链表大小不同,所以每次返回的结果数量也就不同。
4.scan遍历过程:
SCAN 命令的回复是一个包含两个元素的数组, 第一个数组元素是用于进行下一次迭代的新游标, 而第二个数组元素则是一个数组, 这个数组中包含了所有被迭代的元素.当游标返回值为0时,则表示遍历结束。
5.示例代码:
//批量查询需要统计的数据
Set<String> keys = redisTemplate.execute((RedisCallback<Set<String>>) connection -> {
Set<String> keysTmp = new HashSet<>();
Cursor<byte[]> cursor = connection
.scan(
new ScanOptions.ScanOptionsBuilder()
.match(RedisKeyConstant.GLOBAL_PREFIX_KEY + RedisKeyConstant.STAFF_ONLINE_INFO_PREFIX + "*")
//count参数在翻译的中文文档中说是返回的数量,但实际应该是每次遍历的哈希槽数量
.count(10000L)
.build());
while (cursor.hasNext()) {
keysTmp.add(new String(cursor.next()));
}
return keysTmp;
});
COUNT:
(1)COUNT参数让用户告知迭代命令, 在每次迭代中应该从数据集里返回多少元素
(2)COUNT 参数的默认值为 10 。
(3)在迭代一个足够大的、由哈希表实现的数据库、集合键、哈希键或者有序集合键时, 如果用户没有使用 MATCH 选项, 那么命令返回的元素数量通常和 COUNT 选项指定的一样, 或者比 COUNT 选项指定的数量稍多一些。
(4)在迭代一个编码为整数集合(intset,一个只由整数值构成的小集合)、 或者编码为压缩列表(ziplist,由不同值构成的一个小哈希或者一个小有序集合)时, 增量式迭代命令通常会无视 COUNT 选项指定的值, 在第一次迭代就将数据集包含的所有元素都返回给用户。
MATCH:
(1)和 KEYS 命令一样, 增量式迭代命令也可以通过提供一个 glob 风格的模式参数, 让命令只返回和给定模式相匹配的元素, 这一点可以通过在执行增量式迭代命令时, 通过给定 MATCH 参数来实现。
网上有很多地方说上述代码有问题,游标不会移动,需要像下面这么写:
但实际上只有使用Jedis时才需要这样,使用Redission作为客户端时,仍然可以按照之前的写法,游标可以正常移动,遍历所有数据.
三.参考:
深入理解Redis的scan命令
更多推荐
所有评论(0)