Redis SCAN 返回空列表,游标却还不是 0
空MATCH批次不代表结束,原样续传游标直至0。COUNT是工作提示,调整负载并处理动态集合、重复结果与最后批次。
使用 SCAN ... MATCH 遍历键时,某一轮返回空列表,游标却仍不是 0。这属于允许的结果,不能在空列表处提前结束遍历。只有服务端返回的游标为 0,这一轮完整迭代才结束。
MATCH 在扫描到元素之后过滤结果。匹配很少的前缀或模式时,当前扫描到的元素可能一个都不符合条件,下一轮却仍可能找到目标。SSCAN、HSCAN、ZSCAN 也需要按返回游标判断完成,结果内容的形状则各不相同。
下一次使用原样返回的游标
下面假设 client 是使用项目原连接配置的同步 redis-py 客户端,handle_key 是已有的键处理函数:
cursor = 0
while True:
cursor, keys = client.scan(cursor=cursor, match="record:*")
for key in keys:
handle_key(key)
if cursor == 0:
break
这里检查的是 redis-py 返回的整数游标。直接使用 Redis 协议或其他客户端时,要按它们的返回类型判断零值;不要把字符串 "0" 当布尔条件。游标应完整保留,不做浮点转换、加减或自行分页计算。
每次都从 0 开始,会反复启动新的迭代;空列表就退出,则可能漏掉后面的匹配键。最后一轮即使游标为 0,也仍应先处理它携带的结果。
COUNT 是工作量提示
COUNT 可以调整单次扫描的工作量,但不保证每次返回指定数量的匹配结果。增加它可能减少往返次数,也可能提高单次延迟和返回量,应结合实例负载和处理时间调整。
不要把 COUNT=1000 写成通用的正确值,也不要为了“每页必须有记录”无限加大 COUNT。整个迭代可以按需要调整 COUNT,只要下一次仍使用上一次的返回游标。
某些小型集合的内部紧凑编码可能一次返回全部元素,不能因此假设 COUNT 是分页上限。也不要用全库 KEYS 替代这个循环来避免空批次,那会改变服务器的负载特点。
完整遍历不等于快照或只处理一次
扫描期间集合可能变化,同一个元素也可能重复出现。handle_key 如果包含扣款、删除、递增或其他有副作用的操作,必须能安全处理重复,或者有经过设计的幂等记录。只读计数同样不能随手把返回数量当成某一时刻的准确总数。
持续无界增长的集合不保证这轮扫描能结束。任务需要时限时,应保留中止状态和处理进度,不能超时后报告整轮完成;恢复游标也不能把动态数据集变成快照。
键已找到但读取方法报 WRONGTYPE 时,应继续检查 扫描结果中的实际类型,不要把跳过空批次与类型过滤当成同一修复。
验收应覆盖中间空批次、最后一轮仍含结果、没有任何匹配项,以及重复结果的处理。确认循环按服务端游标结束且未漏掉已返回元素,再根据实际负载选择 COUNT。


