成人性生交大片免费看视频r_亚洲综合极品香蕉久久网_在线视频免费观看一区_亚洲精品亚洲人成人网在线播放_国产精品毛片av_久久久久国产精品www_亚洲国产一区二区三区在线播_日韩一区二区三区四区区区_亚洲精品国产无套在线观_国产免费www

主頁(yè) > 知識(shí)庫(kù) > 關(guān)于redigo中PubSub的一點(diǎn)小坑分析

關(guān)于redigo中PubSub的一點(diǎn)小坑分析

熱門(mén)標(biāo)簽:百度商家地圖標(biāo)注怎么做 地圖標(biāo)注如何即時(shí)生效 地圖標(biāo)注費(fèi)用 最簡(jiǎn)單的百度地圖標(biāo)注 太原營(yíng)銷(xiāo)外呼系統(tǒng) 玄武湖地圖標(biāo)注 西藏教育智能外呼系統(tǒng)價(jià)格 小紅書(shū)怎么地圖標(biāo)注店 竹間科技AI電銷(xiāo)機(jī)器人

前言

最近在用 golang 做一些 redis 相關(guān)的操作,選用了 redigo 這個(gè)第三方庫(kù)。然后在使用 Pub/Sub 的時(shí)候,卻發(fā)現(xiàn)了一個(gè)小坑……

Redis Client

首先,我們來(lái)初始化一個(gè)帶連接池的 Redis Client:

import (
	"github.com/gomodule/redigo/redis"
)

type RedisClient struct {
	pool *redis.Pool
}

func NewRedisClient(addr string, db int, passwd string) *RedisClient {
	pool := redis.Pool{
		MaxIdle:  10,
		IdleTimeout: 300 * time.Second,
		Dial: func() (redis.Conn, error) {
			c, err := redis.Dial("tcp", addr, redis.DialPassword(passwd), redis.DialDatabase(db))
			if err != nil {
				return nil, err
			}
			return c, nil
		},
		TestOnBorrow: func(c redis.Conn, t time.Time) error {
			if time.Since(t)  time.Minute {
				return nil
			}
			_, err := c.Do("PING")
			return err
		},
	}
	log.Printf("new redis pool at %s", addr)
	client := RedisClient{
		pool: pool,
	}
	return client
}

Publish

然后我們可以簡(jiǎn)單的實(shí)現(xiàn)一個(gè) publish 方法:

func (r *RedisClient) Publish(channel, message string) (int, error) {
	c := r.pool.Get()
	defer c.Close()
	n, err := redis.Int(c.Do("PUBLISH", channel, message))
	if err != nil {
		return 0, fmt.Errorf("redis publish %s %s, err: %v", channel, message, err)
	}
	return n, nil
}

Subscribe

接下來(lái)就是一個(gè)稍微復(fù)雜點(diǎn)的帶有心跳的 subscribe 方法:

func (r *RedisClient) Subscribe(ctx context.Context, consume ConsumeFunc, channel ...string) error {
	psc := redis.PubSubConn{Conn: r.pool.Get()}
	defer psc.Close()
	log.Printf("redis pubsub subscribe channel: %v", channel)
	if err := psc.Subscribe(redis.Args{}.AddFlat(channel)...); err != nil {
		return err
	}
	done := make(chan error, 1)
	// start a new goroutine to receive message
	go func() {
		for {
			switch msg := psc.Receive().(type) {
			case error:
				done - fmt.Errorf("redis pubsub receive err: %v", msg)
				return
			case redis.Message:
				if err := consume(msg); err != nil {
					done - err
					return
				}
			case redis.Subscription:
				if msg.Count == 0 {
					// all channels are unsubscribed
					done - nil
					return
				}
			}
		}
	}()

	// health check
	tick := time.NewTicker(time.Minute)
	defer tick.Stop()
	for {
		select {
		case -ctx.Done():
			if err := psc.Unsubscribe(); err != nil {
				return fmt.Errorf("redis pubsub unsubscribe err: %v", err)
			}
			return nil
		case err := -done:
			return err
		case -tick.C:
			if err := psc.Ping(""); err != nil {
				return err
			}
		}
	}

	return nil
}

最后,我們寫(xiě)一個(gè)簡(jiǎn)單地 main 函數(shù)來(lái)調(diào)用 publish subscribe:

func (r *RedisClient) Subscribe(ctx context.Context, consume ConsumeFunc, channel ...string) error {
	psc := redis.PubSubConn{Conn: r.pool.Get()}
	defer psc.Close()
	log.Printf("redis pubsub subscribe channel: %v", channel)
	if err := psc.Subscribe(redis.Args{}.AddFlat(channel)...); err != nil {
		return err
	}
	done := make(chan error, 1)
	// start a new goroutine to receive message
	go func() {
		for {
			switch msg := psc.Receive().(type) {
			case error:
				done - fmt.Errorf("redis pubsub receive err: %v", msg)
				return
			case redis.Message:
				if err := consume(msg); err != nil {
					done - err
					return
				}
			case redis.Subscription:
				if msg.Count == 0 {
					// all channels are unsubscribed
					done - nil
					return
				}
			}
		}
	}()

	// health check
	tick := time.NewTicker(time.Minute)
	defer tick.Stop()
	for {
		select {
		case -ctx.Done():
			if err := psc.Unsubscribe(); err != nil {
				return fmt.Errorf("redis pubsub unsubscribe err: %v", err)
			}
			return nil
		case err := -done:
			return err
		case -tick.C:
			if err := psc.Ping(""); err != nil {
				return err
			}
		}
	}

	return nil
}


咋一看之下,好像并沒(méi)有什么異常?然而,如果我們這時(shí)候去看 redis 的 tcp 連接,就可以發(fā)現(xiàn)一些貓膩:

$sudo netstat -antp | grep redis
tcp  0  0 0.0.0.0:6379   0.0.0.0:*    LISTEN  940/redis-server 0. 
tcp  0  0 172.16.8.128:6379  172.16.8.1:55010  ESTABLISHED 940/redis-server 0. 
tcp  0  0 172.16.8.128:6379  172.16.8.1:55015  ESTABLISHED 940/redis-server 0. 
tcp  0  0 172.16.8.128:6379  172.16.8.1:55009  ESTABLISHED 940/redis-server 0. 
tcp  0  0 172.16.8.128:6379  172.16.8.1:55005  ESTABLISHED 940/redis-server 0. 
tcp  0  0 172.16.8.128:6379  172.16.8.1:55012  ESTABLISHED 940/redis-server 0. 
tcp  0  0 172.16.8.128:6379  172.16.8.1:55011  ESTABLISHED 940/redis-server 0. 
tcp  0  0 172.16.8.128:6379  172.16.8.1:55013  ESTABLISHED 940/redis-server 0. 
tcp  0  0 172.16.8.128:6379  172.16.8.1:55007  ESTABLISHED 940/redis-server 0. 
tcp  0  0 172.16.8.128:6379  172.16.8.1:55006  ESTABLISHED 940/redis-server 0. 
tcp  0  0 172.16.8.128:6379  172.16.8.1:55014  ESTABLISHED 940/redis-server 0. 
tcp  0  0 172.16.8.128:6379  172.16.8.1:54972  ESTABLISHED 940/redis-server 0. 

竟然是每一次 subscribe 就新建了一個(gè)連接,而 connection pool 似乎沒(méi)有什么作用。

更進(jìn)一步地調(diào)試,我們發(fā)現(xiàn)在 defer psc.Close() 的時(shí)候就卡住了,也就是上面的 10 個(gè) goroutine 其實(shí)并沒(méi)有正常退出。

Concurrent

排查許久之后,終于定位到了問(wèn)題!引用 redigo 的說(shuō)明:

Connections support one concurrent caller to the Receive method and one concurrent caller to the Send and Flush methods. No other concurrency is supported including concurrent calls to the Do method.

For full concurrent access to Redis, use the thread-safe Pool to get, use and release a connection from within a goroutine. Connections returned from a Pool have the concurrency restrictions described in the previous paragraph.

也就是說(shuō),雖然一個(gè)連接可以在不同的 goroutine 并發(fā)調(diào)用 Receive() 和 Subscribe()(subscribe調(diào)用了send和flush) ,但是卻不能再有其他并發(fā)操作(比如 Close())。

其他相似的問(wèn)題還可以參考 issue

Fix

知道了上面的原因之后,我們稍微修改一下 defer psc.Close() 的位置即可解決問(wèn)題:

	// start a new goroutine to receive message
	go func() {
		// IMPORTANT!
		defer psc.Close()
		for {
			switch msg := psc.Receive().(type) {
			case error:

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

您可能感興趣的文章:
  • go實(shí)現(xiàn)redigo的簡(jiǎn)單操作

標(biāo)簽:廣東 香港 唐山 贛州 澳門(mén) 林芝 揚(yáng)州 景德鎮(zhèn)

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《關(guān)于redigo中PubSub的一點(diǎn)小坑分析》,本文關(guān)鍵詞  關(guān)于,redigo,中,PubSub,的,一點(diǎn),;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《關(guān)于redigo中PubSub的一點(diǎn)小坑分析》相關(guān)的同類(lèi)信息!
  • 本頁(yè)收集關(guān)于關(guān)于redigo中PubSub的一點(diǎn)小坑分析的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    网红女主播少妇精品视频| 91超薄肉色丝袜交足高跟凉鞋| 毛片毛片毛片毛| 青青国产精品| 国产精品蜜臀在线观看| 国产精品精品久久久| 欧美日韩在线播放| 又粗又大的机巴好爽欧美| 蜜臀av性久久久久蜜臀av麻豆| 久久sese| 艳妇臀荡乳欲伦亚洲一区| 成人激情视频在线播放| 日韩另类在线| 国产丝袜控视频在线观看| 高清久久久久久| 亚洲天堂精品视频| 制服诱惑一区| 狠狠综合久久av一区二区老牛| 欧美浪妇xxxx高跟鞋交| 日韩福利视频在线| 成人久久久精品国产乱码一区二区| 欧美不卡1区2区3区| 国语对白在线视频| 国产区视频在线| 手机在线观看你懂的| 日本视频一区二区不卡| 日韩精品成人在线观看| 91麻豆国产福利在线观看| 99热成人精品热久久66| 日韩午夜免费| 精品一区亚洲| 一区二区三区日韩精品视频| 精品国产亚洲av麻豆| 26uuu国产日韩综合| 久久久久久成人精品| 在线不卡一区| 欧洲精品一区二区三区在线观看| 这里有精品可以观看| 成人国产一区二区| 国产精品美女www| 成人av二区| 中文字幕亚洲免费| 中文字幕一区在线观看视频| 国产亚洲欧美日韩高清| 96sao精品视频在线观看| 国产欧美高清视频在线| 国产不卡精品视频| 中文无字幕一区二区三区| 91九色视频导航| 丁香天五香天堂综合| 精品卡1卡2卡三卡免费网站| 久久婷婷中文字幕| 亚洲精品日产| 理论片大全免费理伦片| 超碰97在线资源站| 亚洲精品一区二区毛豆| 精品成av人一区二区三区| 亚洲精品粉嫩美女一区| 欧美一区二区综合| 一区久久精品| 羞羞答答国产精品www一本| 国产极品美女在线| 欧美不卡1区2区3区| 亚洲视频天天射| 99视频精品全部免费在线视频| 日本韩国欧美三级| 性久久久久久| 精品成人私密视频| 一区二区三区在线高清| www.国产精品| 国产高清免费观看| 日本亚洲色大成网站www久久| 国产一二三四视频| 奇米一区二区三区av| 国产成人免费视频app| 最近免费观看高清韩国日本大全| 加勒比一区二区三区| 亚洲精品天堂在线| jk破处视频在线| 草色在线视频| 欧美综合77777色婷婷| 免费av网站观看| 免费在线观看的黄色网址| 91精品国产黑色紧身裤美女| 粉嫩aⅴ一区二区三区四区| 国语自产精品视频在线看抢先版结局| 一区二区三区欧美久久| 999热精品视频| 亚洲线精品一区二区三区八戒| 一级毛片在线播放| 日美av在线| 欧美激情一区二区三区| 最新国产精品自拍| 爱情岛亚洲播放路线| 欧美成人合集magnet| 国产免费一区二区三区四在线播放| 日日夜夜精品一区| 韩国三级电影一区二区| 黄色网页在线看| 午夜亚洲一区| 在线观看视频在线观看| 神马午夜在线观看| 天天爱天天色| www视频免费看| 国产精品国产三级国产有无不卡| 婷婷五月精品中文字幕| 天天做天天爱夜夜爽| 欧美日韩一区二区三区在线观看免| 国产中文在线观看| 色天天综合狠狠色| 亚洲av人无码激艳猛片服务器| 国产一区二区三区四| 超碰人人干人人| 久热99视频在线观看| 欧美一级视频免费在线观看| 韩国午夜理伦三级不卡影院| 在线天堂中文www视软件| 欧美图片欧美激情欧美精品| 日韩中文字幕91| 粉嫩一区二区三区国产精品| 欧美激情第3页| 欧美高清xxxx性| 欧美成人基地| 日韩精品一区中文字幕| 国产亚洲欧美色| 在线欧美一区| www.在线成人| 91亚洲精品一区二区乱码| 亚洲人成亚洲人成在线观看| 成人做爰69片免费看网站| 97久久综合精品久久久综合| 亚洲国产精品电影| 日本不卡的三区四区五区| 高潮白浆女日韩av免费看| 99精品国产高清一区二区| 337p亚洲精品色噜噜噜| 5858s免费视频成人| 精品欧美一区免费观看α√| 国产成人精品免高潮在线观看| 麻豆视频一区| 精品国产一区二区三区四区在线观看| 国产视频手机在线| 深夜精品寂寞黄网站在线观看| 中文字幕色视频| 国产伦子伦对白在线播放观看| 亚洲片在线观看| 欧美亚洲另类视频| 国产老熟妇精品观看| 国产精品探花在线观看| 成人精品福利视频| 深夜成人在线| 九色成人免费视频| 国内精品不卡在线| 欧美一区二区日韩一区二区| 黄网在线免费看| 久久精品夜夜夜夜久久| 午夜亚洲精品| 在线观看视频欧美| 国产原创一区二区三区| 大地资源高清在线视频观看| 欧美另类视频在线| 欧美偷拍综合| 无码国产精品一区二区高潮| 国产三级电影在线观看| 国产99久久九九精品无码免费| 欧美一级网站| 小说区图片区色综合区| 午夜精品在线播放| 精品伊人久久大线蕉色首页| 欧美精品一区二区高清在线观看| 欧美激情一二三| 日韩电影免费在线观看中文字幕| 东京久久高清| 在线观看亚洲大片短视频| 精品素人av| 日韩欧美在线观看一区二区三区| 福利片在线观看| 激情一区二区三区| 久久精品免费av| 国模gogo一区二区大胆私拍| 欧洲亚洲一区二区三区四区五区| 精品国产一区二区三区在线| 拍拍拍999自拍偷| 亚洲国产成人精品久久久国产成人一区| 欧美老人xxxx18| 在线观看欧美一区| 久久精品日产第一区二区三区精品版| 国产影视一区二区| 欧美天堂影院| 亚洲欧洲日本专区| 亚洲欧美另类久久久精品| 超碰在线观看91| 久久经典视频| 日本a级c片免费看三区| 亚洲国产成人在线播放| 国产午夜精品福利视频| 91美女视频在线| 日韩欧美一级精品久久| 亚洲欧美在线成人| 国产精品传媒毛片三区| 亚洲福利国产| 久久久伊人日本| 久久视频在线直播| 国产精品久久久久9999吃药| 96久久精品| 天天干免费视频| 日韩一级大片在线观看| 欧美午夜精品一区| 亚洲va欧美va国产va天堂影院| 国内精品久久久久影院优| 亚洲成人直播| 91导航在线观看| 国产精品欧美精品| 欧美超碰在线观看| 91啪九色porn原创视频在线观看| 少妇人妻好深好紧精品无码| 性欧美精品中出| 日本中文字幕久久| 国产一级网站视频在线| 九色91国产| 9久久9毛片又大又硬又粗| 成人高清视频免费观看| 视频一区二区三区在线观看| 久久午夜夜伦鲁鲁一区二区| 日韩乱码人妻无码中文字幕| 一本色道久久| 在线综合亚洲| www.色婷婷.com| 亚洲成av人片在线观看www| 99国产精品免费视频观看| 久久久精品在线观看| 亚洲最新免费视频| 国产人妻精品一区二区三区| 亚洲成人中文字幕| 久久久久久国产视频| 国产精品加勒比| 日本亚洲欧美成人| 奇米影视第四色777| 国产一区二区三区电影在线观看| 伦伦影院午夜理论片| 6080成人| 欧美精三区欧美精三区| 国产精品一卡二卡三卡| 日韩av中文字幕一区| 在线播放高清视频www| 欧美国产欧美亚州国产日韩mv天天看完整| 欧美在线国产| 精品国产乱子伦| 亚洲自拍偷拍福利| 成人综合久久网| 日本久久精品| 亚洲午夜精品一区二区国产| 99国产精品视频免费观看一公开| 青青草国产成人久久91网| 日韩一区日韩二区| 台湾佬中文娱乐网欧美电影| 亚洲精品伦理| 国内自拍视频在线看免费观看| 亚洲sss视频| 亚洲ai欧洲av| 图片区小说区国产精品视频| 国产成人精品一区二区色戒| 国产高清自拍视频在线观看| www.com久久久| 国产精品第一页在线观看| 激情综合色综合啪啪开心| 亚洲精品大片| 亚洲女同精品视频| 午夜伦理在线视频| 国产日韩欧美夫妻视频在线观看| 久久久国产精华| 欧美黑粗硬大| 激情伦成人综合小说| 毛片基地在线观看| 美女网站色91| 日本一区二区免费高清| 91精品久久久久久久久久久久| 男人免费av| 97精品国产97久久久久久| 日日躁夜夜躁白天躁晚上躁91| 黄色三级电影网| 欧美视频日韩| 麻豆91在线| 激情综合网五月婷婷| 黄色在线免费| 超碰个人在线| 黄色一级片免费在线观看| 91精品视频一区| 亚洲a一级视频| 日韩美女视频一区二区在线观看| 国产激情视频在线播放| 国产精品二区一区二区aⅴ| 综合久久久久久| 在线视频一区二区三区| 久久久精品日本| 欧美一二三区| 在线激情小视频| 在线日韩av永久免费观看| 91久久嫩草影院一区二区| 99re这里只有精品在线| 两女双腿交缠激烈磨豆腐| 久久人人爽人人人人片| 欧美一区国产| 成年人免费在线视频| 精品美女在线播放| 污网站在线观看免费| 国产日韩亚洲| 一区二区三区短视频| 一区二区三区四区激情| 九九在线免费视频| 国产美女三级视频| 国产成人精品网| 精品一区二区三区久久久| 欧美成人a∨高清免费观看| 日韩一区精品| 香蕉视频免费在线看| 日本黄色的视频| 中文字幕1区2区3区| 一区二区三区视频网| www.成人精品| 国偷自产视频一区二区久| 国产精品毛片在线| 二区在线视频| 天天做天天爱天天爽综合网| 国产亚洲精品美女久久久久久久久久| 亚洲经典一区| 国产99re66在线视频| 四虎一区二区|