首页 > 代码库 > 多线程读取数据库导致连接失败解决方案
多线程读取数据库导致连接失败解决方案
问题背景:
某需求需要处理千万级别的数据,按一定规则导出,生成txt或xml文件,单线程处理太慢,写了一个跑了看差不多要处理6~10个小时。想了想还是就用多线程来从数据库中limit不同的数据来进行处理,耗时控制在5分钟以内.相关逻辑为:
1 //……其他代码 2 int count = 10000000;//假设共1千万条数据需要读取 3 int per = 50000;//每次处理5万条 4 for (int i = 0 ; i < count/per ; i ++){ //创建1000/5=200个线程来处理数据 5 //使用线程池来处理多线程 6 ThreadPool.execute(new ProcessTask(i*per,per)); 7 }
8 //……其他代码 9 class ProcessTask implements Runnable{10 int beigin,num;11 public ProcessTask(int begin,int num){12 this.begin = begin;13 this.num = num;14 }15 @Overview16 public void run (){17 //线程内容,读取数据18 List<Data> userlist = XXXService.getDataByLimit(begin,num);19 //……对读出来的数据进行处理20 //……其他代码21 }22 }
可见,此处通过循环同时创建了200个线程,而这200个线程都需要读取数据库,测试环境下最大连接数设置的是20,此时数据库就容易报错,无法连接。
除了无法连接数据库以外,还可能会导致以下问题:
- 短时间内大量占用服务器内存,导致卡顿,甚至OOM
- 在线上环境此处大量占用必定引起其他项目的性能
- 此接口恶意盗刷可能导致服务器直接宕机
解决方案:
对读取数据库操作进行sleep
1 //……其他代码 2 int count = 10000000;//假设共1千万条数据需要读取 3 int per = 50000;//每次处理5万条 4 for (int i = 0 ; i < count/per ; i ++){ //创建1000/5=200个线程来处理数据 5 //使用线程池来处理多线程 6 ThreadPool.execute(new ProcessTask(i*per,per,i)); 7 } 8 //……其他代码 9 class ProcessTask implements Runnable{10 int beigin,num;11 int i ;12 public ProcessTask(int begin,int num,int i ){13 this.begin = begin;14 this.num = num;15 this.i = i ;16 }17 @Overview18 public void run (){19 //线程内容,读取数据20 Thread.sleep(i*500);//可以改成更大的值21 List<Data> userlist = XXXService.getDataByLimit(begin,num);22 //……对读出来的数据进行处理23 //……其他代码24 }25 }
这样处理后就可以分时的读取数据库,减少服务器的负担,但是时间会变长(sleep操作),200*0.5=100s,不过也是在可以接受的范围内。
感觉好像也没多少技术含量……或者说把getDataByLimit方法设置成synchronizd就行了吧,如果是单独使用的情况下……
<--EOF-->
多线程读取数据库导致连接失败解决方案
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。