连接池是管理数据库连接的软件组件。这可以通过多种方式帮助提高资源利用率,帮助实现负载平衡或故障转移,并且可以大大减少事务时间。在这篇博文中,我们将了解什么是连接池以及如何配置它。
连接池是一个软件组件管理数据库连接。这可以通过多种方式帮助提高资源利用率,帮助实现负载平衡或故障转移,并且可以大大减少事务时间。在这篇博文中,我们将了解什么是连接池以及如何配置它。
打开与数据库的连接需要许多步骤。我们需要连接到服务器并执行初始握手,就加密和连接设置达成一致,然后在所有层(网络驱动程序、操作系统层、数据库层等)中保留新的连接资源。每个连接都会消耗内存,内存大小取决于数据库引擎。对于 PostgreSQL,一个连接甚至可以使用 1.3MB 内存。打开连接也需要时间,因为我们需要协商新连接的设置。
如果我们不断为每个 SQL 查询打开新连接,可能会导致数据库服务器出现多个问题:
打开连接需要时间和资源,因此我们的交易速度较慢
我们可能会超出活动连接的限制(默认情况下可以设置为某个值)像一百个连接)
数据库可能会消耗更多内存,这可能会对缓存命中率和可用于查询的可用内存产生负面影响
而不是打开每个 SQL 查询都有一个新连接,我们可以池化连接。我们可以配置连接池来保留连接数量并为所有客户端重用它们。这样我们的应用程序连接到池化器而不是直接连接数据库,然后池化器连接到数据库。这带来了多个优点:
连接池使连接保持打开状态的时间更长,从而减少了数据库端打开和关闭连接的开销并减少了延迟。
我们可以在连接之间甚至数据库之间实现负载平衡,从而提高性能。
池化器可以维持稳定的连接数量,因此我们可以避免这个问题活动连接过多,会减少资源使用。
池化器可以重定向主服务器和备用服务器之间的连接,以提供故障转移,从而提高稳定性和可扩展性。
池化器可以将密码存储到数据库的中央位置,从而提高安全性。
池化器可以缓存结果以提高查询性能。
连接池也有一些缺点:
它是我们系统中可能成为故障点的另一个组件。
由于应用程序和数据库之间的另一个网络跃点,网络延迟可能会略有增加。
低效的连接池可能会成为瓶颈。
我们需要调整和维护连接池,这增加了维护负担。
有很多实现连接池的方法。在本节中,我们将了解各种实现细节。
在典型情况下,我们从应用程序连接到数据库。我们现在可以将连接池放在两个位置之一:应用程序本身或应用程序和数据库之间的某个位置。
将连接池放在应用程序中(应用程序端连接池)可以非常容易因为许多 ORM 或数据库驱动程序都支持开箱即用。例如,JDBC 支持 c3p0,而 ODBC 支持开箱即用。这带来了很多好处。我们不需要安装和维护任何额外的组件,因为池化器位于应用程序内部。我们只需要部署应用程序的新版本,然后就可以准备好池化了。这也减少了网络延迟,因为我们没有任何额外的网络跃点(一切都位于我们的应用程序内部)。
不幸的是,应用程序端连接池有一些缺点。最大的一个是它仅针对一个应用程序进行配置。如果我们有很多应用程序(尤其是在分布式环境中),那么我们需要在很多地方配置池化器。更不用说我们仍然可能达到服务器端的连接计数限制,因为池化器彼此不了解。拥有许多连接池也会导致更高的资源使用率,并且通常性能较低。
我们还可以使用位于应用程序和数据库之间的外部连接池。这可以与任意数量的应用程序一起使用,并让我们能够精确控制连接限制。集中式连接池还可以更好地控制资源,让我们实现故障转移或负载分配。
外部连接池也有一些缺点。首先也是最重要的,它是我们需要随着时间的推移安装、配置、调整和维护的另一个组件。我们还需要重新配置每个应用程序以使用连接池(这应该像更改一些连接字符串并重新部署应用程序一样简单)。外部池化器还会增加一些网络延迟,因为它是应用程序和数据库之间的另一个网络组件。
外部连接池化器也可能成为故障点。如果池化器由于某种原因而关闭,应用程序将无法再连接到数据库。如果池化器速度缓慢或效率低下,则会影响所有使用它的应用程序。因此,池化器必须具有高质量,才不会降低整体性能。
每个池化器需要决定如何将连接分配给客户端。通常有三种方法。
第一种是会话池。在这种方法中,连接在会话持续时间内分配给客户端(直到客户端断开连接或达到超时)。这是最简单的方法,但是,这有效地限制了客户端数量,因为通常每个客户端消耗一个连接。
下一个解决方案是事务池。在此方法中,池程序为每个事务分配连接,并且仅在事务持续时间内分配连接。如果客户端想要运行另一个事务,他们需要获得另一个连接(并且可能需要等待其他连接可用)。这允许池化器处理更多客户端,并且是推荐的方法。
最后一种方法是为每个 SQL 语句独立分配连接。理论上,这会带来最高的灵活性和连接利用率。但是,这会导致一项事务跨越多个连接。由于许多事务设置与连接相关,这可能会成为技术限制。
根据您使用的数据库类型,可能有一些内置的解决方案,或者您可能需要手动配置它们。让我们看一些示例。
根据您的基础设施提供商,您也许能够使用内置或近内置解决方案:
Neon PostgreSQL 数据库有一个内置的 PgBouncer
Supabase 有一个内置的 Supavisor
适用于 PostgreSQL 的 Azure 数据库支持内置 PgBouncer
DigitalOcean 的 PostgreSQL 包括 PgBouncer
Azure 数据库可与 ProxySql
Azure 数据库可与 Heimdall 数据库代理一起使用
ADO.NET 支持内置连接池
Oracle 支持通用连接池对于 JDBC
Oracle 自治数据库支持数据库驻留连接池
您可以使用许多外部解决方案使用:
Amazon RDS 代理
Pgpool
PgBouncer
奥德赛
Heimdall 数据库代理
ProxySQL
pgcat
在此示例中,我们将研究 PgBouncer。
我们首先按照文档中的方式安装它。
然后我们需要配置它。最重要的设置是:
pool_mode:如何处理连接;我们可以使用事务
max_client_conn:配置可以连接到连接池的客户端数量
default_pool_size:配置允许多少个服务器连接对于每个用户数据库
min_pool_size:要保留多少个备用连接
配置池化器后,我们可以使用pgbench验证其性能:
pgbench -c 10 -p -j 2 -t 1000 database_name
PgBouncer 可以轻松地将每秒事务数增加 60%,如基准测试所示:
对 PostgreSQL 连接池进行基准测试:PgBouncer、PgCat和 Supavisor
通过连接池提高数据库性能
使用 PgBouncer 增强 PostgreSQL
连接池可以提高性能并减少资源消耗。有许多内置解决方案可以轻松地与我们的数据库一起使用,无论我们将它们托管在哪里以及我们使用什么数据库引擎。我们需要记住,连接池是另一个故障点,需要小心处理。配置良好的连接池可以使每秒的事务数量增加近一倍,从而极大地提高性能。
以上是配置连接池的详细内容。更多信息请关注PHP中文网其他相关文章!