数据库连接池大小的调整原则

配置连接池是开发人员经常犯的错误。配置池时需要理解几个原则(对于某些人来说可能违反直觉)。

想象一下,您有一个网站,虽然可能不是 Facebook 规模的,但仍然经常有 10,000 个用户同时发出数据库请求,每秒处理约 20,000 笔交易。您的连接池应该有多大?

你可能认为连接池越大越好!

问题不在于有多大,而在于有多小!

在没有任何其他更改的情况下,仅减少连接池大小即可将应用程序的响应时间从约 100 毫秒减少到约 2 毫秒,提高了 50 倍以上。
观看来自 Oracle Real-World Performance 小组的这段简短视频(点击标题)

同理,为什么仅使用 4 个线程的nginx Web 服务器就可以远远优于具有100 个进程的Apache Web 服务器?

即使是只有一个 CPU 内核的电脑,也能 "同时 "支持数十或数百个线程。但我们都[应该]知道,这不过是操作系统利用时间切片魔法玩的把戏。实际上,单个内核一次只能执行一个线程,然后操作系统会切换上下文,让该内核执行另一个线程的代码,以此类推。在单个 CPU 资源的情况下,顺序执行 A 和 B 总比通过时间切分 "同时 "执行 A 和 B 快,这是计算的基本定律。一旦线程数超过 CPU 内核数,增加线程的速度只会更慢,而不会更快。

资源有限
虽然不像上面说的那么简单,但也差不多了。还有其他一些因素在起作用。我们可以将数据库的主要瓶颈归纳为三个基本类别:CPU、磁盘和网络。我们可以把内存也加进去,但与磁盘和网络相比,带宽相差几个数量级。

如果我们忽略磁盘和网络,情况就会很简单。在一台有 8 个计算核心的服务器上,将连接数设置为 8 就能获得最佳性能,而超过这个数后,由于上下文切换的开销,速度就会开始变慢。但我们不能忽视磁盘和网络。数据库通常将数据存储在磁盘上,磁盘传统上由旋转的金属板组成,读/写头安装在步进电机驱动的机械臂上。读/写头一次只能位于一个位置(为单次查询读/写数据),必须 "寻道 "到新的位置才能为不同的查询读/写数据。因此会产生寻道时间成本和旋转成本,即磁盘必须等待数据在盘片上 "再次旋转 "才能读/写。缓存当然在这方面有所帮助,但原理仍然适用。

在这段时间内("I/O 等待"),连接/查询/线程只是被 "阻塞",等待磁盘。而在这段时间里,操作系统可以通过为另一个线程执行更多代码来更好地利用 CPU 资源。因此,由于线程在 I/O 时会被阻塞,我们实际上可以通过连接/线程数量大于物理计算核心数量来完成更多工作。

多多少?我们拭目以待。至于多多少,还取决于磁盘子系统,因为较新的固态硬盘驱动器没有 "寻道时间 "成本或旋转因素。不要受骗上当,认为 "固态硬盘速度更快,因此我可以拥有更多线程"。这完全是180度的倒退。速度更快、无寻道、无旋转延迟意味着阻塞更少,

因此更少的线程(更接近核心数)比更多的线程性能更好。
只有当阻塞为执行创造机会时,更多线程才会有更好的表现。

网络与磁盘类似。当发送/接收缓冲区填满并停滞时,通过以太网接口向外写入数据也会造成阻塞。万兆以太网接口的阻塞小于千兆以太网接口,而千兆以太网接口的阻塞小于百兆以太网接口。但就资源阻塞而言,网络是第三名,有些人在计算时经常忽略它。


在上述 PostgreSQL 基准中,您可以看到 TPS 率在连接数达到 50 个左右时开始趋于平稳。在甲骨文的上述视频中,他们展示了将连接数从 2048 降到 96 的过程。我们认为即使是 96 个连接也可能过高,除非您使用的是 16 核或 32 核的服务器。

设置数据库连接池的公式

下面的公式是 PostgreSQL 项目作为起点提供的,但我们相信它在很大程度上适用于所有数据库。您应该测试您的应用程序,即模拟预期负载,并围绕这个起点尝试不同的池设置:

连接数 = ((core_count * 2) + effective_spindle_count)

猜猜这意味着什么?

你有台只有一个硬盘的 4 核 i7 服务器,运行的连接池应该是9 = ((4 * 2) + 1).
整数为 10。

看起来少吗?试试看吧,我们打赌,在这样的设置下,您可以轻松处理 3000 名前端用户以 6000 TPS 的速度运行简单查询。

如果运行负载测试,您可能会发现 TPS 率开始下降,而前端响应时间开始攀升,因为您(在给定的硬件上)将连接池推到了 10 以上。

为了避免死锁而计算池大小是一个相当简单的资源分配公式:
池大小 = T n x (C m - 1) + 1
其中T n是最大线程数,C m是单个线程持有的最大同时连接数。
例如,假设有三个线程 ( T n =3 ),每个线程需要四个连接来执行某些任务 ( C m =4 )。确保永远不会出现死锁所需的池大小为:
池大小 = 3 x (4 - 1) + 1 = 10
另一个例子,您最多有八个线程 ( T n =8 ),每个线程需要三个连接来执行某些任务 ( C m =3 )。确保永远不会出现死锁所需的池大小为:
池大小 = 8 x (3 - 1) + 1 = 17
这不一定是最佳池大小,而是避免死锁所需的最小值。

在某些环境中,使用 JTA(Java 事务管理器)可以通过将 getConnection() 中的同一连接返回给已在当前事务中持有连接的线程,从而大大减少所需的连接数。

总结
池大小最终取决于部署。

例如,混合有长时间运行的事务和非常短的事务的系统通常是最难使用任何连接池进行调整的。在这些情况下,创建两个池实例可以很好地发挥作用(例如,一个用于长时间运行的作业,另一个用于“实时”查询)。

在主要具有长时间运行事务的系统中,所需连接数量通常存在“外部”约束,例如作业执行队列仅允许同时运行一定数量的作业。在这些情况下,作业队列大小应“大小合适”以匹配池(而不是相反)。

https://www.jdon.com/69541.html ​​​​​​​

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/128459.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

力扣第1049题 最后一块石头的重量Il c++ 动态规划(01背包)

题目 1049. 最后一块石头的重量 II 中等 相关标签 有一堆石头&#xff0c;用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。 每一回合&#xff0c;从中选出任意两块石头&#xff0c;然后将它们一起粉碎。假设石头的重量分别为 x 和 y&#xff0c;且 x <…

网络工程师应知应会:基础知识(5)

一、防火墙区域结构 防火墙按安全级别不同&#xff0c;可划分为内网、外网和 DMZ 区。 (1) 内网。 内网是防火墙的重点保护区域&#xff0c;包含单位网络内部的所有网络设备和主机。该区域是可信的&#xff0c;内网发出的连接较少进行过滤和审计。 (2) 外网。 外网是防火墙重…

面试算法51:节点值之和最大的路径

题目 在二叉树中将路径定义为顺着节点之间的连接从任意一个节点开始到达任意一个节点所经过的所有节点。路径中至少包含一个节点&#xff0c;不一定经过二叉树的根节点&#xff0c;也不一定经过叶节点。给定非空的一棵二叉树&#xff0c;请求出二叉树所有路径上节点值之和的最…

9.Vue前端使用iframe集成帆软报表的单点登录

一、背景 需要把帆软报表内嵌到若依里面来。 二、帆软设置 2.1 帆软报表的url 打开帆软后端里面的【目录管理】查看具体报表的url 帆软报表的具体地址为: Frm聚合报表地址: 【帆软的服务http】+【/webroot/decision/view/form?viewlet=demo/demo.frm】 CPT普通报表的地…

查询和下载“省市县乡村“五级行政区划

背景信息 在更新完CTAmap1.12版本之后&#xff0c;我想继续完善这个系列的数据&#xff0c;把时间范围往前更新是基础&#xff0c;但如何展现多年的数据是个值得解决的问题。 如何展现多个年份的行政区划&#xff1f;我的思考是用思维导图的形式&#xff0c;简单明了。既然要…

WSL1 安装 debian xfce 用xrdp 导入远程桌面

凑合能用 晃晃行 晃晃不行 而且比较卡 还经常报崩溃 sudo apt install xfce4 xfce4-goodies xorg dbus-x11 x11-xserver-utils apt install locales -y 安装过完应该会提示设置locales&#xff0c;如果安装完之后想要更改相关设置&#xff0c;可以使用如下命令重新设置loca…

Github 自动化部署到GitHub Pages

1.准备工作 新建仓库 新建项目 配置 vite.config.ts base: ./,部署应用包时的基本URL&#xff0c;例&#xff1a;vue-cli 5.x 配置 publicPath 推送到远程仓库 2.配置 GitHub Token 点击 Settings -> Actions -> General 找到 Workflow permissions&#xff0c;选中第…

【java学习—十】操作集合的工具类Collections(8)

文章目录 1. 操作集合的工具类&#xff1a; Collections2. 应用3. 查找、替换3.1. max 与 min3.2. 根据Comparator返回max(min) 3.3. frequency 与 replaceAll4. 同步控制 1. 操作集合的工具类&#xff1a; Collections Collections 是一个操作 Set 、List 和 Map 等集合的工具…

Spring XML使用CASE WHEN处理SELECT字段

在日常开发中&#xff0c;经常会碰到需要导出的情况。而一些枚举值或者状态一般是定义成整型&#xff0c;这个时候需要对数据进行转换&#xff0c;转换成对应的文本再导出。 在XML中用CASE WHEN来根据不同的查询结果做不同的处理。 比如 SELECT name AS 姓名, age AS 年龄 C…

红黑树——插入底层实现【C++】面试重灾区!!

目录 前言 一&#xff0c;概念 定义 二&#xff0c;insert 情况一&#xff1a; 情况二&#xff1a; 情况三&#xff1a; insert代码 三&#xff0c; 红黑树验证(面试题) 产生随机数验证 每日一图区&#xff1a; 前言 AVL树是一棵绝对平衡的二叉搜索树&#xff0c;其…

shell script中的数值运算declare和$((运算式 ))

linux中变量定义默认是字符串类型&#xff0c;如要进行数值运算&#xff0c;需要先声明变量类型&#xff0c;或者通过固定格式来计算 看案例 如果不通过固定格式&#xff0c;直接 echo 55 如图&#xff0c;结果显示的55本身 可以写成 declare -i var#声明变量integrate类型&…

ref、reactive、toRef、toRefs

ref 作用&#xff1a;定义一个响应式数据 语法&#xff1a;const xxx ref(initValue) 创建一个包含响应式数据的引用对象 js中操作数据&#xff1a;xxx.value 模板中读取数据&#xff1a;不需要.value,直接<div>{{xxx}}</div> 接收的数据&#xff1a;基本类型、对…

【aspose之三】【springboot】java使用aspose.html 的cloud版html转pdf,html2pdf

前言 把url网页或本地文件html转换pdf 一、html转pdf 一&#xff09;代码实现 1.maven配置 <dependency><groupId>com.aspose</groupId><artifactId>aspose-html-cloud</artifactId><version>22.12.1</version></dependency>…

计算机视觉 计算机视觉识别是什么?

计算机视觉识别&#xff08;Computer Vision Recognition&#xff09;是计算机科学和人工智能领域中的一个重要分支&#xff0c;它致力于使计算机系统能够模拟和理解人类视觉的过程&#xff0c;从而能够自动识别、分析和理解图像或视频中的内容。这一领域的发展旨在让计算机具备…

python---数据类型(列表)

组织列表 使用sort()方法对列表永久性排序 按照字母顺序排序&#xff1a; motorcycles [chunlan, yamaha, dayun, jianshe]motorcycles.sort()print(motorcycles) 字母倒序&#xff1a; motorcycles [chunlan, yamaha, dayun, jianshe]motorcycles.sort(reverseTrue)pri…

SQL server数据库定时搜索

问题现象 出现下图问题&#xff0c;导致连接该数据库的程序不能正常启动 解决办法 定时搜索数据库 脚本 # 设置数据库名称 # 设置定时任务时间# 生成定时任务执行sql文件 sql语句 USE [master] GO ALTER DATABASE volador SET RECOVERY SIMPLE WITH NO_WAIT GO ALTER DA…

软件测试:压力测试详解

压力测试 压力测试是一种软件测试&#xff0c;用于验证软件应用程序的稳定性和可靠性。压力测试的目标是在极其沉重的负载条件下测量软件的健壮性和错误处理能力&#xff0c;并确保软件在危急情况下不会崩溃。它甚至可以测试超出正常工作点的测试&#xff0c;并评估软件在极端…

java中main方法和@Test注解的区别

Java的main方法和Test注解在用途和功能上有很大的区别。 main方法是Java应用程序的入口点。当你运行一个Java程序时&#xff0c;JVM会首先查找具有public static void main(String[] args)签名的类&#xff0c;并从这个方法开始执行程序。main方法通常用于控制程序的启动、执行…

界面控件DevExpress WPF Gauge组件 - 轻松实现个性化商业仪表盘

DevExpress WPF Gauge&#xff08;仪表&#xff09;控件包含了多种圆形仪表类型、水平和垂直线性仪表、分段和矩阵数字仪表以及状态指示器&#xff0c;同时还具有最终用户交互性的集成支持。 P.S&#xff1a;DevExpress WPF拥有120个控件和库&#xff0c;将帮助您交付满足甚至…

自适应H5樱花个人网站引导页导航源码SEO增强版

懂前端和 PHP 技术想更改前端页面的可以看&#xff1a;网站的前端页面不好看&#xff0c;你可以查看 index 目录&#xff0c;内有参数 txt 文本里面记录了前端页面所使的关键 JS 代码和 php 代码&#xff0c;只需要稍加复制粘贴修改到新的前端页面就可以了&#xff01;主目录的…