讓我們先從pool的數(shù)據(jù)結(jié)構(gòu)說(shuō)起:

Dial:是必須要實(shí)現(xiàn)的,就是調(diào)用普通的的redis.Dial即可。
TestOnBorrow:在獲取conn的時(shí)候會(huì)調(diào)用一次這個(gè)方法,來(lái)保證連接可用(其實(shí)也不是一定可用,因?yàn)閠est成功以后依然有可能被干掉),這個(gè)方法是可選項(xiàng),一般這個(gè)方法是去調(diào)用一個(gè)redis的ping方法,看項(xiàng)目需求了,如果并發(fā)很高,想極限提高速度,這個(gè)可以不設(shè)置。如果想增加點(diǎn)連接可用性,還是加上比較好??磦€(gè)人取舍了。
MaxIdle,idle,IdleTimeout:都是idle相關(guān)設(shè)置,MaxIdle決定idle的列表長(zhǎng)度,IdleTimeout決定了idle列表中conn的生命周期,默認(rèn)為0,即lifetime,如果設(shè)置了idleTimeout的話,在獲取conn的時(shí)候會(huì)檢查idle隊(duì)列中的連接,把超時(shí)的連接關(guān)閉掉。
MaxActive:線程池的最大連接數(shù)。線程池都是優(yōu)先復(fù)用已有的連接,但是不可避免總是會(huì)有新建連接的時(shí)候,那么這個(gè)值就是限定了連接數(shù)的上限。
Wait:當(dāng)連接數(shù)已滿,是否要阻塞等待獲取連接。false表示不等待,直接返回錯(cuò)誤。
下面我們分析一下核心的獲取連接的方法
// get prunes stale connections and returns a connection from the idle list or
// creates a new connection.
func (p *Pool) get() (Conn, error) {
p.mu.Lock()
// Prune stale connections.
//檢查超時(shí)的連接,如果超時(shí),則從idle隊(duì)列中移除
if timeout := p.IdleTimeout; timeout > 0 {
for i, n := 0, p.idle.Len(); i < n; i++ {
e := p.idle.Back()
if e == nil {
break
}
ic := e.Value.(idleConn)
if ic.t.Add(timeout).After(nowFunc()) {
break
}
p.idle.Remove(e)
p.release()
p.mu.Unlock()
ic.c.Close()
p.mu.Lock()
}
}
for {
// Get idle connection.
//從idle隊(duì)列中復(fù)用已有的連接
for i, n := 0, p.idle.Len(); i < n; i++ {
e := p.idle.Front()
if e == nil {
break
}
ic := e.Value.(idleConn)
p.idle.Remove(e)
test := p.TestOnBorrow
p.mu.Unlock()
if test == nil || test(ic.c, ic.t) == nil {
return ic.c, nil
}
ic.c.Close()
p.mu.Lock()
p.release()
}
// Check for pool closed before dialing a new connection.
if p.closed {
p.mu.Unlock()
return nil, errors.New("redigo: get on closed pool")
}
// Dial new connection if under limit.
//還沒(méi)達(dá)到最大連接數(shù),idle中又沒(méi)有可用的連接,那么就new一個(gè)連接出來(lái)
if p.MaxActive == 0 || p.active < p.MaxActive {
dial := p.Dial
p.active += 1
p.mu.Unlock()
c, err := dial()
if err != nil {
p.mu.Lock()
p.release()
p.mu.Unlock()
c = nil
}
return c, err
}
if !p.Wait {
p.mu.Unlock()
return nil, ErrPoolExhausted
}
if p.cond == nil {
p.cond = sync.NewCond(&p.mu)
}
p.cond.Wait()
}
}
綜上可知,想提高redis的處理速度,可以把idle設(shè)置的大一點(diǎn),當(dāng)然active的值是一定要比idle大的(0表示不限制)。這里還有一點(diǎn)需要注意的redis本身支持的連接數(shù)設(shè)置問(wèn)題,剛才分析的都是client端的情況,如果server只支持100的連接數(shù),那客戶端的pool設(shè)定再多也沒(méi)有用,redis的連接數(shù)配置又是另外一個(gè)話題,這里就不展開(kāi)講。