我们说我正在存储Person(id, country_id, name)
的数据。并且让我们说用户刚刚发送了id和country_id,然后我们发回了这个名字。
现在我有一个db和2个webserver,每个webserver保持一个20连接的连接池(例如c3p0)。
这意味着db正在维护40个连接,每个Web服务器维护20个连接。
分析上面的系统,我们可以看到我们使用了连接池,因为人们说"创建数据库连接很昂贵"
这一切都有意义
现在让我说我在country_id
上分享表数据,所以现在可能有200分贝,也假设我们的应用现在很流行,我们需要有50个网络服务器。
现在,上面的连接池策略失败,就好像每个Web服务器在池中为每个数据库保留20个连接一样
这意味着每个网络服务器将具有20 * 200 db = 4000连接
每个数据库将有50个Web服务器* 20 = 1000连接。
这听起来并不好,所以我得到了一个问题,为什么要使用连接池,每个网页请求创建1个连接的开销是多少?
所以我运行一个测试,我看到DriverManager.getConnection()
在localhost上平均需要20毫秒。
每次请求额外20毫秒不是游戏杀手
问题1:每个网络请求使用1个连接还有其他缺点吗?
问题2:互联网上的人们说"数据库连接很昂贵"。有哪些不同的开支?
PS:我也看到pinterest做同样的https://medium.com/@Pinterest_Engineering/sharding-pinterest-how-we-scaled-our-mysql-fleet-3f341e96ca6f
答案 0 :(得分:2)
如果您有一个繁忙的网站,并且每个对数据库的请求都会打开并关闭一个连接,那么您就已经死了。
您测量的20ms用于localhost
连接。我不认为你的所有50个网络服务器都在localhost
...
除了建立和关闭数据库连接所花费的时间之外,它还使用数据库服务器上的资源。这主要是CPU,但也可能存在对内核数据结构的争用。
此外,如果你允许几千个连接,没有任何东西可以防止所有人同时忙碌,在这种情况下你的数据库服务器将会超载并且没有响应,除非它有几千个内核(甚至那么你' d受到锁争用的限制。)
您的解决方案是pgBouncer等外部连接池。
答案 1 :(得分:2)
除连接创建&连接关闭周期是一项耗时的任务(即成本高昂),还可以进行池化以控制与数据库同时打开的连接数,因为数据库服务器可以处理的并发连接数有限制。当你这样做时,每个请求有一个连接,你就失去了控制权,你的应用程序总是有可能在高峰负载时崩溃。
其次,您将不必要地将Web服务器容量与数据库容量联系起来,目标也是将数据库连接管理视为开发人员关注的问题,而不是基础架构问题。您是否愿意根据他/她的代码控制为开发人员打开生产应用程序的数据库连接?
在传统的单片应用程序服务器(如Weblogic,JBoss,WebSphere等)中,其sys管理员将根据db serer容量创建连接池,并将JNDI名称传递给开发人员以使用。开发人员的工作仅限于使用该JNDI获取连接。
接下来,如果数据库在各种独立应用程序之间共享,那么池化会让您知道您向哪个应用程序提供的内容。有些应用程序可能需要更多数据,有些应用程序可能不那么密集。
传统的资源泄漏问题,即当开发人员忘记干净地关闭他们的连接时,也需要使用池。
总而言之 - 集合背后的想法是让开发人员只关心使用连接并完成工作,而不是担心打开和关闭它。如果连接未在X分钟内使用,则每个配置将返回到池。