Vitess 中的连接池
连接池是现代应用程序中常用的一种技术,用于高效管理数据库连接。它通过创建一个数据库连接的缓存供应用程序根据需要使用。应用程序不需要为每次数据库请求创建新连接,而是从池中获取连接。应用程序使用完连接后,将其返回到池中以供后续使用,而不是直接关闭连接。
应用级连接池的优势
使用连接池能够为应用程序带来以下几个好处:
性能提升
连接池减少了建立新数据库连接的开销。连接被重复利用,而不需要针对每个请求创建或关闭新的连接。这对需要频繁进行较小规模数据库交互的应用程序特别有用。
MySQL SSL 连接建立阶段通常会为数据库网络连接带来约 50 毫秒的额外开销,而通过实现连接池,应用程序可以显著减少每次请求的响应时间,避免额外的 50 毫秒延迟。这种性能上的改进可以显著优化应用程序的整体功能。
可扩展性
连接池显著提高了应用程序处理大量并发连接的能力。通过重复使用现有连接,消除连接建立的开销,从而释放 CPU 用于其他任务。这使得应用程序能够同时处理更多的并发请求。
流量整形
连接池通过限制活跃连接数量来帮助管理数据库资源。当应用层出现流量高峰时,连接池会对部分请求进行限制,让它们等待分配连接。这可以防止数据库负载过高,避免性能下降或崩溃。数据库因此能够在最大容量利用率下继续运行。
当连接池不足以应对需求时
虽然应用级连接池是一种有用的工具,但它在解决所有可扩展性问题时有其局限性。连接池本身只负责管理和重复利用连接,而无法使数据库扩展到应对不断增长的负载。当有数千个并发请求时,数据库的资源(例如 CPU、内存和磁盘 I/O)可能会超载,导致性能下降或数据库崩溃。
随着应用规模的增长和负载的增加,部署在多个服务器上的需求必然出现。然而,当服务器数量从少数增长到数百或数千时,可能会让数据库超载。此外,连接到同一数据库的新应用也会加重这种负担。
在应用服务器增加以及引入新应用后,应用级连接池可能会导致数据库连接的效率下降。应用服务器的负载有时可能并不均衡,应用程序可能没有正确限制数据库连接,从而造成连接浪费。在这种情况下,真正需要连接的应用服务器可能因达到数据库连接限制而无法获得资源。
大规模情况下的连接池
2010 年,YouTube 遇到了类似的挑战,促使 Vitess 和其首个组件 Vttablet 的开发。Vttablet 充当了 MySQL 的代理,并主要负责管理连接池。通过让客户端应用程序仅能连接到 Vttablet,而不是直接连接到数据库,应用级连接池的需求被消除。这意味着连接可以集中由 Vttablet 管理,连接数量上限在 Vttablet 中是可配置的,而不会随着应用数量的增加而不受控制地增长。这大大减轻了数据库的负担并提高了可扩展性。
为处理大规模的并发请求,Vttablet 的连接池实现被设计为无锁结构,采用原子操作和非阻塞的数据结构配合无锁算法。这种设计使 Vitess 能够有效地管理大量并发请求,同时进一步提升可扩展性和性能。
连接设置
MySQL 提供了一系列会话级系统设置,每个连接都可以调整。但当使用连接池时,池中的所有连接共享相同的设置。对某一连接的修改会使它无法用于其他请求,因为它变得“受污染”。因此,修改后的连接设置要么必须恢复为原值,要么需在操作完成后关闭连接以确保连接池的稳定性。需要注意频繁修改连接设置的潜在影响,因为这可能会随着请求数量的增加而降低性能。
Vitess 长期以来未支持在连接上的系统设置修改。若存在设置修改请求,Vitess 会忽略它们以维持连接池的优势。然而,当 Vitess 开始支持 MySQL 协议时,针对多种语言的不同 ORM(对象关系映射)可以通过该语言的默认 MySQL 连接器连接到 Vitess。这些 ORM 在连接开始时通常会发出 SET
语句来修改连接设置,并期望这些连接按特定方式运行。
为支持这些连接级设置,Vitess 必须偏离其原始连接池方法。在 Vitess v7.0 版本中,允许在连接上修改系统设置。这使得连接被保留用于应用会话,无法再返回连接池。由于这些类型的保留连接不再属于连接池,其数量可能无限增长,最终会导致 MySQL 连接耗尽,使数据库无法被应用使用。
在 Vitess v15.0 之前,限制保留连接对 MySQL 连接总数影响的方法包括以下两种:
限制保留连接影响:方法 1
当应用程序通过连接发出 SET
语句来修改系统设置时,Vitess 首先验证这些变量的当前系统设置。如果所需连接设置与 MySQL 的设置相同,则 Vitess 会忽略该 SET
语句,连接不会被标记为保留连接。
例如,若应用程序发送查询 SET unique_checks = 0
,Vitess 将向 MySQL 发送查询 SELECT 0 FROM DUAL WHERE @@unique_checks != 0
。如果查询返回一行数据,则说明连接设置正在被修改,会话将被标记使用保留连接,并应用新的设置。否则,不需要使用保留连接,且可以忽略 SET
语句。
限制保留连接影响:方法 2
MySQL 8.0 提供了一项能力,可以通过 SET_VAR
提示在查询期间临时修改内存中的系统设置。这种查询提示不会在应用设置时“污染”连接,使得连接可以重复使用。
基于之前的例子,一旦 Vitess 识别到 unique_checks
设置正在被修改,后续会话中的所有查询都会被重写。例如,查询 INSERT INTO user (id, name) VALUES (1, 'foo')
将被重写为 INSERT /*+ SET_VAR(unique_checks=0) */ INTO user (id, name) VALUES (1, 'foo')
。
然而,需要注意,并非所有设置都可以使用 SET_VAR
。对于那些不允许的设置,仍然需要使用保留连接。
通过使用上述技术,我们尽可能减少了保留连接的使用,从而保留了连接池的优势。然而,由于能够使用 SET_VAR
的系统设置数量有限,仍然有必须应用于连接的系统设置,导致连接被移出连接池并导致数据库性能下降。
Settings Pool 的引入
随着连接设置功能的推出,我们建议 Vitess 用户谨慎使用它。我们建议将 MySQL 默认为满足 ORM 的 SET
语句设置,以尽量减少使用保留连接的可能性,避免连接耗尽的问题。然而,随着时间推移,Vitess 用户发现这一方法并非总是可行,特别是当多个具有不同 ORM 的应用程序在一个 Vitess 集群上运行时。不同行的 ORM 可能为同一设置指定不同的值,使 MySQL 的默认设置失效,从而导致使用保留连接的数量增加。因此,这个问题需要在 Vitess 层面解决。
在 Vitess 15 中,引入了新的连接池——“设置池(Settings Pool)”。设置池能够处理修改过连接的情况,同时不损害连接池的优势。Vitess 现在能够跟踪并管理那些已修改了系统设置的连接。这个过程对应用来说是透明的,但同时提供了连接池的所有优势,并允许针对每个连接的特定设置。当应用提交查询给 Vitess 执行时,Vitess 可以从连接池中检索正确的连接,无论是否应用了设置,基于该应用在会话中指定的设置来执行查询。
目前,这项功能需要通过标志开启,并可在 Vttablet 中使用 queryserver-enable-settings-pool
启用。
在 PlanetScale,我们已经开始推广该功能,并看到了对于之前依赖于应用 ORM 而使用保留连接的客户带来的查询延迟和 Vttablet 负载的改善。
关注公众号:程序新视界,一个让你软实力、硬技术同步提升的平台
除非注明,否则均为程序新视界原创文章,转载必须以链接形式标明本文链接
本文链接:https://www.choupangxia.com/2025/09/13/vitess-connectin-pooling/