连接池策略:好,坏或丑?

时间:2009-09-21 20:28:33

标签: java mysql database tomcat connection-pooling

我负责开发和维护一组以类似数据为中心的Web应用程序。我当时决定的架构是每个应用程序都有自己的数据库和Web-root应用程序。每个应用程序都维护一个连接池到它自己的数据库和一个用于共享数据的中央数据库(登录等)

一位同事一直认为这种策略不会扩展,因为有这么多不同的连接池将无法扩展,我们应该重构数据库,以便所有不同的应用程序使用单个中央数据库和任何修改系统可能是唯一的,需要从该数据库中反映出来,然后使用由Tomcat提供支持的单个池。他假定有很多“元数据”在网络中来回传递,以维护连接池。

我的理解是,通过适当的调整,在不同的池中使用尽可能多的连接(小批量应用程序获得更少的连接,大批量应用程序获得更多,等等)池的数量连接数相比无关紧要,或者更正式地说,与1个30个连接池相比,维护3个10个连接池所需的开销差异可以忽略不计。

最初将系统分解为单应用程序一数据库设计背后的原因是应用程序之间可能存在差异,并且每个系统都可以根据需要对架构进行修改。同样,它消除了系统数据流入其他应用程序的可能性。

不幸的是,公司没有强有力的领导作出艰难的决定。虽然我的同事只是模糊地支持他的担忧,但我想确保理解多个小型数据库/连接与一个大型数据库/连接池的分支。

6 个答案:

答案 0 :(得分:10)

您的原创设计基于合理的原则。如果它对您的情况有帮助,则此策略称为horizontal partitioning or sharding。它提供:

1)更高的可扩展性 - 因为如果需要,每个分片可以存在于单独的硬件上。

2)更高的可用性 - 因为单个分片的失败不会影响其他分片

3)更高的性能 - 因为被搜索的表具有更少的行,因此索引更小,从而产生更快的搜索。

您同事的建议会让您进入单点故障设置。

关于3个大小为10的连接池与1个大小为30的连接池的问题,解决这个争论的最佳方法是使用基准测试。单独配置您的应用程序,然后使用ab(Apache Benchmark)进行一些压力测试,看看哪种方式表现更好。我怀疑不会有显着的差异,但做基准来证明它。

答案 1 :(得分:4)

如果您有一个数据库和两个连接池,每个连接池有5个连接,则您有10个与数据库的连接。如果您有5个连接池,每个连接池有2个连接,则您有10个与数据库的连接。最后,您有10个与数据库的连接。数据库不知道您的池存在,没有意识。

池和DB之间交换的任何元数据都将在每个连接上发生。当连接开始时,连接被拆除等等。因此,如果你有10个连接,这个流量将发生10次(至少,假设它们在池的整个生命周期内保持健康)。无论您有1个游泳池还是10个游泳池,都会发生这种情况。

至于“每个应用程序1个数据库”,如果你不是为每个数据库与单独的数据库实例交谈,那么它基本上没关系。

如果您有一个托管5个数据库的数据库服务器,并且您与每个数据库建立了连接(例如,每个连接2个连接),那么与托管单个数据库的同一个数据库相比,这将消耗更多的开销和内存。但这种开销最多只是微不足道的,而且在具有GB大小的数据缓冲区的现代机器上完全无关紧要。超过某一点,所有数据库关心的是将数据页面从磁盘映射和复制到RAM并再次返回。

如果您在数据库中有一个重复的大型冗余表,那么这可能会造成浪费。

最后,当我使用“数据库”这个词时,我的意思是服务器用来合并表的逻辑实体。例如,Oracle真的喜欢每个服务器有一个“数据库”,分解为“模式”。 Postgres有几个DB,每个DB都可以有模式。但无论如何,所有现代服务器都具有可以使用的逻辑数据边界。我这里只是使用“数据库”这个词。

因此,只要您为所有应用程序点击数据库服务器的单个实例,连接池等在整体上并不重要,因为服务器将共享所有内存和资源必要时跨越客户。

答案 2 :(得分:2)

很好的问题。我不知道哪种方式更好,但您是否考虑过以这样的方式设计代码:您可以在尽可能少的痛苦的情况下从一种策略切换到另一种策略?也许可以使用一些轻量级数据库代理对象来掩盖来自更高级代码的此设计决策。以防万一。

答案 3 :(得分:1)

数据库和开销方面,1个具有30个连接的池和3个具有10个连接的池大致相同,假设两种情况下的负载相同。

应用程序方面,让所有数据通过单个点(例如服务层)与具有每个应用程序访问点之间的区别可能非常大;在性能和易于实现/维护方面(例如,考虑必须使用分布式缓存)。

答案 4 :(得分:0)

嗯,这是一个很好的问题,但使用多种数据库(A)方法或大型方法(B)进行讨论并不容易:

  1. 这取决于数据库本身。 Oracle,例如在Sybase(因此也就是LOCK)策略方面与Sybase ASE的行为不同。最好使用几种不同的&如果存在大量并行写入并且数据库正在使用悲观锁定策略(Sybase),那么小数据库可以将锁争用率保持在较低水平。
  2. 如果小数据库的表空间没有分布在多个磁盘上,最好使用一个大数据库来仅使用一个(缓冲区/缓存)内存。我认为这种情况很少发生。
  3. 使用(A)是因为与性能不同的原因而更好地进行缩放。您可以在需要时在不同的(更新/更快)硬件上移动热点数据,而无需触及其他数据库。在我以前的公司,这种方法总是比变种(B)便宜(没有新的许可证)。
  4. 我个人更喜欢(A)原因3。

答案 5 :(得分:0)

当没有常识或简单的数学背后,设计,架构,计划和伟大的想法都会失败。一些更多的练习和/或经验有帮助...这里有一个简单的数学计算,为什么10个连接5个连接的池与1个连接50个连接池不同: 每个池都配置了min&最大开放连接,事实是它通常会使用(99%的时间)最小数量的50%(在5分钟的情况下为2-3),如果它使用的更多,那么这个池配置错误,因为它是一直打开和关闭连接(昂贵)...所以我们10个池,每个连接5分钟= 50个开放连接...意味着50个TCP连接;在它们之上有50个JDBC连接......(你调试了JDBC连接吗?你会惊奇地发现了两种元数据流...) 如果我们有1个池(服务于上面的相同基础设施),我们可以将min设置为30,因为它可以更有效地平衡额外的...这意味着减少20个JDBS连接。我不了解你,但对我来说这是很多...... 细节中的魔鬼 - 你在每个游泳池中留下的2-3个连接,以确保它不会一直打开/关闭...... 甚至不想进入10池管理的开销......(我不想每隔一个维护10个池,那么另一个,不是吗?) 现在你让我开始这个,如果是我,我会用一个应用程序(任何人的服务层?)“包装”数据库(数据源),它将提供差异服务(REST / SOAP / WS / JSON - 选择你的毒药)和我的应用程序甚至不会知道JDBC,TCP等等哦,等谷歌有它 - GAE ......