go redis 連線池原始碼分析

2021-10-01 18:23:28 字數 4230 閱讀 3310

1、建立連線和關閉連線 2、池子裡面取conn的管理 3、監控統計 4、整個pooler池子的關閉

結構體

type connpool struct

//池子裡面空閒的conn的同步channel

connsmu sync.mutex

conns [

]*conn //活躍的active conns

idleconnsmu sync.rwmutex

idleconns [

]*conn //空閒的idle conns

stats stats

_closed uint32

// atomic //池子是否關閉標籤

}

初始化連線池
var

_ pooler =

(*connpool)

(nil

)//介面檢查

func

newconnpool

(opt *options)

*connpool

, opt.poolsize)

,//同步用的

conns:

make([

]*conn,

0, opt.poolsize)

, idleconns:

make([

]*conn,

0, opt.poolsize),}

if opt.idletimeout >

0&& opt.idlecheckfrequency >

0return p

}//reaper字面意思為收割者,為清理的意思

func

(p *connpool)

reaper

(frequency time.duration)

//定時清理無用的conns

n, err := p.

reapstaleconns()

if err !=

nil atomic.

adduint32

(&p.stats.staleconns,

uint32

(n))}}

func

(p *connpool)

reapstaleconns()

(int

,error

)//處理完了,釋放占用的channel的位置

p.freeturn()

if cn !=

nilelse

}return n,

nil}

func

(p *connpool)

reapstaleconn()

*conn

//取第乙個空閒conn

cn := p.idleconns[0]

//判斷是否超時沒有人用

if!cn.

isstale

(p.opt.idletimeout)

//超時沒有人用則從空閒列表裡面移除

p.idleconns =

(p.idleconns[:0

], p.idleconns[1:

]...

)return cn

}//判斷是否超時的處理

func

(cn *conn)

isstale

(timeout time.duration)

bool

//移除連線就是乙個很簡單的遍歷

func

(p *connpool)

removeconn

(cn *conn)

} p.connsmu.

unlock()

}

建立連線
func

(p *connpool)

newconn()

(*conn,

error)

p.connsmu.

lock()

//建立好後加入conns中

p.conns =

(p.conns, cn)

p.connsmu.

unlock()

return cn,

nil}

func

(p *connpool)

newconn()

(*conn,

error

)//判斷是否一直出錯

if atomic.

loaduint32

(&p.dialerrorsnum)

>=

uint32

(p.opt.poolsize)

netconn, err := p.opt.

dialer()

if err !=

nilreturn

nil, err

}return

newconn

(netconn)

,nil

}func

(p *connpool)

trydial()

//就是不斷的dailer直到成功

conn, err := p.opt.

dialer()

if err !=

nil//dialer成功,則設定dialerrorsnum為0

atomic.

storeuint32

(&p.dialerrorsnum,0)

_= conn.

close()

return

}}

從乙個連線池中獲取乙個連線(get)
func

(p *connpool)

get()(

*conn,

error

)//等待有空閒,通過channel方式同步,如果池子裡面滿了,則會阻塞等待,但是不會一直阻塞,有乙個超時機制

err := p.

waitturn()

if err !=

nilfor

//取出空閒的,並判斷conn是否過期

if cn.

isstale

(p.opt.idletimeout)

atomic.

adduint32

(&p.stats.hits,1)

return cn,

nil}

//沒有取到conn,miss了

atomic.

adduint32

(&p.stats.misses,1)

//建立新的連線

newcn, err := p.

newconn()

if err !=

nilreturn newcn,

nil}

是get方法成功的時候就往channel裡面寫,put方法成功就往channel裡面讀,釋放出來位置

func

(p *connpool)

waitturn()

error

:return

nildefault

: timer := timers.

get().

(*time.timer)

timer.

reset

(p.opt.pooltimeout)

select:if

!timer.

stop()

timers.

put(timer)

return

nilcase

<-timer.c:

//超時寫入機制

timers.

put(timer)

atomic.

adduint32

(&p.stats.timeouts,1)

return errpooltimeout

}}}

put
func

(p *connpool)

put(cn *conn)

p.idleconnsmu.

lock()

//放入空閒conns裡面來,方便get的時候取出來

p.idleconns =

(p.idleconns, cn)

p.idleconnsmu.

unlock()

//get成功時候是寫入channel,這個時候自然是釋放channel

p.freeturn()

}

資料庫連線池Hikaricp原始碼分析

hikaricp總結 借助哪些技術使效能超越其他執行緒池的?為了效能,自定義資料結構 fastlist concurrentbag 主要就是concurrentbag使用threadlocal sharelist 等待queue 對獲取connnection做了優化。定時器相關的使用 schedul...

Mybatis自帶連線池原始碼解析

poolmaximumactiveconnections 連線池最大活躍連線數,預設為10個。poolmaximumidleconnections 連線池最大空閒連線數,預設為5個。poolmaximumcheckouttime 最大可 時間,當活躍連線數達到上限時,如果此時有連線請求,則會檢查當前...

深入分析連線池技術 模擬實現連線池

模擬實現資料庫連線池連線池類 connectionpool 模擬資料庫連線池的操作流程 1.建立乙個資料庫連線池 2.初始10個連線物件 3.來乙個客戶端,從連線池裡取 4.當客戶用完了,則不是真的銷毀,而是放入到連線池中public class connectpool public connect...