MySQL-连接池优化

MySQL 连接池是什么?

存储连接的池子,本质上是一种资源复用技术。

作用:节约连接创建的成本,提升流程处理的效率。

注意:连接池是在 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 连接池