为什么会有连接池这个东西
redis是基于内存的,计算的效率很高,但是网络通信是redis性能提升的瓶颈,如果redis服务器每次都要与客户端随机创立连接然后释放连接,会造成一定性能浪费,执行的效率会大大降低。
连接池的技术就是redis服务端预先开通连接,等客户端需要的时候,直接从连接池里面取出连接,然后使用。不再是当客户端需要的时候再去创建连接了,提高了资源的利用率和访问速度。
说明:通过 Golang对Redis操作, 还可以通过Redis链接池 流程如下:
- 事先初始化一定数量的链接,放入到链接池
- 当 Go需要操作Redis时,直接从Redis链接池取出链接即可。
- 这样可以节省临时获取 Redis 链接的时间,从而提高效率。
pool.go 源码
type Pool struct {// Dial is an application supplied function for creating and configuring a// connection.//// The connection returned from Dial must not be in a special state// (subscribed to pubsub channel, transaction started, ...).Dial func() (Conn, error)// DialContext is an application supplied function for creating and configuring a// connection with the given context.//// The connection returned from Dial must not be in a special state// (subscribed to pubsub channel, transaction started, ...).DialContext func(ctx context.Context) (Conn, error)// TestOnBorrow is an optional application supplied function for checking// the health of an idle connection before the connection is used again by// the application. Argument t is the time that the connection was returned// to the pool. If the function returns an error, then the connection is// closed.TestOnBorrow func(c Conn, t time.Time) error// Maximum number of idle connections in the pool.MaxIdle int// Maximum number of connections allocated by the pool at a given time.// When zero, there is no limit on the number of connections in the pool.MaxActive int// Close connections after remaining idle for this duration. If the value// is zero, then idle connections are not closed. Applications should set// the timeout to a value less than the server's timeout.IdleTimeout time.Duration// If Wait is true and the pool is at the MaxActive limit, then Get() waits// for a connection to be returned to the pool before returning.Wait bool// Close connections older than this duration. If the value is zero, then// the pool does not close connections based on age.MaxConnLifetime time.Durationmu sync.Mutex // mu protects the following fieldsclosed bool // set to true when the pool is closed.active int // the number of open connections in the poolinitOnce sync.Once // the init ch once funcch chan struct{} // limits open connections when p.Wait is trueidle idleList // idle connectionswaitCount int64 // total number of connections waited for.waitDuration time.Duration // total time waited for new connections.}
核心代码:
var pool *redis.Pool// 初始化连接池pool = &redis.Pool{MaxIdle: 8, //最大空闲链接数MaxActive: 0, //表示和数据库的最大链接数,0表示没有限制IdleTimeout: 100, //最大空闲时间Dial: func() (redis.Conn, error) { // 初始化链接的代码,链接哪个ip的redisreturn redis.Dial("tcp", "localhost:6379")},}c := pool.Get() // 从连接池中取出一个链接pool.Close() // 关闭连接池,一旦关闭链接池,就不能从链接池连接
代码体验
// redis 连接池package mainimport ("fmt""github.com/gomodule/redigo/redis")// 定义一个全局的 poolvar pool *redis.Pool// 当启动程序时,初始化连接池func init() {pool = &redis.Pool{MaxIdle: 8, //最大空闲链接数MaxActive: 0, //表示和数据库的最大链接数,0表示没有限制IdleTimeout: 100, //最大空闲时间Dial: func() (redis.Conn, error) { // 初始化链接的代码,链接哪个ip的redisreturn redis.Dial("tcp", "localhost:6379")},}}func main() {fmt.Printf("pool 类型: %T, 值: %v \n", pool, pool)// 1. 先从 pool 里面取出连接conn := pool.Get()// conn 类型: *redis.activeConn, 值: &{0xc000070500 0xc0000aa000 0}fmt.Printf("conn 类型: %T, 值: %v \n", conn, conn)defer conn.Close()// 2. 操作_, err := conn.Do("Set", "watch", "xiaomi")if err != nil {fmt.Println("操作失败", err)return}val, err := redis.String(conn.Do("Get", "watch"))if err != nil {fmt.Println("操作失败", err)return}fmt.Println("val =", val)// 关闭连接池, 不能再继续读写了pool.Close()conn2 := pool.Get()fmt.Println("conn2=", conn2)_, err = conn2.Do("Set", "watch2", "xiaomi222")if err != nil {// Set()操作失败 redigo: get on closed poolfmt.Println("Set()操作失败", err)return}val, err = redis.String(conn2.Do("Get", "watch2"))if err != nil {fmt.Println("get操作失败", err)return}fmt.Println("val2 =", val)}
