mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-11-04 00:10:25 +08:00
!25 优化redis在scan查询时当前游标没有数据的场景
Merge pull request !25 from yechuankai/master
This commit is contained in:
@@ -206,8 +206,31 @@ func (r *Redis) Scan(rc *ctx.ReqCtx) {
|
|||||||
mode := ri.Info.Mode
|
mode := ri.Info.Mode
|
||||||
if mode == "" || ri.Info.Mode == entity.RedisModeStandalone || mode == entity.RedisModeSentinel {
|
if mode == "" || ri.Info.Mode == entity.RedisModeStandalone || mode == entity.RedisModeSentinel {
|
||||||
redisAddr := ri.Cli.Options().Addr
|
redisAddr := ri.Cli.Options().Addr
|
||||||
keys, cursor := ri.Scan(form.Cursor[redisAddr], form.Match, form.Count)
|
//汇总所有的查询出来的键值
|
||||||
|
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
|
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
|
var keyInfoSplit []string
|
||||||
if len(keys) > 0 {
|
if len(keys) > 0 {
|
||||||
@@ -233,20 +256,40 @@ func (r *Redis) Scan(rc *ctx.ReqCtx) {
|
|||||||
}
|
}
|
||||||
} else if mode == entity.RedisModeCluster {
|
} else if mode == entity.RedisModeCluster {
|
||||||
var keys []string
|
var keys []string
|
||||||
|
//有通配符或空时使用scan,非模糊匹配直接匹配key
|
||||||
|
if form.Match == "" || strings.ContainsAny(form.Match, "*") {
|
||||||
mu := &sync.Mutex{}
|
mu := &sync.Mutex{}
|
||||||
// 遍历所有master节点,并执行scan命令,合并keys
|
// 遍历所有master节点,并执行scan命令,合并keys
|
||||||
ri.ClusterCli.ForEachMaster(ctx, func(ctx context.Context, client *redis.Client) error {
|
ri.ClusterCli.ForEachMaster(ctx, func(ctx context.Context, client *redis.Client) error {
|
||||||
redisAddr := client.Options().Addr
|
redisAddr := client.Options().Addr
|
||||||
ks, cursor, _ := client.Scan(ctx, form.Cursor[redisAddr], form.Match, form.Count).Result()
|
for {
|
||||||
|
cursorRes[redisAddr] = form.Cursor[redisAddr]
|
||||||
|
ks, cursor, _ := client.Scan(ctx, cursorRes[redisAddr], form.Match, form.Count).Result()
|
||||||
// 遍历节点的内部回调函数使用异步调用,如不加锁会导致集合并发错误
|
// 遍历节点的内部回调函数使用异步调用,如不加锁会导致集合并发错误
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
cursorRes[redisAddr] = cursor
|
cursorRes[redisAddr] = cursor
|
||||||
|
if len(ks) > 0 {
|
||||||
|
//返回了数据则追加总集合中
|
||||||
keys = append(keys, ks...)
|
keys = append(keys, ks...)
|
||||||
|
}
|
||||||
mu.Unlock()
|
mu.Unlock()
|
||||||
|
//匹配的数量满足用户需求退出
|
||||||
|
if int32(len(keys)) >= int32(form.Count) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
//匹配到最后退出
|
||||||
|
if cursor == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
} else {
|
||||||
|
//精确匹配
|
||||||
|
keys = append(keys, form.Match)
|
||||||
|
}
|
||||||
|
|
||||||
// 因为redis集群模式执行lua脚本key必须位于同一slot中,故单机获取的方式不适合
|
// 因为redis集群模式执行lua脚本key必须位于同一slot中,故单机获取的方式不适合
|
||||||
// 使用lua获取key的ttl以及类型,减少网络调用
|
// 使用lua获取key的ttl以及类型,减少网络调用
|
||||||
keyInfoLua := `local ttl = redis.call('ttl', KEYS[1]);
|
keyInfoLua := `local ttl = redis.call('ttl', KEYS[1]);
|
||||||
|
|||||||
Reference in New Issue
Block a user