亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

關于 Redigo 和并發的一些問題

關于 Redigo 和并發的一些問題

Go
肥皂起泡泡 2022-01-10 15:03:53
我已經閱讀了可以在此處找到的整個 Redigo 文檔。 https://godoc.org/github.com/garyburd/redigo/redis#pkg-variables這里的文檔明確指出連接不支持并發調用 Send()、Flush() 或 Receive() 方法。連接不支持并發調用寫入方法(發送、刷新)或并發調用讀取方法(接收)。連接確實允許并發讀取器和寫入器。然后它指出,由于 Do 方法可以是 Send()、Flush() 和 Receive() 的組合,我們不能同時使用 Do()(與)其他方法。由于 Do 方法結合了 Send、Flush 和 Receive 的功能,因此 Do 方法不能與其他方法同時調用。這是否意味著我們可以使用存儲在全局變量中的單個連接同時單獨使用 Do(),只要我們不將它與其他方法混合使用?例如像這樣:var (    // Redis Conn.    redisConn redis.Conn    // Redis PubSubConn wraps a Conn with convenience methods for subscribers.    redisPsc redis.PubSubConn)func redisInit() {    c, err := redis.Dial(config.RedisProtocol, config.RedisAddress)    if err != nil {        log.Fatal(err)    }    c.Do("AUTH", config.RedisPass)    redisConn = c    c, err = redis.Dial(config.RedisProtocol, config.RedisAddress)    if err != nil {        log.Fatal(err)    }    c.Do("AUTH", config.RedisPass)    redisPsc = redis.PubSubConn{c}    for {        switch v := redisPsc.Receive().(type) {        case redis.Message:            // fmt.Printf("%s: message: %s\n", v.Channel, v.Data)            socketHub.broadcast <- v.Data        case redis.Subscription:            // fmt.Printf("%s: %s %d\n", v.Channel, v.Kind, v.Count)        case error:            log.Println(v)        }    }}然后在一些 go 例程中調用 Do() 方法,如下所示:if _, err = redisConn.Do("PUBLISH", fmt.Sprintf("user:%d", fromId), message); err != nil {    log.Println(err)}if _, err = redisConn.Do("PUBLISH", fmt.Sprintf("user:%d", toId), message); err != nil {    log.Println(err)}然后后來文檔說,為了對 Redis 的完全并發訪問,我們需要創建一個池并從池中獲取連接,并在完成后釋放它們。這是否意味著我可以根據需要使用 Send()、Flush() 和 Receive(),只要我從池中獲得連接?所以換句話說,每次我需要在 go 例程中做某事時,我都必須從池中獲取新連接,而不是重用全局連接?這是否意味著只要我從池中獲得新連接,我就可以將 Do() 方法與例如 Send() 一起使用?所以總結一下:1) 只要不將 Do() 方法與 Send、Flush 和 Receive 方法一起使用,我可以同時使用它嗎?2) 只要我從池中獲得新的連接并在完成后釋放它,我就可以使用我想要的一切嗎?3) 如果 (1) 為真,這會影響性能嗎?在我提供的示例中,僅使用 Do() 方法同時使用全局連接,而不是與發送、刷新和接收混為一談,是否更好?
查看完整描述

1 回答

?
BIG陽

TA貢獻1859條經驗 獲得超6個贊

您可以有一個并發寫入器和一個并發讀取器。因為Do結合了讀取和寫入操作,您可以對Do. 換句話說,您不能Do同時調用。您不能將連接存儲在全局變量中并在Do不使用互斥鎖保護連接或使用其他機制來確保不超過一個并發調用者的情況下調用Do.


池支持并發訪問。poolGet方法返回的連接遵循上述并發規則。為了獲得對數據庫的完全并發訪問,應用程序應該在單個 goroutine 中執行以下操作: Get來自池的連接;在連接上執行 Redis 命令; Close將基礎資源返回到池的連接。


換成redisConn redis.Conn水池。在應用啟動時初始化池:


 var redisPool *redis.Pool


 ...


redisPool = &redis.Pool{

    MaxIdle: 3,  // adjust to your needs

    IdleTimeout: 240 * time.Second,  // adjust to your needs

    Dial: func () (redis.Conn, error) {

        c, err := redis.Dial(config.RedisProtocol, config.RedisAddress)

        if err != nil {

            return nil, err

        }

        if _, err := c.Do("AUTH", config.RedisPass); err != nil {

            c.Close()

            return nil, err

        }

        return c, err

    },

}

使用池發布到頻道:


 c := redisPool.Get()

 if _, err = c.Do("PUBLISH", fmt.Sprintf("user:%d", fromId), message); err != nil {

    log.Println(err)

 }

 if _, err = c.Do("PUBLISH", fmt.Sprintf("user:%d", toId), message); err != nil {

    log.Println(err)

 }

 c.Close()

不要在redisInit(). 不能保證redisInit()會在應用程序中的其他代碼使用池之前執行。


還要添加對訂閱或PSubscribe的調用。


查看完整回答
反對 回復 2022-01-10
  • 1 回答
  • 0 關注
  • 242 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號