真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

go語言redis連接池 go redis連接池

Go語言與Docker操作Redis

首選,如果之前使用過redis容器,我們需要先remove掉之前的容器

創(chuàng)新互聯(lián)主營鳳泉網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營網(wǎng)站建設(shè)方案,成都app開發(fā),鳳泉h5小程序設(shè)計(jì)搭建,鳳泉網(wǎng)站營銷推廣歡迎鳳泉等地區(qū)企業(yè)咨詢

然后創(chuàng)建redis容器,并運(yùn)行

進(jìn)入redis容器中

接著我們通過 redis-cli 連接測試使用 redis 服務(wù)

setex指令 可以設(shè)置數(shù)據(jù)存在的時(shí)間, setex key second value

MSET 一次設(shè)置多個(gè)key-value

MGET一次獲取多個(gè)key-value

HGET

HGETALL

Hlen和hexist

Lpush 和 Lrange

Lpop和Rpop 從鏈表取出并移走數(shù)據(jù)

刪除鏈表所有數(shù)據(jù) DEL

字符串無序 不能重復(fù)

從連接池中Get出一個(gè)conn連接

如何在 Go 語言中使用 Redis 連接池

一、關(guān)于連接池

一個(gè)數(shù)據(jù)庫服務(wù)器只擁有有限的資源,并且如果你沒有充分使用這些資源,你可以通過使用更多的連接來提高吞吐量。一旦所有的資源都在使用,那么你就不 能通過增加更多的連接來提高吞吐量。事實(shí)上,吞吐量在連接負(fù)載較大時(shí)就開始下降了。通常可以通過限制與可用的資源相匹配的數(shù)據(jù)庫連接的數(shù)量來提高延遲和吞 吐量。

如何在Go語言中使用Redis連接池

如果不使用連接池,那么,每次傳輸數(shù)據(jù),我們都需要進(jìn)行創(chuàng)建連接,收發(fā)數(shù)據(jù),關(guān)閉連接。在并發(fā)量不高的場景,基本上不會(huì)有什么問題,一旦并發(fā)量上去了,那么,一般就會(huì)遇到下面幾個(gè)常見問題:

性能普遍上不去

CPU 大量資源被系統(tǒng)消耗

網(wǎng)絡(luò)一旦抖動(dòng),會(huì)有大量 TIME_WAIT 產(chǎn)生,不得不定期重啟服務(wù)或定期重啟機(jī)器

服務(wù)器工作不穩(wěn)定,QPS 忽高忽低

要想解決這些問題,我們就要用到連接池了。連接池的思路很簡單,在初始化時(shí),創(chuàng)建一定數(shù)量的連接,先把所有長連接存起來,然后,誰需要使用,從這里取走,干完活立馬放回來。 如果請求數(shù)超出連接池容量,那么就排隊(duì)等待、退化成短連接或者直接丟棄掉。

二、使用連接池遇到的坑

最近在一個(gè)項(xiàng)目中,需要實(shí)現(xiàn)一個(gè)簡單的 Web Server 提供 Redis 的 HTTP interface,提供 JSON 形式的返回結(jié)果??紤]用 Go 來實(shí)現(xiàn)。

首先,去看一下 Redis 官方推薦的 Go Redis driver。官方 Star 的項(xiàng)目有兩個(gè):Radix.v2 和 Redigo。經(jīng)過簡單的比較后,選擇了更加輕量級(jí)和實(shí)現(xiàn)更加優(yōu)雅的 Radix.v2。

Radix.v2 包是根據(jù)功能劃分成一個(gè)個(gè)的 sub package,每一個(gè) sub package 在一個(gè)獨(dú)立的子目錄中,結(jié)構(gòu)非常清晰。我的項(xiàng)目中會(huì)用到的 sub package 有 redis 和 pool。

由于我想讓這種被 fork 的進(jìn)程最好簡單點(diǎn),做的事情單一一些,所以,在沒有深入去看 Radix.v2 的 pool 的實(shí)現(xiàn)之前,我選擇了自己實(shí)現(xiàn)一個(gè) Redis pool。(這里,就不貼代碼了。后來發(fā)現(xiàn)自己實(shí)現(xiàn)的 Redis pool 與 Radix.v2 實(shí)現(xiàn)的 Redis pool 的原理是一樣的,都是基于 channel 實(shí)現(xiàn)的, 遇到的問題也是一樣的。)

不過在測試過程中,發(fā)現(xiàn)了一個(gè)詭異的問題。在請求過程中經(jīng)常會(huì)報(bào) EOF 錯(cuò)誤。而且是概率性出現(xiàn),一會(huì)有問題,一會(huì)又好了。通過反復(fù)的測試,發(fā)現(xiàn) bug 是有規(guī)律的,當(dāng)程序空閑一會(huì)后,再進(jìn)行連續(xù)請求,會(huì)發(fā)生3次失敗,然后之后的請求都能成功,而我的連接池大小設(shè)置的是3。再進(jìn)一步分析,程序空閑300秒 后,再請求就會(huì)失敗,發(fā)現(xiàn)我的 Redis server 配置了 timeout 300,至此,問題就清楚了。是連接超時(shí) Redis server 主動(dòng)斷開了連接??蛻舳诉@邊從一個(gè)超時(shí)的連接請求就會(huì)得到 EOF 錯(cuò)誤。

然后我看了一下 Radix.v2 的 pool 包的源碼,發(fā)現(xiàn)這個(gè)庫本身并沒有檢測壞的連接,并替換為新server{location/pool{content_by_lua_block{localredis=require"resty.redis"localred=redis:new()localok,err=red:connect("127.0.0.1",6379)ifnotokthenngx.say("failedtoconnect:",err)returnendok,err=red:set("hello","world")ifnotokthenreturnendred:set_keepalive(10000,100)}}}

發(fā)現(xiàn)有個(gè) set_keepalive 的方法,查了一下官方文檔,方法的原型是 syntax: ok, err = red:set_keepalive(max_idle_timeout, pool_size) 貌似 max_idle_timeout 這個(gè)參數(shù),就是我們所缺少的東西,然后進(jìn)一步跟蹤源碼,看看里面是怎么保證連接有效的。

function_M.set_keepalive(self,...)localsock=self.sockifnotsockthenreturnnil,"notinitialized"endifself.subscribedthenreturnnil,"subscribedstate"endreturnsock:setkeepalive(...)end

至此,已經(jīng)清楚了,使用了 tcp 的 keepalive 心跳機(jī)制。

于是,通過與 Radix.v2 的作者一些討論,選擇自己在 redis 這層使用心跳機(jī)制,來解決這個(gè)問題。

四、最后的解決方案

在創(chuàng)建連接池之后,起一個(gè) goroutine,每隔一段 idleTime 發(fā)送一個(gè) PING 到 Redis server。其中,idleTime 略小于 Redis server 的 timeout 配置。連接池初始化部分代碼如下:

p,err:=pool.New("tcp",u.Host,concurrency)errHndlr(err)gofunc(){for{p.Cmd("PING")time.Sleep(idelTime*time.Second)}}()

使用 redis 傳輸數(shù)據(jù)部分代碼如下:

funcredisDo(p*pool.Pool,cmdstring,args...interface{})(reply*redis.Resp,errerror){reply=p.Cmd(cmd,args...)iferr=reply.Err;err!=nil{iferr!=io.EOF{Fatal.Println("redis",cmd,args,"erris",err)}}return}

其中,Radix.v2 連接池內(nèi)部進(jìn)行了連接池內(nèi)連接的獲取和放回,代碼如下:

//Cmdautomaticallygetsoneclientfromthepool,executesthegivencommand//(returningitsresult),andputstheclientbackinthepoolfunc(p*Pool)Cmd(cmdstring,args...interface{})*redis.Resp{c,err:=p.Get()iferr!=nil{returnredis.NewResp(err)}deferp.Put(c)returnc.Cmd(cmd,args...)}

這樣,我們就有了 keepalive 的機(jī)制,不會(huì)出現(xiàn) timeout 的連接了,從 redis 連接池里面取出的連接都是可用的連接了。看似簡單的代碼,卻完美的解決了連接池里面超時(shí)連接的問題。同時(shí),就算 Redis server 重啟等情況,也能保證連接自動(dòng)重連。

如何在go語言中使用redis連接池

1.在創(chuàng)建連接池之后,起一個(gè) go routine,每隔一段 idleTime 發(fā)送一個(gè) PING 到 Redis server。其中,idleTime 略小于 Redis server 的 timeout 配置。

2.連接池初始化部分代碼如下:

p, err := pool.New("tcp", u.Host, concurrency) errHndlr(err) go func() { for { p.Cmd("PING") time.Sleep(idelTime * time.Second) } }()

3.使用 redis 傳輸數(shù)據(jù)部分代碼如下:

func redisDo(p *pool.Pool, cmd string, args ...interface{}) (reply *redis.Resp, err error) { reply = p.Cmd(cmd, args...) if err = reply.Err; err != nil { if err != io.EOF { Fatal.Println("redis", cmd, args, "err is", err) } } return }

4.其中,Radix.v2 連接池內(nèi)部進(jìn)行了連接池內(nèi)連接的獲取和放回,代碼如下:

// Cmd automatically gets one client from the pool, executes the given command // (returning its result), and puts the client back in the pool func (p *Pool) Cmd(cmd string, args ...interface{}) *redis.Resp { c, err := p.Get() if err != nil { return redis.NewResp(err) } defer p.Put(c) return c.Cmd(cmd, args...) }

這樣,就有了系統(tǒng) keep alive 的機(jī)制,不會(huì)出現(xiàn) time out 的連接了,從 redis 連接池里面取出的連接都是可用的連接了??此坪唵蔚拇a,卻完美的解決了連接池里面超時(shí)連接的問題。同時(shí),就算 Redis server 重啟等情況,也能保證連接自動(dòng)重連。

golang 如何連接redis --- 2022-04-03

下面介紹golang如何連接redis服務(wù)端。

1.golang連接redis

通過例子,我們知道主要通過Options配置redis的連接參數(shù),下面對Options參數(shù)進(jìn)行詳細(xì)說明。

提示:go-redis包自帶了連接池,會(huì)自動(dòng)維護(hù)redis連接,因此創(chuàng)建一次client即可,不要查詢一次redis就關(guān)閉client。

2.Options參數(shù)詳解


網(wǎng)頁標(biāo)題:go語言redis連接池 go redis連接池
文章轉(zhuǎn)載:http://weahome.cn/article/hhgigo.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部