Java多线程应用程序中优化数据存储库的使用技巧
yuyutoo 2024-10-12 01:03 1 浏览 0 评论
当执行的查询数量很大时,数据存储库通常是高要求系统的瓶颈。延迟批处理执行器(DelayedBatchExecutor)是一个组件,可通过在Java多线程应用程序中对所需查询进行批处理来减少所需查询的数量。
n个查询1个参数与1个查询n个参数
让我们假设一个Java应用程序执行对关系数据库的查询,以在给定其唯一标识符(id)的情况下检索Product实体(行)。
查询看起来像这样:
现在,要检索n种产品,可以通过两种方法进行:
- 对一个参数执行n个独立查询:
使用IN运算符或OR的组合,对n个参数执行一次查询以同时检索n个产品
后者在网络流量和数据库服务器资源(CPU和磁盘)方面更为有效,因为:
- 到数据库的往返次数为1,而不是n。
- 数据库引擎针对n个参数优化了其数据遍历过程,即,它可能只需要对每个表进行一次扫描而不是n次扫描。
这不仅适用于SELECT操作,而且适用于其他操作,例如INSERT,UPDATE和DELETE,实际上,JDBC API包括这些操作的批处理操作。
这同样适用于NoSQL存储库,其中大多数都显式提供BULK操作。
延迟批处理执行器
需要从数据库检索数据的Java应用程序(如REST微服务或异步消息处理器)通常实现为多线程应用程序(* 1),其中:
- 每个线程在其执行的某个时刻执行相同的查询(每个查询具有不同的参数)。
- 并发线程数很高(每秒数十或数百)。
在这种情况下,数据库很可能在很短的时间间隔内多次执行相同的查询。
如前所述,如果将这1个参数的n个查询替换为具有n个参数的单个等效查询,则应用程序将使用较少的数据库服务器和网络资源。
好消息是,可以通过以下涉及时间窗口的机制来实现它 :
第一个尝试执行查询的线程将打开一个时间窗口,因此其参数存储在列表中,并且该线程已暂停。在时间窗口内执行相同查询的其余线程会将其参数添加到列表中,并且也会被暂停。此时,尚未在数据库上执行任何查询。
时间窗口结束或列表已满(预先定义了最大容量限制)后,便会使用列表中存储的所有参数执行单个查询。最后,一旦数据库提供了该查询的结果,每个线程将接收其相应的结果,并且所有线程将自动恢复。
我为自己(延迟批处理执行器)构建了此机制的简单轻便的实现,可以轻松在新的或现有的应用程序中使用。它基于 Reactor库,并且使用带有通量的Flux缓冲发布者作为参数列表。
使用延迟批处理执行器的吞吐量和延迟分析
让我们假设一个针对产品的REST微服务,它公开了一个端点,用于从给定的数据库中检索产品数据 productId。如果不使用 延迟批处理执行器,则说到端点每秒有200次命中,则数据库每秒执行200个查询。如果端点使用的 时间窗口延迟批处理执行器配置为50毫秒,最大容量 = 10个参数,则数据库每秒仅执行20个查询,每个参数10个参数,但代价是最多在50毫秒内增加延迟(* 2)对于每个线程执行。
换句话说,为了将等待时间增加50 ms(* 2),在保持系统整体吞吐量的同时,数据库每秒收到的查询减少了10倍。
其他有趣的配置:
- 窗口时间 = 100毫秒,最大容量 = 20个参数→20个参数的10个查询(查询减少20倍)
- 窗口时间 = 500毫秒,最大容量 = 100个参数→2个查询,共100个参数(查询减少100倍)
延迟批处理执行器在行动
深入研究Product微服务示例,假设对于每个传入的HTTP请求,微服务的控制器都要求我们检索提供其ID的Product(Java Bean),因此它将调用该方法:
public Product getProductById(Integer productId) DAO组件的ProductDAO。
让我们看看不带和带的DAO的实现 延迟批处理执行器。
没有延迟批处理执行器
使用延迟批处理执行器
首先,延迟批处理执行器必须在DAO中创建的实例,在本例中为delayedBatchExecutorProductById。它需要以下三个参数:
- 时间窗口(在此示例中为50毫秒)
- 参数列表的最大容量(在此示例中为10个参数)
- 将使用参数列表调用的方法(我们将在后面详细介绍)。在此示例中,方法是retrieveProductsByIds
注意:我们将在后面看到为什么延迟批处理执行器的标识(delayedBatchExecutor ProductById)是该类的实例DelayedBatchExecutor2<Product, Integer>
其次,DAO方法public Product getProductById(Integer productId)已经过重构,可以简单地调用实例的execute方法,仅此delayedBatchExecutor ProductById而已。所有的“魔术”都是由DelayedBatchExecutor。
之所以delayedBatchExecutor ProductById是的实例,DelayedBatchExecutor2<Product, Integer>是因为其execute方法返回一个Product实例并接收一个Integer实例作为其参数。因此,我们有: DelayedBatchExecutor2<Product, Integer>.
如果execute方法需要接收两个参数(例如an Integer和a String)并返回的实例Product,则定义为DelayedBatchExecutor3<Product, Integer,String> ,依此类推。
最后,该 retrieveProductsByIds方法必须返回a List<Product>并接收a List<Integer>作为参数。
如果我们使用DelayedBatchExecutor3<Product, Integer,String>,则retrieveProductsByIds必须是List<Product> retrieveProductsByIds(List<Integer> productIdsList, List<String> stringList)
就是这样。
一旦运行,执行控制器逻辑的并发线程将getProductById(Integer id)在某个时候调用该方法,并且该方法将返回相应的乘积。他们不会知道他们实际上可能已经被暂停并恢复了延迟批处理执行器.
超越数据仓库
尽管本文与数据存储库有关, 延迟批处理执行器 但是可以在其他上下文中使用,例如,在对REST微服务的请求中。同样,用一个参数启动n个GET请求要比使用n个参数启动1个GET要昂贵得多。
延迟批处理执行器的改进
我创建 延迟批处理执行器并使用了一段时间,以有效地处理由个人项目中的并发线程启动的多个查询的执行。我相信它对其他人也可能有用,所以我决定将其公开。
话虽如此,仍有很大的改进空间并可以扩展所提供的功能 延迟批处理执行器。最有趣的是能够根据执行的特定条件动态更改参数 延迟批处理执行器(窗口时间和最大容量),以最大程度地减少等待时间,同时利用具有n个参数的查询。
相关推荐
- jQuery VS AngularJS 你更钟爱哪个?
-
在这一次的Web开发教程中,我会尽力解答有关于jQuery和AngularJS的两个非常常见的问题,即jQuery和AngularJS之间的区别是什么?也就是说jQueryVSAngularJS?...
- Jquery实时校验,指定长度的「负小数」,小数位未满末尾补0
-
在可以输入【负小数】的输入框获取到焦点时,移除千位分隔符,在输入数据时,实时校验输入内容是否正确,失去焦点后,添加千位分隔符格式化数字。同时小数位未满时末尾补0。HTML代码...
- 如何在pbootCMS前台调用自定义表单?pbootCMS自定义调用代码示例
-
要在pbootCMS前台调用自定义表单,您需要在后台创建表单并为其添加字段,然后在前台模板文件中添加相关代码,如提交按钮和表单验证代码。您还可以自定义表单数据的存储位置、添加文件上传字段、日期选择器、...
- 编程技巧:Jquery实时验证,指定长度的「负小数」
-
为了保障【负小数】的正确性,做成了通过Jquery,在用户端,实时验证指定长度的【负小数】的方法。HTML代码<inputtype="text"class="forc...
- 一篇文章带你用jquery mobile设计颜色拾取器
-
【一、项目背景】现实生活中,我们经常会遇到配色的问题,这个时候去百度一下RGB表。而RGB表只提供相对于的颜色的RGB值而没有可以验证的模块。我们可以通过jquerymobile去设计颜色的拾取器...
- 编程技巧:Jquery实时验证,指定长度的「正小数」
-
为了保障【正小数】的正确性,做成了通过Jquery,在用户端,实时验证指定长度的【正小数】的方法。HTML做成方法<inputtype="text"class="fo...
- jquery.validate检查数组全部验证
-
问题:html中有多个name[],每个参数都要进行验证是否为空,这个时候直接用required:true话,不能全部验证,只要这个数组中有一个有值就可以通过的。解决方法使用addmethod...
- Vue进阶(幺叁肆):npm查看包版本信息
-
第一种方式npmviewjqueryversions这种方式可以查看npm服务器上所有的...
- layui中使用lay-verify进行条件校验
-
一、layui的校验很简单,主要有以下步骤:1.在form表单内加上class="layui-form"2.在提交按钮上加上lay-submit3.在想要校验的标签,加上lay-...
- jQuery是什么?如何使用? jquery是什么功能组件
-
jQuery于2006年1月由JohnResig在BarCampNYC首次发布。它目前由TimmyWilson领导,并由一组开发人员维护。jQuery是一个JavaScript库,它简化了客户...
- django框架的表单form的理解和用法-9
-
表单呈现...
- jquery对上传文件的检测判断 jquery实现文件上传
-
总体思路:在前端使用jquery对上传文件做部分初步的判断,验证通过的文件利用ajaxFileUpload上传到服务器端,并将文件的存储路径保存到数据库。<asp:FileUploadI...
- Nodejs之MEAN栈开发(四)-- form验证及图片上传
-
这一节增加推荐图书的提交和删除功能,来学习node的form提交以及node的图片上传功能。开始之前需要源码同学可以先在git上fork:https://github.com/stoneniqiu/R...
- 大数据开发基础之JAVA jquery 大数据java实战
-
上一篇我们讲解了JAVAscript的基础知识、特点及基本语法以及组成及基本用途,本期就给大家带来了JAVAweb的第二个知识点jquery,大数据开发基础之JAVAjquery,这是本篇文章的主要...
- 推荐四个开源的jQuery可视化表单设计器
-
jquery开源在线表单拖拉设计器formBuilder(推荐)jQueryformBuilder是一个开源的WEB在线html表单设计器,开发人员可以通过拖拉实现一个可视化的表单。支持表单常用控件...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- mybatis plus (70)
- scheduledtask (71)
- css滚动条 (60)
- java学生成绩管理系统 (59)
- 结构体数组 (69)
- databasemetadata (64)
- javastatic (68)
- jsp实用教程 (53)
- fontawesome (57)
- widget开发 (57)
- vb net教程 (62)
- hibernate 教程 (63)
- case语句 (57)
- svn连接 (74)
- directoryindex (69)
- session timeout (58)
- textbox换行 (67)
- extension_dir (64)
- linearlayout (58)
- vba高级教程 (75)
- iframe用法 (58)
- sqlparameter (59)
- trim函数 (59)
- flex布局 (63)
- contextloaderlistener (56)