所有托管服务节省 15%

测试技能,享折扣

使用代码: Skills 开始使用
China
Linux 专用服务器

在Linux上使用Redis扫描命令:完整指南

Redis 是一个高性能、开源、内存中数据结构存储,广泛用作键值数据库、缓存和消息代理。其最强大的功能之一——尽管经常被低估——是扫描命令,它允许你增量地遍历大型数据集,而不会阻止服务器或降低性能。

如果你在基于 Linux 的服务器上运行 Redis,掌握扫描命令对于构建可扩展的、生产就绪的应用程序至关重要。与危险的 KEYS 命令不同,后者在单个阻塞操作中检索所有匹配的键,扫描命令以小的、可管理的批次返回数据——使其成为处理大量数据的任何环境中的正确工具。

在这份综合指南中,你将学到如何在 Linux 上的 Redis 中使用 SCANSSCANHSCANZSCAN,包括真实世界的示例、shell 脚本和生产部署的最佳实践。

Redis Scan 命令是什么?

Redis scan 命令提供了一种基于游标的非阻塞机制,用于迭代遍历键、集合、哈希和有序集合。每次调用都会返回一个小的元素子集以及一个游标值,您可以使用该游标值在后续调用中继续迭代。当游标返回到 0,表示已遍历完整个数据集。

这种方法从根本上比 KEYS 更安全、更高效,后者会阻塞整个 Redis 服务器直到扫描完成——这在拥有数百万个键的生产环境中是一个严重问题。

四个核心 Scan 命令

命令用途
SCAN迭代遍历整个键空间中的键
SSCAN迭代遍历集合中的元素
HSCAN迭代遍历哈希中的字段和值
ZSCAN迭代遍历有序集合中的成员和分数

扫描命令的基本语法

所有四个扫描命令共享一致的语法结构:

SCAN cursor [MATCH pattern] [COUNT count]
SSCAN key cursor [MATCH pattern] [COUNT count]
HSCAN key cursor [MATCH pattern] [COUNT count]
ZSCAN key cursor [MATCH pattern] [COUNT count]

参数说明

  • cursor — 表示迭代中当前位置的整数。始终以 0 开始新的扫描。Redis 在每个响应中返回一个新的游标;在下一次调用中使用它来继续。
  • MATCH pattern *(可选)* — 使用 glob 风格的模式匹配过滤结果(例如 user:**session*)。注意:过滤发生在检索*之后*,因此低密度匹配可能需要多次迭代。
  • COUNT count *(可选)* — 向 Redis 建议每次迭代返回多少个元素的提示。这不是硬限制;Redis 可能返回更多或更少。默认值是 10

在 Linux 上安装 Redis

在使用 scan 命令之前,您需要在 Linux 服务器上安装并运行 Redis。无论您是在高流量生产环境还是开发机器上,安装过程都很简单。

> 提示:对于需要大规模 Redis 的生产工作负载,请考虑在 VPS Hosting 计划或 Dedicated Server 上部署,以确保您拥有 Redis 所需的内存、CPU 和 I/O 资源。

在 Debian/Ubuntu 上安装 Redis

sudo apt update
sudo apt install redis-server -y

在 CentOS/RHEL 上安装 Redis

sudo yum install redis -y

启动 Redis 服务

sudo systemctl start redis
sudo systemctl enable redis

验证安装

sudo systemctl status redis

您应该在输出中看到 active (running)。现在连接到 Redis CLI:

redis-cli

进入 CLI 后,测试连接:

127.0.0.1:6379> PING
PONG

您已准备好开始使用 scan 命令。

使用 SCAN 命令

SCAN 命令遍历 Redis 键空间中的所有键。它是生产环境中 KEYS 命令的通用替代品。

示例 1:基本 SCAN

要开始扫描数据库中的所有键,请从游标 0 开始:

SCAN 0

示例输出:

1) "14"
2) 1) "session:abc123"
   2) "user:1001"
   3) "product:55"

第一个元素(14)是下一个游标。在下一次 SCAN 调用中使用它。当返回的游标为 0 时,完整的迭代已完成。

示例 2:使用 MATCH 过滤键

要检索仅匹配特定模式的键 — 例如,所有以 user: 为前缀的键:

SCAN 0 MATCH user:*

这仅返回名称以 user: 开头的键。继续迭代直到游标返回 0,以确保您已扫描整个键空间。

示例 3:使用 COUNT 控制批大小

要建议 Redis 每次迭代返回大约 100 个键:

SCAN 0 COUNT 100

记住:COUNT 是一个*提示*,不是保证。根据内部数据结构,Redis 可能返回略多或略少的结果。

示例 4:使用 Shell 脚本进行完整键空间迭代

在实际场景中,您需要以编程方式循环遍历整个键空间。以下是一个生产就绪的 Bash 脚本,用于迭代所有匹配模式的键:

#!/bin/bash

cursor=0
echo "Starting full keyspace scan..."

while true; do
    # Execute SCAN and capture the result
    result=$(redis-cli SCAN $cursor MATCH user:* COUNT 100)

    # Extract the new cursor (first line of output)
    cursor=$(echo "$result" | head -n 1)

    # Extract and display the keys (remaining lines)
    keys=$(echo "$result" | tail -n +2)
    echo "Keys found:"
    echo "$keys"

    # Break the loop when cursor returns to 0
    if [[ "$cursor" == "0" ]]; then
        echo "Scan complete."
        break
    fi
done

要运行此脚本:

chmod +x scan_keys.sh
./scan_keys.sh

使用 SSCAN 命令

SSCAN 用于增量迭代遍历 Redis Set 的成员。它遵循与 SCAN 相同的基于游标的模式。

步骤 1:创建 Set 并添加成员

SADD myset "apple"
SADD myset "banana"
SADD myset "cherry"
SADD myset "date"
SADD myset "elderberry"
SADD myset "mango"
SADD myset "mango:tropical"
SADD myset "mango:dried"

步骤 2:基本 SSCAN

从游标 0 开始扫描 myset 中的所有元素:

SSCAN myset 0

步骤 3:使用 MATCH 过滤元素

仅检索与模式 mango:* 匹配的元素:

SSCAN myset 0 MATCH mango:*

步骤 4:使用 Shell 脚本迭代 Set

#!/bin/bash

cursor=0
echo "Scanning through myset:"

while true; do
    # Scan the set
    result=$(redis-cli SSCAN myset $cursor COUNT 10)

    # Update cursor
    cursor=$(echo "$result" | head -n 1)

    # Print elements returned
    elements=$(echo "$result" | tail -n +2)
    echo "Elements: $elements"

    # Stop when cursor returns to 0
    if [[ "$cursor" == "0" ]]; then
        echo "Set scan complete."
        break
    fi
done

保存为 scan_myset.sh,使其可执行,然后运行:

chmod +x scan_myset.sh
./scan_myset.sh

使用 HSCAN 命令

HSCAN 遍历 Redis Hash 的字段和值。当 Hash 包含数百或数千个字段,且需要处理它们而不一次性将所有内容加载到内存中时,这特别有用。

步骤 1:创建 Hash 并添加字段

HSET myhash name "John Doe"
HSET myhash age "30"
HSET myhash occupation "Software Developer"
HSET myhash city "San Francisco"
HSET myhash country "USA"
HSET myhash email "john@example.com"

步骤 2:基本 HSCAN

HSCAN myhash 0

示例输出:

1) "0"
2) 1) "name"
   2) "John Doe"
   3) "age"
   4) "30"
   5) "occupation"
   6) "Software Developer"
   ...

结果以交替的字段-值对形式返回。

步骤 3:使用 MATCH 过滤 Hash 字段

要仅检索名称包含 "city" 或匹配某个模式的字段:

HSCAN myhash 0 MATCH *city*

步骤 4:使用 Shell 脚本遍历 Hash

#!/bin/bash

cursor=0
echo "Scanning hash: myhash"

while true; do
    result=$(redis-cli HSCAN myhash $cursor COUNT 10)
    cursor=$(echo "$result" | head -n 1)
    fields=$(echo "$result" | tail -n +2)

    echo "Fields and values:"
    echo "$fields"

    if [[ "$cursor" == "0" ]]; then
        echo "Hash scan complete."
        break
    fi
done

使用 ZSCAN 命令

ZSCAN 遍历 Redis 有序集合的成员和分数。有序集合通常用于排行榜、优先级队列和时间序列数据——所有这些场景都需要高效地扫描大型集合。

步骤 1:创建有序集合并添加成员

ZADD mysortedset 1 "apple"
ZADD mysortedset 2 "banana"
ZADD mysortedset 3 "cherry"
ZADD mysortedset 4 "date"
ZADD mysortedset 5 "elderberry"

步骤 2:基本 ZSCAN

ZSCAN mysortedset 0

示例输出:

1) "0"
2) 1) "apple"
   2) "1"
   3) "banana"
   4) "2"
   5) "cherry"
   6) "3"

结果以交替的成员-分数对形式返回。

步骤 3:使用 MATCH 过滤成员

查找所有名称包含字母 "e" 的成员:

ZSCAN mysortedset 0 MATCH *e*

步骤 4:完整有序集合迭代脚本

#!/bin/bash

cursor=0
echo "Scanning sorted set: mysortedset"

while true; do
    result=$(redis-cli ZSCAN mysortedset $cursor COUNT 10)
    cursor=$(echo "$result" | head -n 1)
    members=$(echo "$result" | tail -n +2)

    echo "Members and scores:"
    echo "$members"

    if [[ "$cursor" == "0" ]]; then
        echo "Sorted set scan complete."
        break
    fi
done

扫描命令比较:快速参考

功能`SCAN``SSCAN``HSCAN``ZSCAN`
目标所有键集合成员哈希字段/值有序集合成员/分数
需要键名
支持 MATCH
支持 COUNT
输出格式键名成员字符串字段-值对成员-分数对
阻塞

在生产环境中使用 Redis Scan 命令的最佳实践

1. 在生产环境中始终使用 SCAN 而不是 KEYS

KEYS 命令是单线程的,会阻止所有其他 Redis 操作,直到完成。在拥有数百万个键的数据库上,这可能会导致严重的延迟峰值。永远不要在生产环境中使用 KEYSSCAN 是正确的、非阻塞的替代方案。

2. 根据数据集大小调整 COUNT

对于小数据集(< 1,000 个键),默认的 COUNT 10 就可以了。对于大数据集,将 COUNT 增加到 1001000 以减少往返次数,同时保持单个响应的可管理性。

3. 不要仅依赖 MATCH 来提高效率

MATCH 过滤器在 Redis 内部检索元素*之后*应用。如果你的模式只匹配一小部分键,Redis 仍然会在内部扫描完整的数据集。使用键命名约定(例如,一致的前缀)来使 MATCH 更有效。

4. 分批处理结果

永远不要在处理前将所有扫描结果累积在内存中。相反,在返回每个批次时立即处理它。这在内存受限的服务器上尤其重要。

5. 小心处理游标状态

始终将游标初始化为 0 并使用每个响应更新它。如果你的应用程序在扫描过程中崩溃,请从 0 重新开始。Redis 游标在服务器重新启动后不会持久化。

6. 首先在开发环境中彻底测试

在将基于扫描的逻辑部署到生产环境之前,请在具有代表性数据集的暂存环境中验证它。验证你的循环在游标返回到 0 时是否正确终止。

7. 保护你的 Redis 实例

Redis 不应在没有身份验证的情况下暴露在公网上。在你的 Redis 配置中使用 requirepass,绑定到 localhost 或私有网络接口,并使用防火墙规则限制访问。

为Redis选择正确的托管环境

Redis性能与可用RAM、CPU速度和网络延迟直接相关。选择正确的托管基础设施与编写高效的Redis命令同样重要。

  • 开发和小型项目:共享Web托管可能足以满足轻量级Redis使用,但始终首选专用Redis实例。
  • 不断增长的应用程序:VPS托管计划为您提供专用资源、root访问权限以及根据您的确切需求调整Redis配置(maxmemory、持久化设置等)的能力。
  • 高流量生产系统:专用服务器提供Redis可以利用的最大RAM和CPU资源,完全消除资源争用。
  • 使用Redis作为向量存储的AI和ML工作负载:GPU托管提供嵌入生成和相似性搜索以及Redis所需的计算能力。

对于还需要Web控制面板以便于管理的应用程序,带cPanel的VPS提供用户友好的界面以及完整的服务器控制。

故障排除常见问题

SCAN 重复返回 0 个元素

这通常意味着您的 MATCH 模式不匹配任何键,或者数据集为空。使用 DBSIZE 验证您的键命名以检查总键数。

127.0.0.1:6379> DBSIZE
(integer) 15420

游标从不返回到 0

这在稳定的 Redis 实例中不应该发生。如果确实发生了,请检查 Redis 版本兼容性(scan 命令需要 Redis 2.8+)或连接中断重置您的游标跟踪。

脚本无限期挂起

确保您的循环正确读取 redis-cli 输出第一行中的游标。总是产生非零游标的解析错误将导致无限循环。

结论

Redis scan 命令 — SCAN, SSCAN, HSCANZSCAN — 是任何在 Linux 上大规模使用 Redis 的开发者或系统管理员不可或缺的工具。它们提供了一种安全、非阻塞、基于游标的机制来遍历大型数据集,避免了与 KEYS 等命令相关的性能风险。

通过将 scan 命令与 MATCH 模式、适当的 COUNT 提示和结构良好的 shell 脚本相结合,您可以构建高效的数据处理管道,随着数据集大小的增加而优雅地扩展。遵循本指南中概述的最佳实践 — 特别是关于生产安全、内存管理和基础设施选择的实践 — 将确保您的 Redis 部署保持高性能和可靠性。

有关最新的命令选项和高级配置详情,请始终查阅官方 Redis 文档。当您准备好在生产级 Linux 环境中部署 Redis 时,请探索 AlexHost 的 VPS 主机专用服务器,这些基础设施专为处理要求高、内存密集型工作负载而构建。