学习-4

作者: NotFoundW | 来源:发表于2020-04-14 15:29 被阅读0次

    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()
    ...
    

    相关文章

      网友评论

          本文标题:学习-4

          本文链接:https://www.haomeiwen.com/subject/qactvhtx.html