diff --git a/server/internal/redis/api/redis.go b/server/internal/redis/api/redis.go index 2905b48f..bf1f8bb7 100644 --- a/server/internal/redis/api/redis.go +++ b/server/internal/redis/api/redis.go @@ -206,8 +206,31 @@ func (r *Redis) Scan(rc *ctx.ReqCtx) { mode := ri.Info.Mode if mode == "" || ri.Info.Mode == entity.RedisModeStandalone || mode == entity.RedisModeSentinel { redisAddr := ri.Cli.Options().Addr - keys, cursor := ri.Scan(form.Cursor[redisAddr], form.Match, form.Count) - cursorRes[redisAddr] = cursor + //汇总所有的查询出来的键值 + var keys []string + //有通配符或空时使用scan,非模糊匹配直接匹配key + if form.Match == "" || strings.ContainsAny(form.Match, "*") { + cursorRes[redisAddr] = form.Cursor[redisAddr] + for { + ks, cursor := ri.Scan(cursorRes[redisAddr], form.Match, form.Count) + cursorRes[redisAddr] = cursor + if len(ks) > 0 { + //返回了数据则追加总集合中 + keys = append(keys, ks...) + } + //匹配的数量满足用户需求退出 + if int32(len(keys)) >= int32(form.Count) { + break + } + //匹配到最后退出 + if cursor == 0 { + break + } + } + } else { + //精确匹配 + keys = append(keys, form.Match) + } var keyInfoSplit []string if len(keys) > 0 { @@ -233,19 +256,39 @@ func (r *Redis) Scan(rc *ctx.ReqCtx) { } } else if mode == entity.RedisModeCluster { var keys []string + //有通配符或空时使用scan,非模糊匹配直接匹配key + if form.Match == "" || strings.ContainsAny(form.Match, "*") { + mu := &sync.Mutex{} + // 遍历所有master节点,并执行scan命令,合并keys + ri.ClusterCli.ForEachMaster(ctx, func(ctx context.Context, client *redis.Client) error { + redisAddr := client.Options().Addr + for { + cursorRes[redisAddr] = form.Cursor[redisAddr] + ks, cursor, _ := client.Scan(ctx, cursorRes[redisAddr], form.Match, form.Count).Result() + // 遍历节点的内部回调函数使用异步调用,如不加锁会导致集合并发错误 + mu.Lock() + cursorRes[redisAddr] = cursor + if len(ks) > 0 { + //返回了数据则追加总集合中 + keys = append(keys, ks...) + } + mu.Unlock() + //匹配的数量满足用户需求退出 + if int32(len(keys)) >= int32(form.Count) { + break + } + //匹配到最后退出 + if cursor == 0 { + break + } + } + return nil + }) - mu := &sync.Mutex{} - // 遍历所有master节点,并执行scan命令,合并keys - ri.ClusterCli.ForEachMaster(ctx, func(ctx context.Context, client *redis.Client) error { - redisAddr := client.Options().Addr - ks, cursor, _ := client.Scan(ctx, form.Cursor[redisAddr], form.Match, form.Count).Result() - // 遍历节点的内部回调函数使用异步调用,如不加锁会导致集合并发错误 - mu.Lock() - cursorRes[redisAddr] = cursor - keys = append(keys, ks...) - mu.Unlock() - return nil - }) + } else { + //精确匹配 + keys = append(keys, form.Match) + } // 因为redis集群模式执行lua脚本key必须位于同一slot中,故单机获取的方式不适合 // 使用lua获取key的ttl以及类型,减少网络调用