为什么要使用连接池
一个数据库服务器只拥有有限的连接资源, 一旦所有的连接资源都在使用, 那么其它需要连接的资源就只能等待释放连接资源. 所以, 在连接资源有限的情况下, 提高单位时间的连接的使用效率, 缩短连接时间, 就能显著缩短请求时间.
所以就有了连接池的概念, 在初始化时, 创建一定数量的连接, 先把所有连接存起来, 然后, 谁需要使用, 从这里取走, 干完活立马放回来. 如果请求数超出连接池容量, 那么就排队等待或者直接丢弃掉. 这样就可以省掉每次都创建和关闭连接的资源消耗和时间.
如果不使用连接池, 那么, 每次传输数据, 我们都需要耗费大量的系统资源进行创建连接, 收发数据, 关闭连接. 很明显, 重复创建连接 关闭连接这样的消耗是可以节省.
怎么使用 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
如果连接数 > 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/
来源: https://www.cnblogs.com/feixiangmanon/p/11155120.html