经过HTTP服务器的分发后 , 单个服务器的负载相对低了一些 , 但总量依然可能很大 , 如果后台商品已经被秒杀完毕 , 那么直接给后来的请求返回秒杀失败即可 , 不必再进一步发送事务了 , 示例代码可以如下所示:
package seckill;import org.apache.http.HttpRequest;/** * 预处理阶段 , 把不必要的请求直接驳回 , 必要的请求添加到队列中进入下一阶段. */public class PreProcessor { // 商品是否还有剩余 private static boolean reminds = true; private static void forbidden() { // Do something. } public static boolean checkReminds() { if (reminds) { // 远程检测是否还有剩余 , 该RPC接口应由数据库服务器提供 , 不必完全严格检查. if (!RPC.checkReminds()) { reminds = false; } } return reminds; } /** * 每一个HTTP请求都要经过该预处理. */ public static void preProcess(HttpRequest request) { if (checkReminds()) { // 一个并发的队列 RequestQueue.queue.add(request); } else { // 如果已经没有商品了 , 则直接驳回请求即可. forbidden(); } }}并发队列的选择Java的并发包提供了三个常用的并发队列实现 , 分别是:ConcurrentLinkedQueue、LinkedBlockingQueue和ArrayBlockingQueue 。
- ArrayBlockingQueue是初始容量固定的阻塞队列 , 我们可以用来作为数据库模块成功竞拍的队列 , 比如有10个商品 , 那么我们就设定一个10大小的数组队列 。
- ConcurrentLinkedQueue使用的是CAS原语无锁队列实现 , 是一个异步队列 , 入队的速度很快 , 出队进行了加锁 , 性能稍慢 。
- LinkedBlockingQueue也是阻塞的队列 , 入队和出队都用了加锁 , 当队空的时候线程会暂时阻塞 。
package seckill;import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.ConcurrentLinkedQueue;import org.apache.http.HttpRequest;public class RequestQueue { public static ConcurrentLinkedQueue<HttpRequest> queue = new ConcurrentLinkedQueue<HttpRequest>();}用户请求模块package seckill;import org.apache.http.HttpRequest;public class Processor { /** * 发送秒杀事务到数据库队列. */ public static void kill(BidInfo info) { DB.bids.add(info); } public static void process() { BidInfo info = new BidInfo(RequestQueue.queue.poll()); if (info != null) { kill(info); } }}class BidInfo { BidInfo(HttpRequest request) { // Do something. }}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 熬夜太伤身,“夜猫子”一族遇到4种水果别吝啬,清热润肺又养心
- 安徽太平猴魁介绍
- 太阳能里面的水可以饮用吗 太阳能的水能喝吗
- 太平猴魁的特点是什么
- 玻璃杯冲泡太平猴魁方法
- 玻璃杯冲泡太平猴魁介绍
- 为什么太平猴魁茶条很长却仍旧鲜嫩
- 开淘宝店运费太高怎么办 淘宝运费自己出吗
- 电视机选购,认准这几个参数就够了,其它方面不用考虑太多
- 安徽绿茶太平猴魁名茶介绍
