当前位置:首页 > 问答 > 正文

Redis里那个SHH命令到底是啥,怎么用来查找东西的?

在标准的、官方的Redis命令列表中,并不存在一个叫做“SHH”的命令,你可能是记错了命令的名称,或者是在某个特定上下文中看到了这个缩写,这很正常,Redis的命令都是缩写,很容易混淆,根据Redis官方文档,最接近“SHH”的、并且用于“查找东西”的命令,极有可能是 SCAN 命令,或者是它的具体数据类型的变体,HSCAN(用于Hash类型)、SSCAN(用于Set类型)和 ZSCAN(用于Sorted Set类型),一个更早的、但有不建议使用风险的命令是 KEYS,下面我就把这些命令当作你可能想找的“SHH”来详细解释。

(引用来源:Redis官方文档命令列表)

为什么会有SCAN和KEYS?它们解决什么问题?

想象一下,你的Redis数据库就像一个巨大的仓库,里面放了成千上万个钥匙(key),每个钥匙对应一件货物(value),现在你想找出所有标记为“用户资料:xxx”的货物,最直接的办法就是让仓库管理员(也就是Redis服务器)把整个仓库里所有钥匙的清单给你,你自己在清单上慢慢找,这个“把全部钥匙清单给你”的命令,KEYS 命令。

你输入 KEYS user:*,Redis就会把你仓库里所有以“user:”开头的钥匙一次性列出来。

Redis里那个SHH命令到底是啥,怎么用来查找东西的?

这种做法有个巨大的风险,如果你的仓库特别大,有几百上千万把钥匙,列出这个清单会非常耗时,而且这个过程会阻塞仓库的正常运营,在管理员翻箱倒柜给你列清单的这段时间里,其他想来存东西、取东西的人(也就是客户端的其他请求)全都得停下来等着,直到清单列完,这在生产环境中是绝对不能接受的,会导致服务卡顿甚至崩溃。

(引用来源:Redis官方文档对KEYS命令的警告说明)

为了解决 KEYS 命令的阻塞问题,Redis从2.8版本开始引入了 SCAN 命令家族。SCAN 命令的做法很聪明:它不像 KEYS 那样一次性给你所有结果,而是采用了一种“游标分批次”的方式,每次只给你一小部分钥匙。

SCAN命令怎么用?

Redis里那个SHH命令到底是啥,怎么用来查找东西的?

它的使用流程是这样的:

  1. 你第一次发出命令:SCAN 0 MATCH user:* COUNT 100
    • 0 是游标,从0开始表示第一次遍历。
    • MATCH user:* 是模式匹配,和 KEYS 命令后面跟的模式一样,用来筛选钥匙。
    • COUNT 100 是一个提示性的数量,告诉Redis你希望每次返回大概100个钥匙(注意,这只是个大概值,Redis可能会返回多一点或少一点)。
  2. Redis执行后,会返回两个东西:一个是下一个游标值(比如返回 12345),另一个是本次扫描到的钥匙列表(最多100个)。
  3. 你用拿到的下一个游标值,继续发出命令:SCAN 12345 MATCH user:* COUNT 100
  4. Redis再次返回一个新的游标值和又一批钥匙。
  5. 你不断地重复这个过程,直到Redis返回的下一个游标值是 0 为止,当返回的游标是0,就意味着整个仓库已经遍历完毕,所有匹配的钥匙都已经分批还给你了。

这个过程的好处是,每次扫描都只占用非常短的时间,不会长时间阻塞仓库运营,即使仓库里有海量钥匙,每次操作也只在“微观”上有一点点影响,不会导致服务卡顿,这就好比你不是让管理员停业盘点,而是让他每次路过货架时,顺手抄下10个符合要求的钥匙号给你,抄完继续干他的活儿,完全不耽误正事。

(引用来源:Redis官方文档对SCAN命令原理的阐述)

HSCAN, SSCAN, ZSCAN 是干嘛的?

Redis里那个SHH命令到底是啥,怎么用来查找东西的?

刚才说的 SCAN 是用于在整个仓库里查找“钥匙”的,但有时候,我们不仅要找钥匙,还想看看某个特定货物(value)里面装了什么,Redis的value有不同的类型,比如Hash(哈希)就像一个小抽屉,里面又装了多个字段和值;Set(集合)就像一袋子不重复的球。

HSCANSSCANZSCAN 就是用来“查找”这些具体货物内部内容的,它们的作用范围不是整个仓库,而是某一个特定的钥匙对应的value内部

  • HSCAN:假设你有一个钥匙叫 user:1001,它的类型是Hash,里面存储了这个用户的姓名、年龄、城市等字段,如果你想找出这个用户所有以“c”开头的字段(city”),你就可以用 HSCAN user:1001 MATCH c*,它也会像 SCAN 一样分批返回Hash内部的字段和值。
  • SSCAN:用于遍历Set类型value内部的所有元素。
  • ZSCAN:用于遍历Sorted Set(有序集合)类型value内部的成员和分值。

总结一下

所以你问的“SHH”命令,大概率是想问 SCAN 或其相关命令,它们核心作用是安全、非阻塞地查找东西

  • 想在整个数据库里查找符合模式的钥匙,用 SCAN
  • 想在某个Hash类型的value里查找其内部的字段,用 HSCAN
  • 想在某个Set类型的value里遍历其所有元素,用 SSCAN
  • 想在某个有序集合类型的value里遍历其成员,用 ZSCAN

而那个老式的、会引发问题的“一次性查找所有钥匙”的命令 KEYS,除非你是在一个数据量极小的测试环境里图省事,否则在生产环境中应该避免使用

希望这个解释能直接解答你的疑惑,Redis里没有“SHH”,但有更强大的“SCAN”家族来完成查找任务。