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

爲何要使用鏈接池

一個數據庫服務器只擁有有限的鏈接資源,一旦全部的鏈接資源都在使用,那麼其它須要鏈接的資源就只能等待釋放鏈接資源。因此,在鏈接資源有限的狀況下,提升單位時間的鏈接的使用效率,縮短鏈接時間,就能顯著縮短請求時間。git

因此就有了鏈接池的概念,在初始化時,建立必定數量的鏈接,先把全部鏈接存起來,而後,誰須要使用,從這裏取走,幹完活立馬放回來。 若是請求數超出鏈接池容量,那麼就排隊等待或者直接丟棄掉。這樣就能夠省掉每次都建立和關閉鏈接的資源消耗和時間。github

若是不使用鏈接池,那麼,每次傳輸數據,咱們都須要耗費大量的系統資源進行建立鏈接,收發數據,關閉鏈接。很明顯,重複建立鏈接 關閉鏈接這樣的消耗是能夠節省。web

怎麼使用Redis鏈接池

先看下簡單的使用案例。
首先固然是下載類庫包
go get github.com/gomodule/redigo/redis
貼下簡單的使用代碼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寫入數據超時時間。app

鏈接流程大概是這樣的
1.嘗試從空閒列表MaxIdle中,得到一個可用鏈接;若是成功直接返回,失敗則嘗試步驟2
2.若是當前的MaxIdle < 鏈接數 < MaxActive,則嘗試建立一個新鏈接,失敗則嘗試步驟3tcp

  1. 若是鏈接數 > MaxActive就等待,直到知足步驟2的條件,重複步驟2

遇到過的問題

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

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

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

read tcp 127.0.0.1:6379: i/o timeout

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

固然了,想了解更多的Redis使用,能夠看下官方的文檔,裏面有各類狀況的各類說明。
https://github.com/gomodule/redigo/

相關文章
相關標籤/搜索