java大并发数据保存方案
做了几年.net,如今终于要做java了。
- 需求:
线下终端会定时上传gps位置到服务端,服务端收到数据保存到mysql数据库,当线下终端过多时,问题出现了,首当其冲的是数据库连接池经常会崩溃,单个tomcat到100并发就会抛出异常。
- 解决思路:
原来是收到一条数据就保存一条数据,现在改为将收到的数据暂存到一个数据池,当满100条数据时再用saveBatch一次性保存,这样终端上传100次其实只建立了一次数据库连接,减轻数据库压力。如果只是这样还有一个不足,就是当数据池的数据一直都不满100条时,永远都不会保存到数据库,所以再加一个守护线程,每2分钟检查一次,如果数据池有数据,就全部保存到数据库。
- 该方案执行效率,如下图,共1000次请求,100次并发的情况
- 具体实现:
1、数据池代码
public class GpsPool {
private static final Logger log = Logger.getLogger(GpsPool.class.getName());
public static Queue<ClientGPS> queGps=new LinkedList<ClientGPS>();//暂存数据,等数据超过100条或者超过时间后自动保存
private static Object lock=new Object();
//private ExecutorService s=Executors.newSingleThreadExecutor();
private ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1, 1, 10, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<Runnable>(1),new ThreadPoolExecutor.DiscardPolicy());
/**
* 一次性最多取出100个数据
* @return
*/
public static List<ClientGPS> poll100(){
List<ClientGPS> gpss=new ArrayList<ClientGPS>();
synchronized (lock) {
int length=100;
if(queGps.size()<100)
length=queGps.size();
for (int i = 0; i < length; i++) { gpss.add(queGps.poll());
}
}
return gpss;
}
public void saveGps(ClientGPS gps){
if (null==gps||queGps.size()>2000) {//大于2000暂不处理
return;
}
if (queGps.size()>100) {
queGps.offer(gps);
threadPool.execute(new GpsSaveThread());
System.out.println("add2pool");
}else{
queGps.offer(gps);
} }
}
2、数据保存线程
class GpsSaveThread implements Runnable{
private static final Logger log = Logger.getLogger(GpsTask.class.getName());
ClientGPSService gpsService;
@Override
public void run() {
gpsService=ServiceLocator.getBean(ClientGPSService.class);
try {
List<ClientGPS> gpss;
while (GpsPool.queGps.size() > 100) {
gpss = GpsPool.poll100();
if (gpss.size() > 0) {
try {
gpsService.saveBatch(gpss.toArray(), gpss.size());
} catch (Exception e) {
saveError(e);
try {//失败后再试一次
gpsService.saveBatch(gpss.toArray(), gpss.size());
} catch (Exception ex) {
}
}
} }
} catch (Exception e) {
saveError(e);
} } }
3、守护线程代码
public class GpsTask implements Runnable{ private static final Logger log = Logger.getLogger(GpsTask.class.getName());
ClientGPSService gpsService;
@Override
public void run() {
gpsService=ServiceLocator.getBean(ClientGPSService.class);
while (true) {
try {
Thread.sleep(1000*60*2);//2分钟检查一次
List<ClientGPS> gpss= GpsPool.poll100();
GpsPool.queGps.clear();
if(gpss.size()>0){
try {
gpsService.saveBatch(gpss.toArray(),gpss.size());
} catch (Exception e) {
saveError(e);
}
}
} catch (InterruptedException e) {
saveError(e);
}catch(Exception e){
saveError(e);
}
} }
}
守护线程代码
- 抛砖引玉
目前这个方案有点问题,就是并发过千时,cpu会达到100%,期待有更好的方案。
java大并发数据保存方案的更多相关文章
- JAVA大集合数据分批次进行切割处理
今天遇到一个大集合里面的数据删除问题, 因为是一个大集合,如果同时传递到数据库,那么就会造成数据库压力 所以分批次的进行批量操作 其实 也可以采用多线程来处理或者多批次加多线程来处理都是可以的 下面的 ...
- Java+MySql图片数据保存与读取的具体实例
1.创建表: drop table if exists photo;CREATE TABLE photo ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY ...
- Java读取excel数据保存入库
Java开发读取excel表格数据入库保存: List<Map<String, Object>> list = null; String filePath = filePath ...
- Java+MySql图片数据保存
之前一直没有做过涉及到图片存储的应用,最近要做的东东涉及到了这个点,就做了一个小的例子算是对图片存储的初试吧! 1.创建表: drop table if exists photo; CREATE TA ...
- java ->大的数据运算(BigInteger)
大数据运算 BigInteger java中long型为最大整数类型,对于超过long型的数据如何去表示呢.在Java的世界中,超过long型的整数已经不能被称为整数了,它们被封装成BigIntege ...
- Linux Bash 脚本:自己定义延迟代码块(裸数据保存方案)
结合 alias 和 read 使用方法.能够保存一些将要延迟执行的脚本,或者裸数据(字符串不被扩展)到一个变量中.以备后用. $ alias BEGIN='read -d "" ...
- Sqlserver 高并发和大数据存储方案
Sqlserver 高并发和大数据存储方案 随着用户的日益递增,日活和峰值的暴涨,数据库处理性能面临着巨大的挑战.下面分享下对实际10万+峰值的平台的数据库优化方案.与大家一起讨论,互相学习提高! ...
- Java大数据人才应用领域广,就业薪酬高
互联网创造了大数据应用的规模化环境,大数据应用成功的案例大都是在互联网上发生的, 互联网业务提供了数据,互联网企业开发了处理软件,互联网企业的创新带来了大数据应用 的活跃,没有互联网便没有今天的大数据 ...
- Java高并发的常见应对方案
Java高并发的常见应对方案 一.关于并发我们说的高并发是什么? 在互联网时代,高并发,通常是指,在某个时间点,有很多个访问同时到来. 高并发,通常关心的系统指标与业务指标? QPS:每秒钟查询量,广 ...
随机推荐
- linux系统下使用流行的版本管理工具 Git
前几天被版本管理困扰了好久,主要是因为 没法回到之前的版本,新版本又出了问题真的很尴尬. 终于决定使用目前网上很火的版本管理工具-------Git 历史啥的就不说了,说些有用的. 我用的是oschi ...
- BPM问题
1.安装XFormDesigner后编辑界面报错 解决方法:
- [转]如何设置eclipse中js默认打开为java Editor
打开window-preference -> General-Editors-File Associator 看到右边的.js下边就是设置默认打开方式了 转自百度知道:http://zhidao ...
- SQL Server 阻止了对组件 'Ad Hoc Distributed Queries' 的 STATEMENT'OpenRowset/OpenDatasource' 的访问
delphi ado 跨数据库访问 语句如下 ' and db = '帐套1' 报错内容是:SQL Server 阻止了对组件 'Ad Hoc Distributed Queries' 的 STATE ...
- 事件DOMContentLoaded和load的区别
1.当 onload 事件触发时,页面上所有的DOM,样式表,脚本,图片,flash都已经加载完成了. 2.当 DOMContentLoaded 事件触发时,仅当DOM加载完成,不包括样式表,图片,f ...
- Non-blocking read on a subprocess.PIPE in python
import sys from subprocess import PIPE, Popen from threading import Thread try: from Queue import Qu ...
- MySQL隐式转化整理
MySQL隐式转化整理 前几天在微博上看到一篇文章:价值百万的 MySQL 的隐式类型转换感觉写的很不错,再加上自己之前也对MySQL的隐式转化这边并不是很清楚,所以就顺势整理了一下.希望对大家有所帮 ...
- JAVA中保留小数的多种方法
// 方式一:double f = 3.1516;BigDecimal b = new BigDecimal(f);double f1 = b.setScale(2, BigDecimal.ROUND ...
- Manage Metadata Service Error: There are no addresses available for this application
打开正常创建的Metadata Service后发现了如下的错误: 检查了Application Pool和Managed Metadata Web Service ,发现两者一切正常,之后查看Sh ...
- nginx_mysql_redis配置
#Nginx所用用户和组,window下不指定 #user nobody; #工作的子进程数量(通常等于CPU数量或者2倍于CPU) worker_processes 2; #错误日志存放路径 #er ...