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:每秒钟查询量,广 ...
随机推荐
- CSS优先级
一.CSS代码出现的几个位置 多重样式(Multiple Styles):如果外部样式.内部样式和内联样式同时应用于同一个元素,就是使多重样式的情况. 一般情况下,优先级如下:(外部样式)Extern ...
- 【WPF】值是枚举的RadioButton 绑定问题
源 1.RadioButton 2.IValueConverter 3.枚举 xaml实现 <RadioButton Content="单打热身" GroupName=&qu ...
- ubuntu下的apt-get内网本地源的搭建
APT本地源的搭建(可用于局域网apt-get源搭建或者本地源) 本文档介绍使用apt-mirror软件搭建apt本地源 需求:内网开发环境由于其特定原因不能上外网,所以需要本地环境下的内网源来方便开 ...
- C#执行Dos命令公用方法
private static string InvokeCmd(string cmdArgs) { string Tstr = ""; Process p = new Proces ...
- 微信开发包注意jar版本:
微信java jar的加密key的大小支持 异常java.security.InvalidKeyException:illegal Key Size的解决方案:在官方网站下载JCE无限制权限策略文件( ...
- struts-hibernate-ajax完成区县和街道级联下拉框功能(二补充使用json解析list结果集,ajax循环json层级处理)
针对<struts-hibernate-ajax完成区县和街道级联下拉框功能>进行补充,上一篇中,要在action中拼接JSON格式字符串,很容易手抖.直接用json处理一下转成json格 ...
- Celery的实践指南
http://www.cnblogs.com/ToDoToTry/p/5453149.html Celery的实践指南 Celery的实践指南 celery原理: celery实际上是实现了一个典 ...
- MVC Controller中View(model)如何在 View中的index页面获得?
http://bbs.csdn.net/topics/390723984?page=1 在页面顶部定义@model List<UserModel>使用@foreach(var x in M ...
- android studio关联genymotion模拟器,未显示设备
如以下截图所示,在搭建android studio+genymotion时,遇到android studio关联genymotion时,显示不出模拟器设备,请问有没有遇到此现象的朋友,分享下解决方法, ...
- Apache服务器网站访问伪静态内页出现No input file specified.的完美解决方案
原文地址:Apache服务器网站访问伪静态内页出现No input file specified.的完美解决方案 启用REWRITE的伪静态功能的时候,首页可以访问,而访问内页的时候,就提示:&quo ...