MySQL-连接池优化
MySQL-连接池优化
xukunMySQL 连接池是什么?
存储连接的池子,本质上是一种资源复用技术。
作用:节约连接创建的成本,提升流程处理的效率。
注意:连接池是在 MySQL 的客户端一侧。
连接池的价值
短连接在高并发场景下反复建立连接成本很高,使用长连接用完后不关闭。
价值:实现连接资源的复用
连接池常见参数
参数控制 MySQL 的连接复用策略,一般由客户端引擎(Java 库)实现。
通常客户端支持的主要参数:
最大空闲连接数/连接池个数(长连接个数): 连接池中最多有多少个空闲连接,
理解为:一共可以维护多少个长连接来节约连接建立的成本。
空闲时间(长连接的持续性):表面了连接池中的连接在空闲时在池子里面可以摸鱼多久,便于节约资源。1-10s 左右
最小连接数:连接池中最小的空闲连接,当连接数小于这个值时,连接池会自动创建新的连接来进行补充。
作用:保持连接池处于就绪状态。
使用场景:需要的长连接比较多,且请求是周期性的。eg.晚上跑脚本触发请求。
初始化连接数:意义不大,由最小连接数补齐。
Druid 的连接池参数(Java)
- maxActive:连接池中的最大连接个数,也就是我们一开始图里的”最大空闲连接数”
- minEvictableldleTimeMillis:连接在池中最小生存的时间,单位是室秒,换句话说达到这个时间就可能被释放掉,其实本质就是”空闲时间”
- maxWait:某个请求到达时,如果连接池满了,就会陷入等待,这个参数指定了最大等待多长时间,单位 ms
- timeBetweenEvictionRunsMillis:配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是 ms
- initialSize:程序启动时,初始化连接池中的连接数量
- minIdle:连接池中最小连接个数
GORM 连接池(Golang)
字段名 | 解释 |
---|---|
maxIdleConn | 连接池中的最大连接个数 |
maxLifetime | 连接可复用的最大时间,换句话说达到这个时间就可能被释放掉,其实本质就是“空闲时间” |
maxOpenConn | 最大连接数,这里指的是GORM一共可以打开多少个连接,实际是连接池里面的长连接(maxIdleConn)和短连接之和,也就是说GORM达到连接池中最大空闲链接数之后,不会等待,而是继续打开短连接,如果超过maxOpenConn这个阈值,就会出现too many connections的提示,这个数字通常可以设置得较大,以应对突如其来的峰值。 |
timeBetweenEvictionRunsMillis | 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 |
initialSize | 程序启动时,初始化连接池中的连接数量 |
minIdle | 连接池中最小连接个数 |
Druid 和 GORM 的连接参数的不同之处
- 连接池满了后的行为不同
Druid 连接池满了,就会等待连接释放,超过最大等待时间后会抛出错误
GORM 则会直接打开短连接
- 对最大、最小的理解不同
比如空闲时间:
Druid 中的 minEvictableldleTimeMillis 连接池在池中最小生存时间,达到这个时间就可以被释放了
GORM 中的maxLifetime,最大生存时间,达到这个时间就可以被回收了
- 框架定位
GORM 是连接数据库的框架,说不上真正的核心
Druid 更像是一个专业的连接池框架,出发点是基于有一个池子考虑的
连接池的应用场景
访问 MySQL 的场景,eg.生成秒杀订单、任务插入等
实战
任务插入场景
任务插入场景 功能性 测试
1 | curl -H "Trace-ID: test" -H "Content-Type: application/json; charset=utf-8" -H "User-ID: 77" http://localhost:8081/demo/create_task -d '{"num":1}' |
这个命令的作用是:
向
http://localhost:8081/demo/create_task
发送一个POST
请求。请求头包括:
Trace-ID: test
Content-Type: application/json; charset=utf-8
User-ID: 77
请求体是一个 JSON 数据:
{"num": 1}
。
任务插入场景压力测试
轻量级工具 wrk 来进行测试
1 | wrk -t8 -c50 -d10s -T1s --script=create_task.lua --latency "http://127.0.0.1:8081/demo/create_task" |
这个命令的作用:
- 8 个线程 来发送请求
- 模拟 50 个并发连接
- 测试持续时间为 10 秒
- 表示设置 请求超时时间为 1 秒,如果服务器在 1 秒内未响应,则认为请求失败。
- 使用 Lua 脚本
create_task.lua
来定义请求的逻辑
任务插入场景优化并压测
8 qps:2500
1 qps:600
100 qps:6000
2000 qps:6000
在 100 以内,适当放大连接池个数,对性能的影响比较明显,
在 100 以上,连接池放大收益不高,通常 100 以内即可,但是很多团队设置成 2000
扩展
如果连接池不够了怎么办?
java 连接池设置过小不仅会导致 QPS 降低性能变低之外还容易导致报错产生(超过等待连接一定秒数后产生报错)jdbc.CannotGetJdbcConnectionException
golang 一般不会导致报错产生(连接池不够用了就会开启短连接,用完就关掉直到最大连接数),除非,过多短链接导致过多 TIME_WAIT,然后报错是因为端口不能打开 can’t assign requested address
注意:端口回收时间是 2 min
总结
池化技术的本质:连接复用(资源复用)
例如:MySQL 连接池、Redis 连接池、Http 连接池、GRPC 连接池