Redis 模式匹配:KEYS vs SCAN 及 Go 实战示例

简介: Redis支持通配符匹配(*、?、[])查找key,但`KEYS`命令会阻塞服务,严禁用于生产;推荐使用非阻塞的`SCAN`命令分批遍历,配合规范命名(如`user:1001:profile`)和合理COUNT值,确保线上稳定。

在使用 Redis 时,我们经常需要按某种命名规则查找一批 key,比如:

  • user:1001:profile
  • user:1002:profile
  • session:abc123
  • session:def456

此时就需要用到 Redis 的模式匹配(Pattern Matching)功能。Redis 提供了两个关键命令:KEYSSCAN。它们都能匹配 key,但使用场景和风险差异巨大。


🔍 1. 通配符匹配规则

Redis 支持以下通配符:

模式 含义 示例匹配(pattern = "user:*"
* 匹配任意数量字符(含 0) user:1, user:100:info, user:
? 匹配单个字符 user:a?user:a1, user:ab ✅;user:abc
[abc] 匹配括号中任一字符 log:[123]log:1, log:2
[a-z] 匹配区间内任一字符 temp:[a-c]temp:a, temp:c

💡 实际开发建议:统一 key 命名规范,比如 namespace:id:field,让匹配更可靠。


⚠️ 2. KEYS 命令:快但危险!

KEYS user:*
  • ✅ 简单直接:一次性返回所有匹配 key
  • 阻塞 Redis 单线程!大数据量时可能导致服务卡顿甚至超时
  • 🚫 严禁在生产环境使用(除非你 100% 确认 key 总数极少)

✅ Go 示例(仅限开发/调试)

package main

import (
    "context"
    "fmt"
    "github.com/redis/go-redis/v9"
)

func main() {
   
    rdb := redis.NewClient(&redis.Options{
   
        Addr: "localhost:6379",
    })

    ctx := context.Background()
    keys, err := rdb.Keys(ctx, "user:*").Result()
    if err != nil {
   
        panic(err)
    }

    fmt.Println("Found keys:", keys)
    // Output: [user:1001:profile user:1002:profile]
}

📌 注意:Keys()KEYS 命令的封装,切勿用于线上


✅ 3. SCAN 命令:安全、分批、推荐!

SCAN 0 MATCH user:* COUNT 10
→ 返回 [cursor, [key1, key2, ...]]
  • 非阻塞:每次只查一小批,不影响线上服务
  • 游标迭代:直到 cursor 回到 0 表示结束
  • ✅ 完美适配生产环境大规模 key 遍历

Go 实战:安全遍历所有匹配 key

package main

import (
    "context"
    "fmt"
    "github.com/redis/go-redis/v9"
)

func scanKeys(ctx context.Context, rdb *redis.Client, pattern string, count int64) ([]string, error) {
   
    var keys []string
    var cursor uint64 = 0

    for {
   
        var err error
        var scanned []string
        scanned, cursor, err = rdb.Scan(ctx, cursor, pattern, count).Result()
        if err != nil {
   
            return nil, err
        }

        keys = append(keys, scanned...)

        // cursor == 0 表示迭代结束
        if cursor == 0 {
   
            break
        }
    }

    return keys, nil
}

func main() {
   
    rdb := redis.NewClient(&redis.Options{
   
        Addr: "localhost:6379",
    })
    ctx := context.Background()

    keys, err := scanKeys(ctx, rdb, "user:*", 10) // 每次最多查 10 个
    if err != nil {
   
        panic(err)
    }

    fmt.Println("Scanned keys:", keys)
    // Output: [user:1001:profile user:1002:profile]
}

⚙️ 参数说明:

  • cursor: 初始为 0,后续用上一次返回的 cursor
  • pattern: "user:*", "session:*"
  • count: 建议值(非精确),如 10/100。太小效率低,太大影响性能。

✅ 即使 Redis 有百万 key,SCAN 也能零感知完成遍历。


🛠️ 4. 最佳实践总结

项目 建议
✅ 生产环境 只用 SCAN,禁用 KEYS
✅ 命名规范 使用层级命名{type}:{id}:{field}(如 order:20251203001:status
✅ 性能调优 COUNT 初始可设 100;若响应慢,调低至 10~50
✅ 防误用 代码审查时 grep "KEYS",或通过 Redis 配置禁用:rename-command KEYS ""

🔚 结语

  • 想快速查几个 key?👉 KEYS仅本地/测试
  • 想安全遍历海量 key?👉 SCAN + Go 循环(生产唯一选择

掌握这个模式,能帮你避免 Redis 线上事故,写出更健壮的缓存层代码!


相关文章
|
人工智能 开发者
文章和 PPT 配图有救了!SVG 绘图专家智能体大揭秘
本文分享如何使用 DeepSeek-V3-0324 和 Claude 3.5 或 3.7 绘制出高质量的图片,可以作为文章配图也可以为 PPT 配图,效率成倍增长。文章还介绍了原型图绘制、图片重绘修改和彩色报纸风的进阶案例。希望本文提供的技巧对大家有帮助,大家也可以修改提示词定制自己喜欢的风格。
1631 13
|
5月前
|
缓存 监控 Java
Java 性能天花板:JIT 即时编译、分层编译与代码缓存深度调优指南
JIT即时编译是Java性能优化的核心机制,本文深入解析了JIT的工作原理与优化技术。文章首先介绍了Java的双重执行模型,对比了解释执行与JIT编译的差异。重点讲解了分层编译机制,包括5个编译层级及其流转规则。针对代码缓存管理,详细说明了分段式架构和监控方法。通过JMH基准测试展示了方法内联、逃逸分析等核心优化技术的实际效果,其中方法内联性能提升10-20倍,逃逸分析优化可达50倍。最后提供了线上常见JIT问题的排查方案,强调JDK17默认参数已优化大部分场景,调优需基于监控数据。
620 1
|
6月前
|
Kubernetes 应用服务中间件 nginx
最全的kubectl命令用法
本文系统讲解kubectl命令行工具:详解所有子命令(创建、查询、部署、调试等)、API资源列表、自动补全配置,并通过大量实操示例(如创建/查看/编辑/删除资源、扩缩容、回滚、标签管理等)助你快速掌握Kubernetes集群管理核心技能。(239字)
1042 143
|
6月前
|
安全 Go API
Go1.26新提案:errors.AsType —— 更安全、更简洁的错误类型检查方案
Go 1.26 新增 `errors.AsType[E error](err error) (E, bool)`,以泛型替代反射实现错误类型匹配。相比传统 `errors.As`,它无需预声明变量、避免指针误用、杜绝运行时 panic,支持 `if x, ok := AsType[T](err); ok` 短声明,作用域更安全,性能更高,代码更简洁清晰。(239字)
317 6
|
6月前
|
安全 Java API
Spring Boot 4 黑科技: 编译期消灭空指针异常!
NPE被称为“幽灵bug”因Java类型系统无法区分可空/非空类型,导致运行时崩溃。Spring Boot 4引入JSpecify标准:`@NullMarked`设包级非空默认,`@Nullable`显式标注例外,配合NullAway在编译期拦截空指针,让NPE从线上事故变为本地错误。(239字)
376 2
|
6月前
|
JSON 编解码 Go
Go 新一代网络请求resty!,比net/http好用10倍
resty 是 Go 语言高性能 HTTP 客户端,比 net/http 简洁 10 倍、比 axios 更 Go 风。零依赖、支持链式调用、自动 JSON 编解码、重试/拦截器/Mock/文件上传下载等,Go 1.18+ 可用,一行代码发起请求,大幅提升开发效率与可维护性。(239 字)
719 1
|
6月前
|
前端开发 Java API
Python MyBoot入门:像写SpringBoot 一样写python
MyBoot是Python版Spring Boot,主打“约定优于配置”,支持自动装配、依赖注入与类Spring注解(如@RestController/@service)。内置HTTP/2、Swagger、健康检查等,单文件启动,30秒初始化项目,零样板配置,专为快速开发企业级API而生。
403 2
|
6月前
|
安全 Java API
SpringBoot 4 黑科技:接口组 ——10 行代码管理 100+ API 客户端
Spring 7 新增「HTTP接口组」特性,告别重复`@Bean`声明与手动配置。通过`@ImportHttpServices`按业务分组(如github、stackoverflow),支持统一超时、Token、baseUrl等配置,Java代码+YAML双驱动,大幅降低配置冗余,提升可维护性与开发效率。(239字)
483 3
|
6月前
|
安全 IDE Java
IDEA 2025.3新特性: 让 Java 空安全落地更丝滑
JSpecify 1.0正式落地,Spring Boot 4、JUnit 6等已默认支持!本文详解IDEA 2025.3如何与NullAway协同实现真正一致的空安全:智能降噪、统一suppress、平滑迁移方案一应俱全——空安全,从此不止于注解。
477 2