免费观看又色又爽又黄的小说免费_美女福利视频国产片_亚洲欧美精品_美国一级大黄大色毛片

go語言redis庫 go redis lua

GO語言使用 Redis數據庫

可以參考: windows環境下redis的安裝

創新互聯建站專業IDC數據服務器托管提供商,專業提供成都服務器托管,服務器租用,成都IDC機房托管成都IDC機房托管,成都多線服務器托管等服務器托管服務。

啟動redis服務器:redis-server.exe redis.windows.conf

獲取包:

導入包

訪問:

Go語言與Docker操作Redis

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

然后創建redis容器,并運行

進入redis容器中

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

setex指令 可以設置數據存在的時間, setex key second value

MSET 一次設置多個key-value

MGET一次獲取多個key-value

HGET

HGETALL

Hlen和hexist

Lpush 和 Lrange

Lpop和Rpop 從鏈表取出并移走數據

刪除鏈表所有數據 DEL

字符串無序 不能重復

從連接池中Get出一個conn連接

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

一、關于連接池

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

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

如果不使用連接池,那么,每次傳輸數據,我們都需要進行創建連接,收發數據,關閉連接。在并發量不高的場景,基本上不會有什么問題,一旦并發量上去了,那么,一般就會遇到下面幾個常見問題:

性能普遍上不去

CPU 大量資源被系統消耗

網絡一旦抖動,會有大量 TIME_WAIT 產生,不得不定期重啟服務或定期重啟機器

服務器工作不穩定,QPS 忽高忽低

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

二、使用連接池遇到的坑

最近在一個項目中,需要實現一個簡單的 Web Server 提供 Redis 的 HTTP interface,提供 JSON 形式的返回結果。考慮用 Go 來實現。

首先,去看一下 Redis 官方推薦的 Go Redis driver。官方 Star 的項目有兩個:Radix.v2 和 Redigo。經過簡單的比較后,選擇了更加輕量級和實現更加優雅的 Radix.v2。

Radix.v2 包是根據功能劃分成一個個的 sub package,每一個 sub package 在一個獨立的子目錄中,結構非常清晰。我的項目中會用到的 sub package 有 redis 和 pool。

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

不過在測試過程中,發現了一個詭異的問題。在請求過程中經常會報 EOF 錯誤。而且是概率性出現,一會有問題,一會又好了。通過反復的測試,發現 bug 是有規律的,當程序空閑一會后,再進行連續請求,會發生3次失敗,然后之后的請求都能成功,而我的連接池大小設置的是3。再進一步分析,程序空閑300秒 后,再請求就會失敗,發現我的 Redis server 配置了 timeout 300,至此,問題就清楚了。是連接超時 Redis server 主動斷開了連接。客戶端這邊從一個超時的連接請求就會得到 EOF 錯誤。

然后我看了一下 Radix.v2 的 pool 包的源碼,發現這個庫本身并沒有檢測壞的連接,并替換為新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)}}}

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

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

至此,已經清楚了,使用了 tcp 的 keepalive 心跳機制。

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

四、最后的解決方案

在創建連接池之后,起一個 goroutine,每隔一段 idleTime 發送一個 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 傳輸數據部分代碼如下:

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 連接池內部進行了連接池內連接的獲取和放回,代碼如下:

//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 的機制,不會出現 timeout 的連接了,從 redis 連接池里面取出的連接都是可用的連接了。看似簡單的代碼,卻完美的解決了連接池里面超時連接的問題。同時,就算 Redis server 重啟等情況,也能保證連接自動重連。

分享文章:go語言redis庫 go redis lua
網址分享:http://m.newbst.com/article20/doppcco.html

成都網站建設公司_創新互聯,為您提供App設計網站建設全網營銷推廣電子商務云服務器網站改版

廣告

聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯

營銷型網站建設