当前位置: 首页 > 后端技术 > Java

数据批处理速度慢?不妨试试这个

时间:2023-04-01 21:36:16 Java

业务系统。业务系统产生的明细数据,通常需要按照一定的逻辑进行处理、计算,成为需要的结果,以支持企业的业务活动。这样的数据处理任务通常很多,需要分批完成。在银行保险行业,常被称为跑批。其他行业如石油、电力等也经常有运行批次的需求。大部分业务统计都需要以某一天为分界点,为了不影响生产系统的运行,批量运行任务一般都在晚上进行。只有这时才能将生产系统当天产生的新的明细数据导出并发送到专门的数据库或数据仓库,完成运行批计算。次日上午,即可将批处理结果提供给业务人员。与在线查询不同,运行批计算是一个定时自动执行的离线任务,不会出现多人同时访问一个任务的情况,所以不存在并发问题,也不需要实时返回结果。但是,运行的批处理必须在指定的窗口时间内完成。比如某银行的批量运行窗口是晚上8:00到次日早上7:00。如果早上7:00之前没有完成批量运行任务,将导致业务人员无法正常工作,造成严重后果。跑一个批任务涉及的数据量非常大,很可能会用到所有的历史数据,而且计算逻辑复杂,步骤多,所以跑一个批的时间往往以小时来衡量。一项任务运行两到三个小时是很常见的。小时并不奇怪。随着业务的发展,数据量还在不断增加。运行一批数据库的负担快速增加,还会出现通宵运行无法完成的情况,严重影响用户业务,这是不能接受的。问题分析要解决批处理运行时间过长的问题,必须仔细分析现有系统架构中存在的问题。跑批系统的典型架构大致如下:从图中可以看出,数据必须从生产数据库中取出,存储到跑批数据库中。批量运行的数据库通常是关系型的,编写存储过程代码来完成运行批量计算。批量运行的结果一般不直接使用,而是从批量运行的数据库中导出,以接口文件的形式提供给其他系统,或者导入到其他系统的数据库中。这是一个典型的架构,图中的生产数据库也可能是中央数据仓库或Hadoop。一般来说,生产数据库和运行批处理的数据库不会是同一个数据库,数据往往以文件的形式在它们之间传递,也更有利于降低耦合度。批量计算完成后,结果需要被多个应用系统使用,一般以文件的形式传输。批量运行很慢的第一个原因是用于完成批量运行任务的关系数据库进出数据库太慢。由于关系数据库封闭的存储和计算能力,数据的进出需要过多的约束检查和安全处理。当数据量很大时,写入和读取的效率很低,而且耗时很长。因此,运行批数据库导入文件数据的过程,运行批计算结果再导出文件的过程会很慢。运行批处理很慢的第二个原因是存储过程的性能很差。由于SQL的语法体系过于陈旧,局限性很多,很多高效的算法无法实现,所以存储过程中SQL语句的计算性能很不理想。而且,当业务逻辑比较复杂时,很难用单一的SQL来实现。往往需要分成多个步骤,用十几条甚至几十条SQL语句就可以完成。每条SQL的中间结果都必须存放在临时表中,以供后续SQL使用。当临时表数据量大时,必须落地,会造成大量数据写入。数据库的写出性能远比读入性能差,会严重拖慢整个存储过程。对于更复杂的计算,直接用SQL语句实现就更困难了,需要使用数据库游标来检索数据和循环计算。但是数据库游标遍历的计算性能比SQL语句差很多。一般不直接支持多线程并行计算。难以利用多个CPU核心的计算能力,会使计算性能更差。那么,是否可以考虑使用分布式数据库代替传统的关系型数据库,通过增加节点数来提高运行批处理任务的速度呢?答案仍然是否定的。主要是跑批量计算的逻辑比较复杂。即使是传统数据库的存储过程,也往往需要编写几千甚至几万行代码。但是分布式数据库的存储过程在计算能力上还是比较弱的,很难实现如此复杂的运行批计算。而且,当复杂的计算任务要分成多个步骤时,分布式数据库也面临着中间结果落地的问题。由于数据可能在不同的节点上,中间结果在前面的步骤落地,后面的步骤读取时,会造成大量的跨网络读写操作,性能非常不可控。这时,在分布式数据库中依靠数据冗余来提高查询速度的方法就不能采用了。这是因为在查询之前可以提前准备多份冗余数据。但是,运行批处理的中间结果是临时生成的。如果冗余,就必须临时生成多个副本,整体性能只会变慢。因此,实际的批量运行业务通常是使用一个大的单体数据库来进行的。当计算强度过大时,会使用像ExaData这样的一体机(ExaData是多库的,但是经过了Oracle的专门优化,可以看成是一个超大的单体数据库。bodydatabase).虽然很慢,但暂时也没有更好的选择。只有这种大型数据库才有足够的计算能力,所以只能用来完成批量运行的任务。SPL专业批量运行计算引擎,开源SPL提供不依赖于数据库的计算能力,直接使用文件系统进行计算,可以解决关系型数据库加载卸载速度过慢的问题。而且SPL实现了更好的算法,其性能远超存储过程,可以显着提高单台计算机的计算效率,非常适合运行批处理计算。使用SPL实现的批处理系统的新架构如下:在新的架构中,SPL解决了造成批处理慢的两大瓶颈。首先,让我们看一下数据存储和存储问题。无需将数据导入关系数据库,直接根据生产数据库导出的文件计算SPL。在完成跑批计算后,SPL还可以直接将最终结果以文本文件等通用格式存储,传递给其他应用系统,避免了对原有跑批数据库的出站操作。这样,SPL省去了进入和退出关系数据库的缓慢过程。我们再来看一下计算过程。SPL提供了更好的算法(其中很多是业界首创),计算性能远超存储过程和SQL语句。这些高性能算法包括:这些高性能算法可以应用于运行批处理任务中常见的JOIN计算、遍历、分组汇总等,可以有效提高计算速度。比如运行批处理任务,往往会遍历整个历史表。在某些情况下,需要多次遍历一张历史表来完成各种业务逻辑计算。history表的数据量一般都比较大,每次遍历都需要很多时间。这时候我们可以应用SPL的遍历复用机制,只需要遍历一次大表就可以同时完成多个计算,可以节省很多时间。SPL的多通道游标可以并行读取和计算数据。即使对于复杂的批处理运行逻辑,也可以采用多CPU核心实现多线程并行运算。但是,数据库游标很难并行化。这样,SPL的计算速度往往可以达到存储过程的数倍。SPL的延迟游标机制可以在一个游标上定义多个计算步骤,然后让数据流完成这些步骤,从而实现链式计算,可以有效减少中间结果的落地次数。当数据必须落地时,SPL还可以将中间结果存储在内置的高性能数据格式中,以供下一步使用。SPL高性能存储以文件为基础,采用有序压缩存储、自由列存储、多重分段、自身压缩编码等技术减少硬盘占用,读写速度远超数据库.应用效果SPL在技术架构上打破了关系型运行批处理数据库的两大瓶颈,在实际应用中取得了很好的效果。LBank批量运行任务采用传统架构,使用关系型数据库作为批量运行数据库,使用存储过程编程实现批量运行逻辑。其中贷款协议存储过程需要执行2个小时,是其他很多批量运行任务的前置任务。耗时这么长,对整个批量运行任务影响严重。采用SPL后,采用高性能列存储、文件游标、多线程并行、小结果内存分组、游标复用等高性能算法和存储机制,将原来2小时的计算时间缩短为10分钟,性能提升12倍。.此外,SPL代码更简洁。原来的存储过程3300多行,改成SPL后只有500条语句,代码量减少6倍多,大大提高了开发效率。P保险公司的车险业务中,需要将新保单与往年历史保单进行关联,在跑批中称为历史保单关联任务。本来也是用关系型数据库来完成跑批的。存储过程计算出与历史保单关联的10天新保单,运行时间为47分钟;30天需要112分钟,将近2小时;如果日期跨度越大,运行时间就会越长,难以忍受,基本上成为不可能完成的任务。采用SPL后,应用高性能文件存储、文件游标、有序合并分段抽取、内存关联、遍历复用等技术,计算10天新策略仅需13分钟;而计算一个30天的新保单只需17分钟,快了近7倍。而且新算法的执行时间随着策略天数的增加也不是很大,不像存储过程那样按比例增加。从总代码来看,原来的存储过程有2000行代码,去掉注释后有1800多行,而SPL总代码不到500格,不到原来的1/3.对于T银行通过互联网渠道发放的贷款明细数据,需要每天执行批量运行任务,收集指定日期之前的所有历史数据。批量运行任务是使用关系数据库的SQL语句实现的,总运行时间为7.8小时,运行该批次占用的时间太多,甚至会影响到其他正在运行的批次任务,因此必须对其进行优化。使用SPL后,应用了高性能文件、文件游标、有序分组、有序关联、延迟游标、二分法等技术。本来跑一个批任务需要7.8小时,但是单线程只需要180秒,双线程137秒。秒,速度提升了204倍。SPL资料SPL下载SPL源码欢迎关注我的公告号:字母哥杂谈,回复003赠作者专栏《docker修炼之道》30余篇优质docker文章PDF版。Antetokounmpo博客:zimug.com