感谢当当,在跑写这个程序的时候,当当让我了解了很多新的知识
这是两个比较经典的提问:
http://topic.csdn.net/u/20071119/23/8af044b3-8c28-4db0-8303-4a8679f2356d.html
http://topic.csdn.net/u/20071209/10/c01ad9da-08cb-452c-9230-dff429619361.html
本程序要做的事情是:从cache服务器中读取店铺访问量数据,然后入库。
问题的难点 :
1 :全国所有店铺的key(city_storeId)有750万,数据量很大,导致跑的时候经常内存溢出
2 :解决了读数据的问题,但是跑这么多数据速度很慢,需要6个多小时,则思考了很多方法
问题一解决方式:
之前我是用buffedreaded类的readline方法一行一行的读取,然后放在list里面,在通过遍历list去做更新操作。这明显是不行的,把所有数据放在list导致内存溢出,放不了那么多数据。
之后放弃这个方式,在buffedreaded类的readline方法读取时就进行数据库的入库操作,因为readline方法每次读取一定量的数据到内存,假设100条key,然后放到队列里,接着就一条一条的更新,所以不会导致内存溢出,但是出现一个问题,就是跑的时间太慢
问题二解决方式:
想了很多方式:有想到用NIO来提高IO读取的效率,也有想到用多线程,分割文件来跑,最后还是用到了多线程,这个要感谢当当,有个例子给我,也让我第一次接触了多线程的current包(想当初就是没有回答上这个包,才被淘宝拒绝的)。刚开始进入了一个误区,还以为是读取文件慢了,结果是因为操作数据库太慢了。mysql数据库每秒可以接受500-1000的并发量,那么750万数据,怎么算都至少跑2个小时(7500000/1000/3600)。所以只能通过加mysql数据库集群才能使速度加快。
找个时间好好学习下current包
ExecutorService fixedPool =Executors.newFixedThreadPool(poolSize);
还有用多线程跑的时候还出现了内存溢出的问题,问了当当之后,通过调整了eclipse的jvm虚拟机的内存(从原来的252M调整到1G),还有就是把线程引用对象读到队列里的时候,每50万条,sleep(5000),不要一下子加载。
下面是代码:
线程类代码
//判断静态类是否有重复创建,可以用此来判断
private static int count = 0;
private static Score dianHitsScore;
private static IStoreExtService storeExtService;
public ThreadForVisit(String data) {
this.data = data;
}
static {
ApplicationContext context = new ClassPathXmlApplicationContext(
"CateVisitTimer.application.xml");
dianHitsScore = (Score) context.getBean("dianHitsScore");
storeExtService = (IStoreExtService) context.getBean("storeExtService");
}
public void run() {
Integer score = null;
// int entity_total = 0; // entity为null数据条数的总数
// int cache_total = 0; // cache中无数据的条数的总数
// int update_total = 0; // 访问量更新的数据条数的总数
try {
String storeId = getCityAndStoreId(data);
score = dianHitsScore.get(data);
if (score != null && score.intValue() > 0) {
StatisticEntity entity = storeExtService.getStatisticById(storeId);
if (entity != null) {
entity.setTotal(score.intValue());
// 这个读取数据库的操作已经用了多线程
storeExtService.updateStatistic(entity, storeId);
//update_total++;
//logger.info(data + "=" + entity.getTotal());
//Thread.sleep(100);
} else {
//entity_total++;
//logger.info(entity + "为null!");
}
} else {
//cache_total++;
//logger.info(data + "cache 中无数据!");
}
count ++;
if(count % 10000 == 0){
System.out.println("=============="+count);
}
} catch (Exception e) {
logger.info("ThreadForVisit类的run方法中的Thread.sleep(100)出问题");
}
}
main函数跑的代码
ExecutorService fixedPool = Executors.newFixedThreadPool(poolSize);
int count = 0;
if (data != null) {
try {
//速度慢不是由于读文件上的浪费,而是对数据库操作时候的慢
BufferedReader buff = new BufferedReader(new FileReader(data));
while ((data_part = buff.readLine()) != null) {
fixedPool.execute(new ThreadForVisit(data_part));
if((++count % 500000) == 0){
System.out.println("数据达到50万");
Thread.sleep(5000);
}
}
} catch (Exception e) {
logger.info("store访问量定时程序异常");
}
}
其实里面还设计到很多调试代码的技巧:分开测每个数据库操作所需要的时间
分享到:
相关推荐
大访问量就是我们平时所说的高并发量,一台服务器很难承受突如其来的访问压力,可以采用负载均衡和冗余技术来解决这些问题
每天可以定时执行一个程序,运行方法,也就是相当于定时器一样.好处就是可以比如平常程序访问量数据量方面比较大的时候,耗时间时你可以把它定时某个访问量或数据量小的时间段运行.
输入一个网址,定时刷新访问该网页的一个小程序
网站定时访问器
写这个小程序的初衷,是因为一个我的WAP前端哥们的公司(只做PHP的公司)有一个业务逻辑需要不停的访问一个PHP方法,来实现他们业 务逻辑所以写了一个,只要输入“空秒数和URL”地址... 启动 定时访问URL.exe 文件开始
具体操作的博客对应地址: http://blog.csdn.net/csethcrm/article/details/17917721
疫情期间用户访问量翻倍增长,但小程序电商仍面临3大挑战.pdf疫情期间用户访问量翻倍增长,但小程序电商仍面临3大挑战.pdf疫情期间用户访问量翻倍增长,但小程序电商仍面临3大挑战.pdf疫情期间用户访问量翻倍增长,但小...
js实现统计访问量js实现统计访问量js实现统计访问量js实现统计访问量
python定时访问网址
怎么进行访问量统计,此资源中的代码也许可以帮助你解决这理问题。访客系统信息如IP,当前在线人数统计,网站总访问量
统计网站总的访问量 屏蔽刷新来增加访问量 访问量数据存放在单独文件中
一个 定时向网络访问数据 的程序,地震速报--HttpURLConnection与 Service 侦测服务, 详情请参见 http://blog.csdn.net/aduovip/article/details/17054129
每天定时抓取CSDN博客访问数量,并保存在数据库,通过echarts展示出最近8天的访问趋势。包框了echarts技术和mybatis技术 springboot框架
Springboot网站用户的访问量统计,代码加入了线程,根据自己的需求下载,不需要线程的留下邮箱
自己写的一个小记数器,用ACCESS存储,样式:今日访问量: 昨日访问量: 本月访问量: 上月访问量: 站总访问量: 开通总天数:
jsp基本实现高访问量的程序源代码 不错的呵呵
框架采用spring,导入eclipse即可,数据库用的sqlserver,mysql也可以,需要改动下驱动包。那个sql建表用的。
控制台应用程序定时执行命令访问网页
asp.net 统计访问量asp.net 统计访问量asp.net 统计访问量asp.net 统计访问量