学习-4

2020-04-14  本文已影响0人  NotFoundW

BLPOP命令相关(BRPOP完全一样)

  1. List存在且长度大于0,返回key name和pop出来的元素
  2. List存在且为空时,如果直到timeout之后都还是为空,就返回nil
  3. List不存在时,将在timeout之后返回nil
  4. BLPOP用在一个不是List的数据上,将会返回error

Code

func Blpop(c redis.Conn) {
    // use BLPOP normally
    c.Do("RPUSH", "sun", "rise")
    results, err := redis.Strings(c.Do("BLPOP", "sun", 3))
    if err != nil {
        colorlog.Error(err.Error())
        return
    }
    fmt.Println("Popped element belongs to list:", results[0])
    fmt.Println("Popped element's value:", results[1])
    // If list is null, will return nil after timeout
    c.Do("RPOP", "sun")
    result, err := c.Do("BLPOP", "sun", 3)
    if err != nil {
        colorlog.Error(err.Error())
        return
    }
    if result == nil {
        fmt.Println("If list is null, will return nil after timeout.")
    }
    // If key doesn't exist, will return nil after timeout
    c.Do("DEL", "bug")
    result, err = c.Do("BLPOP", "bug", 3)
    if err != nil {
        colorlog.Error(err.Error())
        return
    }
    if result == nil {
        fmt.Println("If key doesn't exist, will return nil after timeout.")
    }
    //  If use BLPOP on a key that is not a list, will return error
    c.Do("SET", "kkk", 12)
    _, err = c.Do("BLPOP", "kkk", 3)
    if err != nil {
        fmt.Println("If use BLPOP on a key that is not a list, will return error:")
        colorlog.Error(err.Error())
    }
}

Output

➤ go run main.go
Popped element belongs to list: sun
Popped element's value: rise
If list is null, will return nil after timeout.
If key doesn't exist, will return nil after timeout.
If use BLPOP on a key that is not a list, will return error:
[ERR]2020/04/14 15:15:11 WRONGTYPE Operation against a key holding the wrong kind of value

  1. BLPOP是LPOP的block版本,尝试一下当List为空时,在BLPOP的timeout之前,向List添加一个元素。
    另外,BRPOPLPUSH的实验方法跟BLPOP几乎一样。

Code

func main() {
    c1, err := redis.Dial("tcp", "127.0.0.1:6379")
    if err != nil {
        fmt.Println("Connect to redis error", err)
        return
    }
    defer c1.Close()
    c2, err := redis.Dial("tcp", "127.0.0.1:6379")
    if err != nil {
        fmt.Println("Connect to redis error", err)
        return
    }
    defer c2.Close()
    c1.Do("RPOP", "sun")
    var wg sync.WaitGroup
    wg.Add(2)
    go func() {
        defer wg.Done()
        fmt.Println("BLPOP start:", time.Now().Format("2006/1/2 15:04:05"))
        results, err := redis.Strings(c1.Do("BLPOP", "sun", 20))
        fmt.Println("BLPOP end:", time.Now().Format("2006/1/2 15:04:05"))
        if err != nil {
            fmt.Println("BLPOP error")
            colorlog.Error(err.Error())
        }
        if results != nil {
            fmt.Println("Popped element belongs to list:", results[0])
            fmt.Println("Popped element's value:", results[1])
        } else {
            fmt.Println("Null list")
        }
    }()
    go func() {
        defer wg.Done()
        fmt.Println("Wait for 6 seconds:", time.Now().Format("2006/1/2 15:04:05"))
        time.Sleep(6 * time.Second)
        fmt.Println("RPUSH start:", time.Now().Format("2006/1/2 15:04:05"))
        rpushResult, err := redis.Int(c2.Do("RPUSH", "sun", "red"))
        if err != nil {
            fmt.Println("RPUSH error")
            colorlog.Error(err.Error())
        }
        fmt.Println("rpushResult:", rpushResult)
    }()
    wg.Wait()
}

Output

➤ go run main.go
Wait for 6 seconds: 2020/4/14 15:27:22
BLPOP start: 2020/4/14 15:27:22
RPUSH start: 2020/4/14 15:27:28
BLPOP end: 2020/4/14 15:27:28
Popped element belongs to list: sun
Popped element's value: red
rpushResult: 1

可以看到,BLPOP在22秒时开始,6秒之后,也就是28秒,RPUSH开始,也就在这一瞬间,List里有了元素,所以在28秒时BLPOP也就结束了,不会等到tiemout。

至于单独把这个阻塞的实验用另一个单独的函数来做,是因为需要两个redis.conn
在这个"github.com/garyburd/redigo/redis"包里,conn实现的Do()函数里,调用的DoWithTimeout()函数。
DoWithTimeout()函数里,conn是用了互斥锁的

func (c *conn) Do(cmd string, args ...interface{}) (interface{}, error) {
    return c.DoWithTimeout(c.readTimeout, cmd, args...)
}
func (c *conn) DoWithTimeout(readTimeout time.Duration, cmd string, args ...interface{}) (interface{}, error) {
    c.mu.Lock()
    pending := c.pending
    c.pending = 0
    c.mu.Unlock()
...
上一篇 下一篇

猜你喜欢

热点阅读