redis / go-redis

Redis Go client
https://redis.uptrace.dev
BSD 2-Clause "Simplified" License
20.17k stars 2.37k forks source link

[Optimization suggestions] Script.Run func #3186

Open ppanphper opened 1 week ago

ppanphper commented 1 week ago
func (s *Script) Run(ctx context.Context, c Scripter, keys []string, args ...interface{}) *Cmd {
    r := s.EvalSha(ctx, c, keys, args...)
    if HasErrorPrefix(r.Err(), "NOSCRIPT") {
        return s.Eval(ctx, c, keys, args...)
    }
    return r
}

like this:

func (s *Script) Run(ctx context.Context, c Scripter, keys []string, args ...interface{}) *Cmd {
        retryTimes := 1
Retry: 
    r := s.EvalSha(ctx, c, keys, args...)
    if HasErrorPrefix(r.Err(), "NOSCRIPT") {
            retryTimes--
        if retryTimes >= 0 {
            if sc := s.Load(ctx, c); sc.Err() != nil {
                return r
            }
            goto Retry
        }
    }
    return r
}
image

However, since each command uses a different connection, this function cannot be implemented. Is there any way to optimize it? This optimization can improve some performance in high-concurrency scenarios, or when the Lua script is larger.

The usage environment is in a cloud vendor, with multiple agents and multiple nodes.

ppanphper commented 1 week ago

Unless you use client.Conn() to get a sticky connection externally, and then use

func (s *Script) Run(ctx context.Context, c Scripter, keys []string, args ...interface{}) *Cmd {
        retryTimes := 1
Retry: 
    r := s.EvalSha(ctx, c, keys, args...)
    if HasErrorPrefix(r.Err(), "NOSCRIPT") {
            retryTimes--
        if retryTimes >= 0 {
            if sc := s.Load(ctx, c); sc.Err() != nil {
                return r
            }
            goto Retry
        }
    }
    return r
}
ppanphper commented 1 week ago

type UniversalClient interface { Conn(ctx context.Context) *Conn // Can you add this method? }