ServiceStack 5.7.0 IRedisClient ScanAllKeys按模式匹配未返回预期结果
StackService.Redis ScanAllKeys 无匹配结果排查方案
- 数据库编号不匹配
- IRedisClient 默认使用配置指定的默认数据库(通常为0),若目标key存储在其他数据库中,需先指定数据库编号:
cache.Db = 实际存储key的数据库编号;
- IRedisClient 默认使用配置指定的默认数据库(通常为0),若目标key存储在其他数据库中,需先指定数据库编号:
- 大小写敏感问题
- Redis SCAN 命令的glob模式匹配默认是大小写敏感的,若searchPattern的大小写与实际key不一致将无法匹配,建议统一key的存储大小写规范,或构造大小写兼容的匹配规则。
- 搜索词含特殊字符未转义
- 若searchPattern本身包含
*/?/[]/\等glob模式特殊字符,未转义会导致匹配规则失效,需先对特殊字符转义,参考转义方法如下:
private string EscapeRedisGlobPattern(string input) { if (string.IsNullOrEmpty(input)) return input; return input.Replace("\\", "\\\\") .Replace("*", "\\*") .Replace("?", "\\?") .Replace("[", "\\[") .Replace("]", "\\]"); } - 若searchPattern本身包含
- 分页参数异常
- 若
skip参数值大于实际匹配到的key总数量,会导致返回空列表,可先去掉Skip、Take逻辑直接查询全量匹配结果,确认存在匹配key后再添加分页逻辑。
- 若
- 部署模式兼容问题
- 若使用Redis集群/哨兵部署模式,旧版本StackService.Redis的ScanAllKeys仅会扫描当前连接节点的key,不会遍历所有集群节点,升级到最新稳定版即可解决该问题。
- 服务端验证
- 先通过Redis命令行执行
SCAN 0 MATCH *你的搜索内容* COUNT 1000,确认服务端确实存在匹配的key,排除key已过期删除的情况。
- 先通过Redis命令行执行
修正后参考代码
using var cache = BuildClient(); // 指定正确的数据库 cache.Db = 1; // 转义搜索词特殊字符 var escapedSearch = EscapeRedisGlobPattern(searchPattern); var matchPattern = $"*{escapedSearch}*"; // 先获取全量匹配结果再分页,避免Scan流式查询分页的潜在问题 var allMatchedKeys = cache.ScanAllKeys(matchPattern).ToList(); cacheKeyList = allMatchedKeys.Skip(skip).Take(take).ToList();
内容的提问来源于stack exchange,提问作者Andrew M
相关产品推荐
相关产品推荐

