Redis

关注公众号 jb51net

关闭
首页 > 数据库 > Redis > Redis Scan 命令使用

Redis Scan 命令使用教程(高效遍历海量数据的方法)

作者:不想写bug的小滕

Scan 是 Redis 2.8 版本引入的迭代式遍历命令,主要用于遍历 Redis 中的键集合或集合类型(如 Hash、Set、Sorted Set)的元素,本文将从基础介绍、实现原理、实操方式到实践总结,全面讲解 Scan 命令的使用,感兴趣的朋友跟随小编一起看看吧

Redis 中 Scan 命令使用教程:高效遍历海量数据

在 Redis 中,当需要遍历所有键或指定模式的键时,传统的 KEYS 命令会因阻塞主线程、无法分页等问题,在海量数据场景下表现糟糕。而 Scan 命令凭借 “非阻塞”“分批遍历” 的特性,成为解决大规模数据遍历的最优方案。本文将从基础介绍、实现原理、实操方式到实践总结,全面讲解 Scan 命令的使用。

一、介绍

Scan 是 Redis 2.8 版本引入的迭代式遍历命令,主要用于遍历 Redis 中的键集合或集合类型(如 Hash、Set、Sorted Set)的元素,核心目标是解决传统遍历命令的性能问题。

1. 为什么需要 Scan?

传统的 KEYS 命令存在明显缺陷:

Scan 命令恰好弥补这些不足,具备以下核心特性:

2. 典型应用场景

二、使用原理

Scan 命令的核心是基于 “游标” 和 “哈希表遍历” 实现的,理解其底层原理能帮助更好地使用命令。

1. Redis 键空间的存储结构

Redis 的键空间(keyspace)底层基于哈希表存储,每个键通过哈希函数映射到哈希表的某个 “桶(bucket)” 中。Scan 命令本质是遍历哈希表的桶,并通过游标记录当前遍历到的桶位置。

2. 游标迭代机制

Scan 的遍历过程类似 “翻书”,游标就是 “页码”,具体流程如下:

3. 避免漏遍历与重复遍历的设计

由于 Redis 哈希表在扩容(rehash)时会重新分配桶的位置,Scan 通过以下机制保证遍历的准确性:

4. 计数参数(count)的作用

Scan 命令中的 count 参数用于指定 “每次遍历的桶数量”,而非 “返回的元素数量”:

三、使用方式

Scan 命令家族包括 SCAN(遍历键空间)、HSCAN(遍历 Hash)、SSCAN(遍历 Set)、ZSCAN(遍历 Sorted Set),核心用法类似,以下以最常用的 SCAN 为例讲解,其他命令用法可类比。

1. 基础语法

(1)SCAN 命令(遍历所有键)
 语法:SCAN cursor [MATCH pattern]  [COUNT count]  [TYPE type]
cursor:游标值(首次为 0,后续用上次返回的游标)
MATCH pattern:通配符匹配,筛选符合条件的键(可选)
COUNT count:每次遍历的桶数量(可选,默认 10)
TYPE type:按键类型筛选(如 string、hash、set,可选,Redis 6.0+ 支持)
(2)其他命令语法(类比)

2. 实操示例

(1)遍历所有键(无筛选)
# 首次遍历:游标 0,默认 count=10
127.0.0.1:6379> SCAN 0
1) "17"  # 下次遍历的游标
2) 1) "user:1001"
    2) "product:2003"
    3) "order:5001"
 # 本次返回 3 个键(少于 count=10,因部分桶无符合条件的键)
# 第二次遍历:使用上次返回的游标 17
127.0.0.1:6379> SCAN 17
1) "0"  # 游标为 0,遍历结束
2) 1) "user:1002"
   2) "temp:3001"
(2)按前缀筛选键(MATCH)
# 遍历所有以 "user:" 为前缀的键,count=20
127.0.0.1:6379> SCAN 0 MATCH user:* COUNT 20
1) "23"
2) 1) "user:1001"
    2) "user:1002"
    3) "user:1003"
# 继续遍历,直到游标返回 0
127.0.0.1:6379> SCAN 23 MATCH user:* COUNT 20
1) "0"
2) 1) "user:1004"
(3)按类型筛选键(TYPE,Redis 6.0+)
# 遍历所有 string 类型的键
127.0.0.1:6379> SCAN 0 TYPE string
1) "12"
2) 1) "user:1001"  # 假设该键是 string 类型
    2) "temp:3001"
(4)遍历 Hash 键(HSCAN)
# 先创建一个 Hash 键
127.0.0.1:6379> HMSET user:1001 name "Alice" age "25" city "Beijing"
OK
# 遍历该 Hash 的字段和值
127.0.0.1:6379> HSCAN user:1001 0
1) "0"  # 游标为 0,Hash 元素少,一次遍历完
2) 1) "name"
   2) "Alice"
  3) "age"
  4) "25"
  5) "city"
  6) "Beijing"

3. 代码示例(Golang)

以遍历所有 user: 前缀的键为例,使用 go-redis 客户端实现:

package main
import (
	"context"
	"fmt"
	"github.com/go-redis/redis/v8"
)
func main() {
	// 初始化 Redis 客户端
	client := redis.NewClient(&redis.Options{
		Addr:     "localhost:6379",
		Password: "",
		DB:       0,
	})
	defer client.Close()
	ctx := context.Background()
	// Scan 遍历所有 user: 前缀的键
	var cursor uint64 = 0  // 初始游标
	count := int64(20)     // 每次遍历的桶数量
	pattern := "user:*"    // 匹配模式
	fmt.Println("开始遍历 user: 前缀的键:")
	for {
		// 执行 Scan 命令
		result, err := client.Scan(ctx, cursor, pattern, count).Result()
		if err != nil {
			fmt.Printf("Scan 执行失败:%v\n", err)
			return
		}
		// 获取本次结果和下次游标
		cursor = result.Cursor
		keys := result.Keys
		// 处理本次获取的键
		for _, key := range keys {
			fmt.Printf("找到键:%s\n", key)
		}
		// 游标为 0,遍历结束
		if cursor == 0 {
			break
		}
	}
	fmt.Println("遍历完成")
}

4. 注意事项

四、总结

Scan 命令是 Redis 中处理海量数据遍历的核心工具,其核心优势可总结为:

在实际使用中,需注意以下关键要点:

总之,Scan 命令彻底解决了传统 KEYS 命令的性能痛点,是 Redis 运维和开发中处理海量数据的 “必备工具”,掌握其用法能显著提升大规模 Redis 集群的管理效率。

到此这篇关于Redis Scan 命令使用教程(高效遍历海量数据的方法)的文章就介绍到这了,更多相关Redis Scan 命令使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文