Redis SCAN 命令使用指南
SCAN 是 Redis 提供的一种非阻塞迭代器命令,用于逐步遍历 Redis 数据库中的键。相比于 KEYS 命令,SCAN 不会一次性加载所有键,因此对性能的影响较小,适合在生产环境中使用。
以下是关于 SCAN 的详细用法和相关知识点:
1. 基本语法
SCAN cursor \[MATCH pattern] \[COUNT count]
参数说明:
cursor:游标值,表示当前迭代的位置。
初始值为 0,表示从头开始扫描。
每次调用 SCAN 后,Redis 会返回一个新的游标值,用于下一次迭代。
当游标值返回 0 时,表示迭代完成。
MATCH pattern(可选):用于匹配键的模式。
支持通配符,例如 user:*
匹配以 user:
开头的所有键。
如果不指定 MATCH,则返回所有键。
COUNT count(可选):提示 Redis 每次迭代返回的键数量。
默认值为 10。
这只是一个提示值,实际返回的键数量可能会少于或略多于 count。
2. 返回值
SCAN 命令返回一个数组,包含两个元素:
新的游标值:用于下一次迭代。
如果返回 0,表示迭代完成。
键列表:当前迭代返回的键集合。
例如:
127.0.0.1:6379> SCAN 0 MATCH user:\* COUNT 10
1\) "15" # 新的游标值
2\) 1) "user:1"
  2\) "user:2"
  3\) "user:3"
3. 示例用法
示例 1:简单遍历所有键
\# 初始化游标为 0
127.0.0.1:6379> SCAN 0
1\) "17" # 新的游标值
2\) 1) "key1"
  2\) "key2"
  3\) "key3"
\# 使用上一次返回的游标值继续迭代
127.0.0.1:6379> SCAN 17
1\) "0" # 游标值为 0,表示迭代完成
2\) 1) "key4"
  2\) "key5"
示例 2:按模式匹配键
假设 Redis 中有以下键:
user:1, user:2, product:1, product:2
可以使用 MATCH 参数匹配特定前缀的键:
127.0.0.1:6379> SCAN 0 MATCH user:\*
1\) "0" # 游标值为 0,表示迭代完成
2\) 1) "user:1"
  2\) "user:2"
示例 3:调整每次返回的键数量
通过 COUNT 参数控制每次返回的键数量:
127.0.0.1:6379> SCAN 0 COUNT 5
1\) "20" # 新的游标值
2\) 1) "key1"
  2\) "key2"
  3\) "key3"
  4\) "key4"
  5\) "key5"
4. 与其他 SCAN 命令的关系
Redis 提供了多个与 SCAN 类似的命令,用于遍历不同的数据结构:
SCAN:遍历数据库中的键
SCAN 0 MATCH user:\* COUNT 10
SSCAN:遍历集合(Set)中的元素
SSCAN myset 0 COUNT 5
HSCAN:遍历哈希表(Hash)中的字段和值
HSCAN myhash 0 MATCH field:\* COUNT 5
ZSCAN:遍历有序集合(Sorted Set)中的成员和分数
ZSCAN myzset 0 COUNT 5
这些命令的语法和行为与 SCAN 类似,只是作用的对象不同。
5. 注意事项
非阻塞性:
SCAN 是非阻塞的,不会像 KEYS 命令那样阻塞 Redis 服务器。
因此,在生产环境中优先使用 SCAN 而不是 KEYS。
不保证顺序:
SCAN 返回的键顺序是不确定的,可能会重复或乱序。
如果需要有序结果,可以在客户端对返回的键进行排序。
COUNT 只是提示值:
COUNT 参数只是一个提示值,Redis 并不保证严格返回指定数量的键。
实际返回的键数量可能会受到数据分布和内部实现的影响。
游标的生命周期:
游标值只在当前迭代过程中有效。如果 Redis 数据集发生变化(如添加或删除键),游标的行为可能会受到影响。
6. 在 Spring Data Redis 中的使用
在 Spring Data Redis 中,SCAN 命令通常通过 RedisConnection 或 RedisTemplate 的 API 来调用。
示例代码:
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
public void scanKeys(RedisTemplate\<String, String> redisTemplate) {
  ScanOptions options = ScanOptions.scanOptions()
  .match("user:\*") // 匹配模式
  .count(10) // 每次返回的键数量
  .build();
  try (Cursor\<String> cursor = redisTemplate.getConnectionFactory()
  .getConnection()
  .scan(options)) {
  while (cursor.hasNext()) {
  String key = cursor.next();
  System.out.println("Found key: " + key);
  }
  } catch (Exception e) {
  e.printStackTrace();
  }
}
7. 总结
SCAN 是 Redis 提供的一种非阻塞迭代器命令,用于逐步遍历数据库中的键。
它支持 MATCH 和 COUNT 参数,可以灵活地控制匹配模式和每次返回的键数量。
在生产环境中,SCAN 是比 KEYS 更安全的选择,因为它不会阻塞 Redis 服务器。
在 Spring Data Redis 中,可以通过 RedisConnection 或 RedisTemplate 的 API 调用 SCAN 命令。