redis / go-redis

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

bug: block client pool when use monitor command #2848

Closed rfyiamcool closed 8 months ago

rfyiamcool commented 8 months ago

summay

block client pool when use monitor command.

image

Test

redis-server version is 7.2.1

docker run -itd --rm --name redis-test -p 6379:6379 redis

go-redis version is 9.3.1.

package main

import (
    "context"
    "fmt"
    "time"

    "github.com/redis/go-redis/v9"
)

func main() {
    ctx := context.Background()

    rdb := redis.NewClient(&redis.Options{
        Addr: ":6379",
    })
    _ = rdb.FlushDB(ctx).Err()

    ress := make(chan string, 10)

    mn := rdb.Monitor(ctx, ress)
    mn.Start()

    go func() {
        // wait
        time.Sleep(3 * time.Second)

        for i := 0; i < 5; i++ {
            fmt.Println("start set kv", i)
            rdb.Set(ctx, "kv", time.Now(), 0)  //  πŸ˜…  block point πŸ˜…
            fmt.Println("done set kv", i)
        }
    }()

    lst := []string{}
    for i := 0; i < 5; i++ {
        s := <-ress
        fmt.Println(">>>>>  ress get", s)
        lst = append(lst, s)
    }
    mn.Stop()

    fmt.Println(lst)
}

function stack

goroutine 8 [semacquire]:
runtime.gopark(0x0?, 0x0?, 0x60?, 0x60?, 0x48a157e8?)
    /usr/local/go/src/runtime/proc.go:398 +0xce fp=0xc00005a998 sp=0xc00005a978 pc=0x103738e
runtime.goparkunlock(...)
    /usr/local/go/src/runtime/proc.go:404
runtime.semacquire1(0xc000136008, 0x1e?, 0x1, 0x0, 0xb0?)
    /usr/local/go/src/runtime/sema.go:160 +0x218 fp=0xc00005aa00 sp=0xc00005a998 pc=0x1047d38
internal/poll.runtime_Semacquire(0x1019716?)
    /usr/local/go/src/runtime/sema.go:67 +0x25 fp=0xc00005aa38 sp=0xc00005aa00 pc=0x1061da5
internal/poll.(*fdMutex).rwlock(0xc000136000, 0x20?)
    /usr/local/go/src/internal/poll/fd_mutex.go:154 +0xc5 fp=0xc00005aa78 sp=0xc00005aa38 pc=0x10a3a85
internal/poll.(*FD).readLock(...)
    /usr/local/go/src/internal/poll/fd_mutex.go:221
internal/poll.(*FD).RawRead(0xc000136000, 0xc000184020)
    /usr/local/go/src/internal/poll/fd_unix.go:697 +0x3a fp=0xc00005aad8 sp=0xc00005aa78 pc=0x10a525a
net.(*rawConn).Read(0xc00018a000, 0x12b98f0?)
    /usr/local/go/src/net/rawconn.go:44 +0x36 fp=0xc00005ab10 sp=0xc00005aad8 pc=0x10e0836

πŸ˜… block πŸ˜…

github.com/redis/go-redis/v9/internal/pool.connCheck({0x12b98f0, 0xc00004e058})
    /Users/ruifengyun/github/rfyiamcool/go-redis/internal/pool/conn_check.go:30 +0xd2 fp=0xc00005ab60 sp=0xc00005ab10 pc=0x10fff32
github.com/redis/go-redis/v9/internal/pool.(*ConnPool).isHealthyConn(0xc00012c000, 0xc0001000f0)
    /Users/ruifengyun/github/rfyiamcool/go-redis/internal/pool/pool.go:504 +0xce fp=0xc00005abd0 sp=0xc00005ab60 pc=0x1101dce
github.com/redis/go-redis/v9/internal/pool.(*ConnPool).Get(0xc00012c000, {0x12b8570, 0x14307a0})
    /Users/ruifengyun/github/rfyiamcool/go-redis/internal/pool/pool.go:274 +0x119 fp=0xc00005ac30 sp=0xc00005abd0 pc=0x1100f99
github.com/redis/go-redis/v9.(*baseClient)._getConn(0xc00006a100, {0x12b8570, 0x14307a0})
    /Users/ruifengyun/github/rfyiamcool/go-redis/redis.go:260 +0x32 fp=0xc00005ac88 sp=0xc00005ac30 pc=0x11c9652
github.com/redis/go-redis/v9.(*baseClient).getConn(0xc00006a100, {0x12b8570?, 0x14307a0?})
    /Users/ruifengyun/github/rfyiamcool/go-redis/redis.go:248 +0x65 fp=0xc00005acc0 sp=0xc00005ac88 pc=0x11c9585
github.com/redis/go-redis/v9.(*baseClient).withConn(0xc00006a100, {0x12b8570, 0x14307a0}, 0xc00005ad80)
    /Users/ruifengyun/github/rfyiamcool/go-redis/redis.go:371 +0x49 fp=0xc00005ad48 sp=0xc00005acc0 pc=0x11c9e09
github.com/redis/go-redis/v9.(*baseClient)._process(0xc00006a100, {0x12b8570, 0x14307a0}, {0x12b9bf8, 0xc000186000}, 0x48a15938?)
    /Users/ruifengyun/github/rfyiamcool/go-redis/redis.go:413 +0xe5 fp=0xc00005adb8 sp=0xc00005ad48 pc=0x11ca125
github.com/redis/go-redis/v9.(*baseClient).process(0xc00006a100, {0x12b8570, 0x14307a0}, {0x12b9bf8, 0xc000186000})
    /Users/ruifengyun/github/rfyiamcool/go-redis/redis.go:395 +0x73 fp=0xc00005ae00 sp=0xc00005adb8 pc=0x11c9fd3
github.com/redis/go-redis/v9.(*baseClient).process-fm({0x12b8570?, 0x14307a0?}, {0x12b9bf8?, 0xc000186000?})
    <autogenerated>:1 +0x45 fp=0xc00005ae38 sp=0xc00005ae00 pc=0x11d4d85
github.com/redis/go-redis/v9.(*hooksMixin).processHook(...)
    /Users/ruifengyun/github/rfyiamcool/go-redis/redis.go:185
github.com/redis/go-redis/v9.(*Client).Process(0xc00004cea8?, {0x12b8570?, 0x14307a0?}, {0x12b9bf8?, 0xc000186000})
    /Users/ruifengyun/github/rfyiamcool/go-redis/redis.go:670 +0x3d fp=0xc00005ae80 sp=0xc00005ae38 pc=0x11cb81d
github.com/redis/go-redis/v9.(*Client).Process-fm({0x12b8570?, 0x14307a0?}, {0x12b9bf8?, 0xc000186000?})
    <autogenerated>:1 +0x45 fp=0xc00005aeb8 sp=0xc00005ae80 pc=0x11d5285
github.com/redis/go-redis/v9.cmdable.Set(0xc000016190, {0x12b8570?, 0x14307a0}, {0x12555b0, 0x2}, {0x1240780?, 0xc000180000}, 0x0)
    /Users/ruifengyun/github/rfyiamcool/go-redis/string_commands.go:182 +0x2ef fp=0xc00005af10 sp=0xc00005aeb8 pc=0x11cc12f
main.main.func1()
    /Users/ruifengyun/github/rfyiamcool/go-redis/example/hll/main.go:30 +0x126 fp=0xc00005afe0 sp=0xc00005af10 pc=0x11d5966
runtime.goexit()
    /usr/local/go/src/runtime/asm_amd64.s:1650 +0x1 fp=0xc00005afe8 sp=0xc00005afe0 pc=0x10658a1
created by main.main in goroutine 1
    /Users/ruifengyun/github/rfyiamcool/go-redis/example/hll/main.go:24 +0xf7
rfyiamcool commented 8 months ago

@ofekshenawa

I tried to fix it, but I couldn't fix the problem. πŸ˜‚

lzakharov commented 8 months ago

Hi, @rfyiamcool!

This behaviour mentioned in the docs:

Using MONITOR blocks the connection to the server for itself. It needs a dedicated connection

So, you need to create separate client for monitoring. I also saw this use case in test: https://github.com/redis/go-redis/blob/master/monitor_test.go.