随着问问题的同学越来越多,公众号内部私信回答问题已经很困难了,所以建立了一个群,关于各种数据库的问题都可以,目前主要是 POSTGRESQL, MYSQL ,MONGODB ,POLARDB ,REDIS 等,期待你的加入
最近很忙没有时间,但年前的一个群里的问题,引发了我写这个帖子的想法,现在闲下来了,可以来捋一捋这个问题。因为是杂谈,所以想到哪里写哪里,可能没有一定的条理性。
一般连接数的这个问题到底应该由谁来负责的这个问题,是应该被注重的,到底应该是谁,这里有以下的一些选择
1 应用程序的架构方给定一定的标准
2 应用程序中懂得业务逻辑的程序部分给出大致的数据设置的想法
3 数据库方给出数据库在不同的配置下可以给出的一个设置的范围
以上的这些数据设置两个部分
1 最大连接数
2 瞬时最大可以承受的并发连接数
3 在业务低峰期可以保留的长时间与数据库的保留连接数
为什么要这样来组织连接数的设置主要考虑有三个部分
1 业务架构有必要和能力来给出业务架构中的每个模块的在程序部分的理论的连接数需求,通过连接数需求来引导整体架构的设计,而不是应用架构设计完毕,在来讨论连接数,那么这样压力就直接传导到 数据库,变成一个风险和忍受的问题。
2 业务逻辑方必须了解你的应用需求的问题,你的应用在设计之初的业务需求特性是什么是短时间高强度的连接方式,还是绵延不绝的数据库连接方式,是OLTP 多 还是OLAP 多的数据库使用属性,这些都要进行规整和规划。
3 数据库硬件和数据库本身来规划数据库连接数的问题,到了这个维度的情况下,实际上已经是下下之策了,因为数据库只能是承受方,能做的工作不多,所以到这个维度的时候,就离出问题不远了。
但即使这样搞,一个连接数调整和设置的关键还未深入触及,我们要讨论的连接数实际上有两个部分 1 理论连接数 2 实际连接数
理论连接数这个部分来自于数据库厂商的一些对于数据库方法的理论来给出一个数据库硬件本身可以接受的连接数。基本主要围绕了三个部分,
1 CPU 核心数
2 内存的大小
3 磁盘IOPS 的快慢
这三者之间的关系也分别为,CPU 的核心数,大家都了解核心数对于并行执行任务的重要性,CPU主要可以支持很多的任务的部分的主要关键在于任务的占用CPU的时长和CPU 本身的核心数对应任务之间的对比。
我们引入这样一个公式来计算你的应用系统在数据库层面大概需要的CPU 核心数
并发任务数 * 任务的执行时间系数(必须大于1) = 你在瞬时需要的CPU核心数
举例你的并发任务是在同一秒为5个任务,而每个任务执行的时间在1.5秒,那么你的系数可以确认在1.5左右
5 * 1.5 = 7.5 个CPU ,我们可以等同于 8 个CPU ,可以满足你的任务的需求,但实际上这里有一个无法避免的问题,在于系数的确认,实际上这是一个非常困难的任务,系数针对与你在数据库中运行的多个任务,那么怎么确定这个系数。
系数的确定
系数的确定实际上是一个非常困难的工作,但是否可以做到,答案是肯定的,那么我们需要什么资源来确认这个系数,测试,业务测试可以确认这个系统,尤其是压力方面的业务测试。在测试中,我们找到一个硬件配置下,这个系统最大的并发的抛物线的定点,此时这时的并发数和CPU的数,就变成了我们可以确认的信息。如
并发任务 16个 / 8核心CPU = 2 则经过压测后,我们这个业务的系数就可以定制为2
那么最终我们在这个业务中的数据库产品可以通过硬件的CPU 来标定大概的业务并发支持
8 * 2 = 16
16 * 2 = 32
以此类推。
那么这样来确认CPU 与并发连接数的关系合理吗。实际上也不合理,我们忘记了另一个核心的硬件部分 内存。
内存部分如何进行标定,连接内存与连接数的设置,如我们的POSTGRESQL 部分,我们的work_mem是我们需要注意的连接内存,在我们设置了大量的 shared_buffer后,我们剩余的内存的一部分多少,作为我们的连接内存。
这也是一个决定连接数的,或者说最大连接数的部分的设定。如我们的内存为32G .postgresql 在 shared buffer中的设置为 8G 则给我们剩余的内存为
32 - 8 - 2 -16 -2 = 4G,那么我们具体可以使用的连接的内存有 6G ,按照我们的work_mem =16MB 来计算我们可以最大支持的连接数为250个。
通过这样的方式我们可以很简单的逻辑推算出,实际中我们可以使用的最大连接数。(上述公式中 8 为shared buffer , 2 为系统预留,16为 file cache ,2 为 maintance meory)
所以一个决定MAX connections 内存最大的部分在于你的 work_mem 设计的大小,而这个大小有关于你所在的业务的部分的对于语句和事务的定义。
所以我们的最大的MAX_CONNECTION 的公式可以定义为
剩余的内存 / 连接内存初始设定 = 最大连接数 *(1-压测后的系数) = 最终最大连接数
那么这个部分的系数是比较难获得,主要是要观察你的数据库系统下压测中是否有大量的连接,在本地进行数据的缓冲,那么可以这样在数据库压测中根据压测的时间长度和存在的数据库的连接中,出现使用磁盘作为缓冲的查询数之比,作为这个系数。
举例我们在1000个查询中,发现有50个出现了使用本地磁盘方式进行数据处理的连接则上面的练习为
4G /16MB = 250 * (1 - 0.05) = 250 * 0.95 = 237 个最大的连接
当然这里面看上去这些数值的设计和获取有些矫情,但对于一个正规的,可以标准化的大型企业,这些有是必须的,而不是可有可无的。
磁盘本身,实际上可以根据你在压测中的磁盘的不同匹配来获得另一个系数,并可以附加到上面的 最大连接数 和 最大并发数的设计中。
但是实际上,一个数据库可以承受的最大连接数和并发数,是很难非常标准化的,我们举一些列子来证明
1 某公司的应用产品,需要部署到数据库上,但是此数据库已经是很多应艳红程序的数据库,其中数据库中包含了大量不同的应用产品,OLAP OLTP 均有,所以以上的公式,在这样的节约成本的企业基本上是无效的。
给我们的现实的部分,只有等到这个数据库本身无法进行运作了,发生问题了才会进入正题,进行应用的分库的操作。
2 某公司应用程序,在数据库上一直进行扩展,并且数据库已经成为系统的瓶颈了,但是业务一直不进行架构的整改,拆分,在这样的情况下,数据库报警成为常态,最终无人关心报警,最终数据库DOWN机,导致重大生产事故。
上面这样的例子我还能举出很多,一个好的数据库所需要的不光是一个好的数据库管理员,而是一个好的架构师,一个靠谱的业务逻辑规划和程序员,综合的进行规划和业务上线前的大量的测试工作,而截至到目前那些公司可以做到这点。
所以一个公式或者标准或理论连接数,最大连接数带给了我们什么,是一个看上去很美的空壳,还是一个我们可以实际上可以操作的标准。