使用 JAVA 队列把高并发转为批量串行降低后端并发压力

整体思路:

1.多用户并发请求后端接口;

2.后端会启动多个线程处理前端的请求,如果并发很大就会对后端数据库造成很大的并发压力;

3.通过 JAVA 队列把用户的并发请求转换为串行批量操作数据库;

4.在 JAVA 应用中设置一个存储所有请求数据的 JAVA 队列(每一个 JAVA 应用进程会有一个这样的队列),进行数据批量入库的线程会从该队列批量获取数据进行入库;

5.在 JAVA 应用中设置一个队列数组,进行数据批量入库的线程会在完成一批入库后,把各针对各请求处理线程的响应数据写入各请求处理线程对应的队列,每个处理请求的线程会使用其中的一个队列获取数据库入库完成后的响应消息;

6.请求处理线程获得数据库入库完成的响应消息后返回响应给前端;

package com.sande.user.thread;


import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class SyncMap {

	
	private static  ConcurrentHashMap<String,BlockingQueue> queueMap = new ConcurrentHashMap<>();
	public  static  BlockingQueue<String> queue = new ArrayBlockingQueue<String>(100);
	
	
	
	public static  void  setQueueMap(String uuid,BlockingQueue queue) {
		queueMap.put(uuid, queue);
	}
	
	public static  BlockingQueue  getQueueMap(String uuid) {
		return queueMap.get(uuid);
	}
	

}

package com.sande.user.trade.serviceImpl;


import javax.annotation.Resource;
import com.sande.user.thread.SyncMap;


@Service(value = "tradeServiceQueueImpl")
public class TradeServiceQueueImpl  {
	

	

	
	public void addQueue() throws InterruptedException {
		BlockingQueue<String> queue2 = new ArrayBlockingQueue<String>(3);
		SyncMap.setQueueMap("queue2", queue2);
		SyncMap.queue.offer("test addQueue");
		System.out.println(queue2.take());
	}
	

	
}
package com.sande.user.trade.controller;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import com.sande.user.trade.dao.TradeMessage;
import com.sande.user.trade.service.TradeService;
import com.sande.user.trade.serviceImpl.TradeServiceQueueImpl;

@RestController
@RequestMapping(value="/trade")
public class TradeController {
	
	
	

	@Autowired
	@Qualifier(value="tradeServiceQueueImpl")
	private TradeServiceQueueImpl tradeServiceQueue;
	

	
	@RequestMapping(value="/order3",method= {RequestMethod.GET , RequestMethod.POST})
	public TradeMessage  order3() {
		String message="test";
		TradeMessage tradeMessage=null;
		//tradeMessage = tradeServiceQueue.trade(message);
		try {
			tradeServiceQueue.addQueue();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		/* System.out.println("controller uuid:"+ tradeMessage.getUuid());
		 System.out.println("controller message:"+ tradeMessage.getMessage());*/
		return tradeMessage;
		//return "完成";
	}

}

应用启动时,自动执行的从队列批量消费消息的后台任务。

逻辑:循环从队列获取数据,假设每100条数据为一个批次,当提取完100条数据后进行批量入库。或者队列中数据不足100条,从队列获取数据返回空时进行批量入库。如果一个批次在队列中一条数据也没获取到就调用队列的 task 方法阻塞线程,等有消息时再唤醒线程。

package com.sande.user.trade.serviceImpl;

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Service;

import com.sande.user.thread.SyncMap;

@Service
public class QueueServiceImpl implements ApplicationRunner {

	//public void consumeQueue() {
		
	//}

	@Override
	public void run(ApplicationArguments args) throws Exception {
		// TODO Auto-generated method stub
		String string = new String();
		try {
			string =SyncMap.queue.take();
			SyncMap.getQueueMap("queue2").offer(string);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值