golang開發:類庫篇(二) Redis連接池的使用

爲什麼要使用連接池

一個數據庫服務器只擁有有限的連接資源,一旦所有的連接資源都在使用,那麼其它需要連接的資源就只能等待釋放連接資源。所以,在連接資源有限的情況下,提高單位時間的連接的使用效率,縮短連接時間,就能顯著縮短請求時間。

所以就有了連接池的概念,在初始化時,創建一定數量的連接,先把所有連接存起來,然後,誰需要使用,從這裏取走,幹完活立馬放回來。 如果請求數超出連接池容量,那麼就排隊等待或者直接丟棄掉。這樣就可以省掉每次都創建和關閉連接的資源消耗和時間。

如果不使用連接池,那麼,每次傳輸數據,我們都需要耗費大量的系統資源進行創建連接,收發數據,關閉連接。很明顯,重複創建連接 關閉連接這樣的消耗是可以節省。

怎麼使用Redis連接池

先看下簡單的使用案例。
首先當然是下載類庫包
go get github.com/gomodule/redigo/redis
貼下簡單的使用代碼

package main

import (
	red "github.com/gomodule/redigo/redis"
	"time"
	"fmt"
)

type Redis struct {
	pool     *red.Pool
}

var redis *Redis

func initRedis() {
	redis = new(Redis)
	redis.pool = &red.Pool{
		MaxIdle:     256,
		MaxActive:   0,
		IdleTimeout: time.Duration(120),
		Dial: func() (red.Conn, error) {
			return red.Dial(
				"tcp",
				"127.0.0.1:6379",
				red.DialReadTimeout(time.Duration(1000)*time.Millisecond),
				red.DialWriteTimeout(time.Duration(1000)*time.Millisecond),
				red.DialConnectTimeout(time.Duration(1000)*time.Millisecond),
				red.DialDatabase(0),
				//red.DialPassword(""),
			)
		},
	}
}

func Exec(cmd string, key interface{}, args ...interface{}) (interface{}, error) {
	con := redis.pool.Get()
	if err := con.Err(); err != nil {
		return nil, err
	}
	defer con.Close()
	parmas := make([]interface{}, 0)
	parmas = append(parmas, key)

	if len(args) > 0 {
		for _, v := range args {
			parmas = append(parmas, v)
		}
	}
	return con.Do(cmd, parmas...)
}

func main() {
	initRedis()

	Exec("set","hello","world")
	fmt.Print(2)
	result,err := Exec("get","hello")
	if err != nil {
		fmt.Print(err.Error())
	}
	str,_:=red.String(result,err)
	fmt.Print(str)
}

使用類庫操作連接池就比較簡單,只要從連接池獲取一個連接,進行數據操作,然後關閉連接。連接池對連接的創建 回收等的管理,都是連接池內部實現。
執行看下結果是不是預想的

go build -o test_web.bin
./test_web.bin
2world

結果跟預想的一毛一樣

基本配置說明

MaxIdle:最大的空閒連接數,表示即使沒有redis連接時依然可以保持N個空閒的連接,而不被清除,隨時處於待命狀態。
MaxActive:最大的連接數,表示同時最多有N個連接。0表示不限制。
IdleTimeout:最大的空閒連接等待時間,超過此時間後,空閒連接將被關閉。如果設置成0,空閒連接將不會被關閉。應該設置一個比redis服務端超時時間更短的時間。
DialConnectTimeout:連接Redis超時時間。
DialReadTimeout:從Redis讀取數據超時時間。
DialWriteTimeout:向Redis寫入數據超時時間。

連接流程大概是這樣的
1.嘗試從空閒列表MaxIdle中,獲得一個可用連接;如果成功直接返回,失敗則嘗試步驟2
2.如果當前的MaxIdle < 連接數 < MaxActive,則嘗試創建一個新連接,失敗則嘗試步驟3
3. 如果連接數 > MaxActive就等待,直到滿足步驟2的條件,重複步驟2

遇到過的問題

目前爲止,連接池的問題只遇到過一次問題,而且是在測試環境的,當時的配置是

DialConnectTimeout:time.Duration(200)*time.Millisecond
DialReadTimeout:time.Duration(200)*time.Millisecond
DialWriteTimeout:time.Duration(200)*time.Millisecond

配置的都是200毫秒。有一次使用hgetall的時候,就一直報錯,大概類似下面的提示

read tcp 127.0.0.1:6379: i/o timeout

字面意思就是 read tcp 超時,可能某些寫入大點數據的時候也會報,write tcp timeout。
後來將讀寫超時時間都改爲1000毫秒,就再也沒有出現過類似的報錯。

當然了,想了解更多的Redis使用,可以看下官方的文檔,裏面有各種情況的各種說明。
https://github.com/gomodule/redigo/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章