`

记一次代码优化(大数据量处理及存储)

阅读更多
记一次代码优化过程
--- 大数据量的处理及存储

1. 原始场景再现:
该模块主要是客户端负责上传一个包含手机号码的txt,其中一行一个手机号码。服务端读取并解析该文件,解析过程中需要做有效性验证。例如:号码位数,是有效数字及是否在有效号段之内。最后保存数据到DB。
该包含手机号码文件数据在20W到200W之间。

2. 问题所在
在客户端上传20W数据的时候,后台相应很慢,查看后台的CPU及内存
mpstat -P ALL 1   //查看LINUX系统内存及CPU的消耗情况
发现CPU一直处在100%状态下,而且消耗的时间很长。近十分钟也没有回复到客户端。

3. 问题详解
首先查看代码。列下原代码思路:
1) 使用apache的公用包来处理文件的上传,保存客户端文件到服务器
2) 打开读取文件IO,及写日志IO,读取文件信息,到一个LIST中。
3) 双重遍历LIST,进行查重操作。重复数据记录到日志文件中
4) 遍历LIST进行有效位数的校验。重复数据记录到日志文件中
5) 遍历LIST进行是否为有效数字验证。重复数据记录到日志文件中
6) 遍历该LIST,组装为数据库存储对象传递到DAO层,DAO层再次遍历对象容器,将插入对象添加到了批量提交的LIST中。最后将20W的数据一次性批量提交

4. 问题解决思路

第一次改动:仔细查看代码我们可以很清晰的看出,问题主要在两块:
一是数据的有效性检查,原代码采用了多次循环遍历的方式处理,很耗CPU。故首先将多次遍历的处理应该缩减为一次遍历即可,但是仔细想想其中存在一个查重的处理操作,故我们将原本用list存储的方式改为SET存储的方式,因为set不会存储重复的数据,这样可以达到查重的效果。

Key:HashSet底层使用hash数组实现的,其原理就是当保存一个对象的时候,首先调用该对象的hashCode方法,获得hash码与原数组及数组子链表中的数据进行比较,若是相同的话则不进行插入操作,再不存在的情况下,才进行存储。由于String 类型已经实现了hashCode方法,所以我们不需要实现该方法若是其他类型的对象我们则需要实现该方法。

二就是数组存储的地方了,原代码采用了几十万条数据的一次批量提交,当然很消耗资源,代码回复给客户端慢。这里我采用了ORACLE写一个存储过程,JAVA端传递一个数组给ORACLE,有存储过程来处理大数据量,这样就将服务器的压力转移到ORACLE安装的的那台服务器。
好的,第一次改动过完成。重启TOMCAT试下。结果当我们只上传20W数据的时候,发现还是很慢很慢,回头又仔细看代码,打断点。再调试的过程中,发现在我只采用一个遍历循环的时候,CPU就一直处理100%,原来在处理这20W数据的时候,CPU就一直处理很高的状态了,那该怎么办呢?这个时候就是第二次改动了
------------------------------------这里是华丽的分割线-------------------------------------
第二次改动:
个人经验,一般处理这种大数据量有两种方法,其实这两次方法的本质是一样的,就是为了降低CPU。
第一种是在我们在遍历循环的时候,在循环遍历到一定数量的时候,进行Thread.sleep(5)操作,带该线程睡眠片刻

For (int I =0 ;I < list.size();i++)
{
	//…业务处理
	If (3000 == i)
{
		Thread.sleep(5)
	}
}

强制CPU暂时不处理该线程。

第二种方法就是采用流控的方式,流控的原理就是我们有一个初始量,循环过程中我们累加这个量,当达到一定量的时候,该线程进行wait()操作,同时我们启动一个定时器,定时间周期对该变量进行清零操作,并唤醒该线程。其中可能会出现两种情况,一是我们定时器的清零操作还没到,累积量就已经到了,那么该线程就会处在等待状态,等待清零时间到,唤醒线程。二是累积量还没到,清零时间就到了,对线程进行清零,那么这个时候线程会一直处在一个运行状态,如果这个时候CPU使用率很高的话,就达不到我们需要的效果,所以该方式的控制就需要实际调整定时器的扫描周期、记累积量的值设定。实际过程中需要调整两参数。
因为我们是将流控写成了一个工具类,所以不好贴出来,具体也就是上面所所得思路。
比较两种方法我们明显可以看出,采用流控的方式更佳,因为它是不阻塞线程,wait的方式。第一次则是sleep,阻塞线程。
好,第二次改动已经完成了,我们就开工试试了。当你怀着美好的愿望时,老天总是不能让你如意。结果很失望,还是慢的一塌糊涂,然后不断的调整参数,结果还是没降下来。这个时候我就开始反思了,难道这种方式有问题,再去打断点调试的过程发现,采用了流控后,在处理数据的时候是CPU确实是降下来了,但是还是存在一个问题,再没处理完一条记录后,都会有一个日志的记录,这个时候用的是bufferRead,结果我们在最后的close()IO的时候,一次行将内存缓存中的数据库刷到文件,导致CPU及内存的过高。知道原因后我开始了第三次的改动。
-------------------------------------分割线又出现了--------------------------------------
第三次改动:
这个时候,我采用了流控相同的思路,就是在处理完一定数据量的数据后,我们进行一次flush操作,将内存中数据刷到文件中,免得一次性刷,同时因为我们一般是整数的W级数据,所以定义一个常量为3000(全局多个地方需要刷数据,好改动),作为flush标示。因为采用3000的话,最后一次我们刷的只有1000的数据量,同时关闭IO需要开销,所以能够在一定程度上降低CPU,同时发现在第一次flush的时候CPU会较高,越后CPU会越低,不知道什么原因。
If (…)
{
		if (3000 == i)
{
		read.flush()l
}
}

OK ,又可以开工进行测试了,我是费了九牛二虎之力开动了TOMCAT(机子太差),哈哈,终于成功了。CPU从原来的100%降到了10%左右,很有成就感,嘿嘿。这样就将给测试区测试了。但是,但是,测试告诉我一个很不幸的消息,CPU还是很高,这个是为什么呢?
仔细看看了,原来TMD应用的服务器跟DB在一台服务器上,气死老夫了。采用一次性传递数据的片刻,ORACLE会使CPU会飙到100%,而且处理这么多数据的时候也会持续5s左右的时间一直处在该位。这个时候咋办呢?这个就需要第四次改动了。
-----------------------------我是分割线,大家好!北边的朋友在哪里?--------------------------
第四次改动:
这个时候,首先改动的是存储过程,采用了动态变量绑定,同时调整commit;的次数,在1000,3000,5000,10000条记录的时候提交数据,结果调试后,没什么改观,没则,只好换个思路。
启用存储过程,在java端想办法,最简单的方法还是启用原来的批量提交方式,修改为一定数量数据后提交,因为这个提交,并在提交后sleep,方式CPU一直处在这个状态。
伪代码就是
If ()
{
	If (3000 == i)
{
		//提交数据到DB
	//清零标示,清空临时list
	Thread.sleep();
}
}

就这么简单。提交调试后,发现java端不会消耗很高的CPU,在第一次提交批量数据时会到30%左右,第二三次会降到15%左右,同时ORACLE消耗的CPU在第一次会100%,但是持续时间很短,就1s的时间,在达到这样的效果后,领导说可以了。总算结束了这段优化过程。
简单的说,我这种方式不过是用时间换CPU的性能,只使用与对于时间要求不是很高,更要求CPU的性能的场景。








分享到:
评论
5 楼 zhangdp_neu 2010-02-15  
"该模块主要是客户端负责上传一个包含手机号码的txt"

很感兴趣你的优化,txt格式是什么样的?
4 楼 zhouky4665 2010-02-15  
直接用sqlload直接导入数据库,然后写个存储过程处理业务逻辑,比如去重、有效性检查。
这样非常快,200w数据最多2分钟搞定
3 楼 mikeandmore 2010-02-14  
inter12 写道
抛出异常的爱 写道
thread.setPriority
大过年的


设置线程的优先级,好像从来没起作用过

如果是windows的话。。。。
的确很难说管用的。。-w-

所以我觉得dispatcher queue是个复杂、强大但是混乱的想法。。。-w-
2 楼 inter12 2010-02-14  
抛出异常的爱 写道
thread.setPriority
大过年的


设置线程的优先级,好像从来没起作用过
1 楼 抛出异常的爱 2010-02-14  
thread.setPriority
大过年的

相关推荐

    经验大数据量处理及存储代码优化过程.docx

    在大数据量处理和存储的场景中,代码优化是至关重要的,尤其是在处理20W到200W级别的数据时。原始场景中,客户端上传包含手机号码的文本文件,服务端负责读取、验证和存储。问题在于后台响应缓慢,CPU长时间处于100%...

    经验大数据量处理及存储代码优化过程.pdf

    在处理大数据量时,优化代码至关重要,尤其是对于涉及大量数据读取、验证和存储的任务。在这个案例中,原始场景是客户端上传一个包含手机号码的文本文件,服务端接收并进行有效性验证,然后将数据存入数据库。问题...

    经验大数据量处理及存储代码优化过程 (2).docx

    在大数据量处理和存储的场景中,代码优化是至关重要的,以确保系统性能和响应速度。以下是从给定内容中提取的关键知识点: 1. **原始场景**:客户端上传包含手机号码的文本文件,服务端读取、验证并保存到数据库。...

    经验大数据量处理及存储代码优化过程 (2).pdf

    在处理大数据量的问题时,代码优化是至关重要的。在上述案例中,原始场景涉及客户端上传包含大量手机号码的文本文件,服务端负责读取、验证和存储这些数据。当数据量达到20万至200万时,系统响应变慢,CPU持续处于...

    大数据量数据存储的优化方案(银行项目)

    因此,如何有效地优化大数据量下的数据存储及查询效率成为了银行信息技术部门面临的关键问题。 #### 二、系统优化现状分析 目前,银行信息系统优化主要集中在以下几个方面: 1. **网络带宽升级**:提高网络传输...

    .net 大数据量处理

    总之,处理.NET中的大数据量需要综合运用多种策略和技术,包括分批加载、分块读取数据库、优化查询、并行处理等,以确保系统在处理大规模数据时仍能保持高效和稳定。根据实际场景选择合适的方案,才能最大化地发挥...

    sqlite数据库 大数据量处理demo

    在这个“sqlite数据库大数据量处理demo”中,我们将深入探讨如何在SQLite数据库中有效地管理大规模数据。 SQLite支持SQL标准,包括创建表、插入数据、更新数据、删除数据以及查询数据等基本操作。对于大数据量的...

    Web大数据量页面优化实践

    在现代Web开发中,随着数据量的急剧增长,如何有效地处理和展示大数据量的页面成为了一个重要的挑战。本文将深入探讨“Web大数据量页面优化实践”,结合提供的标签“源码”和“工具”,我们将从代码优化和利用工具两...

    大量数据处理优化方案

    在大数据处理领域,优化数据处理效率是至关重要的。本文将探讨一种常见的优化方案——通过游标方式处理大量数据,以及如何通过调整参数和利用索引来提升性能。 首先,游标方式是数据库操作中常用的一种机制,它允许...

    处理大数据量excel

    在IT行业中,处理大数据量的Excel文件是一项常见的挑战,尤其对于数据分析、数据处理以及报告生成等领域。Excel虽然作为个人和小团队的数据管理工具非常实用,但当数据量达到一定规模时,其性能会显著下降。这篇博文...

    如何优化大数据量加载DataGrid

    在IT领域,尤其是在软件开发与用户界面设计中,处理大数据量的展示是一个常见的挑战。当涉及到使用DataGrid组件时,这一挑战尤为突出。DataGrid是一种广泛应用于桌面应用程序的数据展示控件,它能以表格的形式直观地...

    提高WebService性能大数据量网络传输处理

    在IT行业中,尤其是在开发涉及大数据量网络传输...这种方法不仅高效,而且免费,对于处理大规模数据的Web服务是一个实用的解决方案。同时,开发者应该根据实际应用的需求和环境,进行性能测试,选择最适合的优化策略。

    七天搞定SQL2005千万级别数据记录+数据库优化经验+代码优化+索引优化

    本文将分享一位开发者针对SqlSever2005一千万条以上记录的分页数据库优化经验,包括索引优化和代码优化,帮助读者理解如何应对大规模数据处理中的性能瓶颈。 首先,当数据量达到千万级别时,数据库的性能表现将直接...

    C# Access 大数据量 批量 效率 快速 导入

    在C#编程环境中,处理大数据量的导入任务时,效率是非常关键的一环。"C# Access 大数据量 批量 效率 快速 导入"这个主题聚焦于如何利用C#语言高效地将大量数据批量导入到Access数据库中。Access作为一个小型数据库...

    大数据量分页

    在IT行业中,大数据量分页是一项重要的...总之,通过JSP和存储过程的结合,我们可以高效地处理大数据量的分页,提供流畅的用户体验。这是一项基础但至关重要的技术,对于任何处理大量数据的Web应用来说都是必不可少的。

    java一次性查询处理几百万数据解决方法

    在Java开发中,处理大数据量是常见的需求之一,特别是当数据规模达到几百万级别时,如何高效、稳定地处理这些数据变得尤为重要。本文将详细介绍一种Java一次性查询处理几百万数据的有效方法,并通过具体代码示例进行...

    基于.net的大数据量SQLSERVER系统数据库和代码优化方案.pdf

    在讨论有关基于.net的大数据量SQL SERVER系统数据库和代码优化方案之前,我们需要理解几个关键的概念和组件。首先,.NET是一个由微软开发的软件框架,它包括一系列用于构建和运行.NET应用程序的库和工具。SQL Server...

    如何统计MySQL数据量大小

    在数据库管理中,了解MySQL数据量的大小是至关重要的,这有助于优化性能、规划存储空间以及进行容量规划。本文将详细讲解如何统计MySQL数据库的数据量大小,并涉及CONCAT函数的解读,以及对information_schema和...

    一种低代码平台大数据量业务数据高性能查询的技术设计与实现

    ### 一种低代码平台大数据量业务数据高性能查询的技术设计与实现 #### 技术领域 本发明属于低代码软件开发及SaaS云技术领域,旨在提高低代码开发平台在面对大数据量时的业务数据查询效率。 #### 技术背景 低代码...

    网页树型结构快速加载大数据量数据的实现.

    在IT领域,尤其是在Web开发中,处理大数据量的树型结构是常见的需求,尤其是在构建复杂的用户界面或数据展示时。本文将深入探讨如何在网页上高效地实现树型结构的大数据量加载,这是一个对性能有高要求的任务,涉及...

Global site tag (gtag.js) - Google Analytics