Skip to content

Commit

Permalink
优化redis在scan查询时当前游标没有数据的场景
Browse files Browse the repository at this point in the history
  • Loading branch information
叶传开 committed Dec 5, 2022
1 parent 3475c39 commit 195127a
Showing 1 changed file with 57 additions and 14 deletions.
71 changes: 57 additions & 14 deletions server/internal/redis/api/redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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以及类型,减少网络调用
Expand Down

0 comments on commit 195127a

Please sign in to comment.