Redis SCAN命令匹配模式是否支持OR(或)逻辑匹配?
Redis SCAN命令的匹配模式支持OR逻辑吗?
嘿,这个问题问得很实在!Redis的SCAN命令自带的match参数并不直接支持「或(OR)」逻辑,它只认简单的glob风格通配符匹配,具体规则是:
*匹配任意数量的任意字符(包括0个)?匹配单个任意字符[]匹配括号内的任意单个字符(比如[abc]只会匹配a、b、c中的某一个字符,不是你想的匹配整个字符串)
你尝试的00,[Paris] || [All+cities]*这种写法肯定不生效,因为Redis根本识别不了||这种OR运算符,而且[Paris]的作用和你预期的完全不一样——它不会匹配完整的"Paris"字符串,只会匹配P、a、r、i、s里的单个字符。
那针对你的需求——匹配包含Paris或All+cities的键,给你几个可行的解决方案:
方案1:分两次执行SCAN命令
最简单直接的方式就是分开扫描,第一次匹配含Paris的键,第二次匹配含All+cities的键,最后在客户端把两次结果合并去重就行。
示例命令:
# 第一次扫描:匹配00,Paris开头的所有键 SCAN 0 MATCH 00,Paris* # 第二次扫描:匹配00,All+cities开头的所有键 SCAN 0 MATCH 00,All+cities*
这种方法适合数据量不大的场景,唯一要注意的是:SCAN本身是弱一致性的,如果两次扫描期间有键新增/删除,可能会出现重复或遗漏,这属于正常现象。
方案2:客户端过滤结果
先执行一个宽泛的SCAN(比如MATCH 00,*,减少返回的数据量),拿到所有符合前缀的键之后,在客户端自己写逻辑判断键是否包含Paris或All+cities。
举个Python伪代码的例子:
import redis client = redis.Redis() cursor = 0 matched_keys = set() while True: cursor, keys = client.scan(cursor=cursor, match="00,*") # 遍历返回的键,过滤出符合条件的 for key in keys: if b"Paris" in key or b"All+cities" in key: matched_keys.add(key.decode()) # 游标为0时结束迭代 if cursor == 0: break print("匹配到的键:", matched_keys)
这种方法适合需要一次性处理的场景,但如果键的数量特别多,客户端过滤会带来一定的性能开销。
方案3:用Lua脚本在服务端过滤
如果想减少客户端和服务端的传输量,可以写一个Lua脚本,在Redis服务端完成SCAN迭代和条件判断,直接返回符合要求的键。
示例Lua脚本:
local cursor = ARGV[1] local target1 = ARGV[2] local target2 = ARGV[3] local matched = {} repeat -- 执行SCAN,匹配00开头的键 local scan_res = redis.call('SCAN', cursor, 'MATCH', '00,*') cursor = scan_res[1] -- 遍历当前批次的键,判断是否包含目标字符串 for _, key in ipairs(scan_res[2]) do if string.find(key, target1) or string.find(key, target2) then table.insert(matched, key) end end until cursor == '0' return matched
然后通过EVAL命令执行脚本:
EVAL "上面的Lua脚本内容" 0 0 "Paris" "All+cities"
这种方法效率更高,适合数据量较大的场景。
内容的提问来源于stack exchange,提问作者boxeus
相关产品推荐
相关产品推荐

