文档章节

水煮秒杀系统设计

精通吹水
 精通吹水
发布于 2017/03/27 16:15
字数 462
阅读 61
收藏 2

秒杀系统设计

大致思路如下(只考虑动态调用,其他手段不进行考虑):

  1. CACHE层防大部分流量(非实时商品数量)
  2. SEMAPHORE 层限制超量流量 (商品数量 * 2)
  3. SEMAPHORE 限制调用流量(保护DB)
  4. 根据商品ID,HASH到不同的负载服务器上

模仿代码


package org.dfw.kill;

import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

/**
 * SecKill
 */
public class Main {
    static final int THRESHOLD = 10;
    static final int BUY_SIZE = 1000 * 10 * 2;
    static AtomicInteger NUM_COUNT = new AtomicInteger(THRESHOLD);
    static volatile int CACHE_SIZE = THRESHOLD;

    static public int buy() {
        boolean ok = false;
        int id = -1;
        while (!ok) {
            int num = NUM_COUNT.get();
            if (num > 0) {
                id = num - 1;
                try {
                    // 模拟耗时操作
                    Thread.sleep(50);
                } catch (Exception e) {
                    // NONE
                }
                ok = NUM_COUNT.compareAndSet(num, id);
            } else {
                ok = true;
                id = -1;
            }
        }
        CACHE_SIZE = NUM_COUNT.get();
        return id;
    }

    static public void main(String[] args) throws Exception {
        final Semaphore semaphore = new Semaphore(THRESHOLD);
        ExecutorService executorService = Executors.newFixedThreadPool(BUY_SIZE);
        final CountDownLatch countDownLatch = new CountDownLatch(1);
        final Random random = new Random(System.currentTimeMillis());

        final AtomicLong CACHE_PASS = new AtomicLong(0);
        final AtomicLong CACHE_FAIL = new AtomicLong(0);
        final AtomicLong SEMAPHORE_PASS = new AtomicLong(0);
        final AtomicLong SEMAPHORE_FAIL = new AtomicLong(0);
        final AtomicLong BUY_PASS = new AtomicLong(0);
        final AtomicLong BUY_FAIL = new AtomicLong(0);
        final CountDownLatch finish = new CountDownLatch(BUY_SIZE);
        for (int i = 0; i < BUY_SIZE; ++i) {
            executorService.submit(new Runnable() {
                public void run() {
                    try {
                        countDownLatch.await();
                        {
                            // 模拟先后到达
                            int sleep = random.nextInt(2);
                            Thread.sleep(sleep * 1000L);
                            // 模拟缓存
                            if (CACHE_SIZE <= 0) {
                                //System.out.println("前端缓存过滤拦截");
                                CACHE_FAIL.incrementAndGet();
                            } else {
                                CACHE_PASS.incrementAndGet();
                                // 击破缓存
                                //  超过固定数量,直接返回
                                if (semaphore.getQueueLength() > THRESHOLD * 2) {
                                    SEMAPHORE_FAIL.incrementAndGet();
                                    //System.out.println("信号量拦截");
                                } else {
                                    SEMAPHORE_PASS.incrementAndGet();
                                    // 进入排队
                                    semaphore.acquire();
                                    try {
                                        int id = buy();
                                        if (id >= 0) {
                                            BUY_PASS.incrementAndGet();
                                            System.out.println("已经购买到商品,ID=" + id);
                                        } else {
                                            BUY_FAIL.incrementAndGet();
                                            System.out.println("对不起,你在DB层被终结");
                                        }
                                    } finally {
                                        semaphore.release();
                                    }
                                }
                            }
                        }
                    } catch (Throwable e) {
                        // NONE
                    } finally {
                        finish.countDown();
                    }

                }
            });
        }
        Thread.sleep(1000 * 4);
        System.out.println("开始抢购了");
        long startTime = System.currentTimeMillis();
        countDownLatch.countDown();
        finish.await();
        long endTime = System.currentTimeMillis();
        executorService.shutdown();
        System.out.println("CACHE_PASS: " + CACHE_PASS.get());
        System.out.println("CACHE_FAIL: " + CACHE_FAIL.get());
        System.out.println("SEMAPHORE_PASS: " + SEMAPHORE_PASS.get());
        System.out.println("SEMAPHORE_FAIL: " + SEMAPHORE_FAIL.get());
        System.out.println("BUY_PASS: " + BUY_PASS.get());
        System.out.println("BUY_FAIL: " + BUY_FAIL.get());
        System.out.println("COST_TIME: " + (endTime - startTime));
    }
}


运行结果

CACHE_PASS: 1398
CACHE_FAIL: 18602
SEMAPHORE_PASS: 31
SEMAPHORE_FAIL: 1367
BUY_PASS: 10
BUY_FAIL: 21
COST_TIME: 8694

© 著作权归作者所有

上一篇: Android LMK
下一篇: Java 泛型简写
精通吹水
粉丝 18
博文 56
码字总数 55035
作品 0
人事招聘
私信 提问
【读后有感】从元宵节煮汤圆看架构的识别与设计

。因此,办法会有很多种,背后所体现的理念会有不同,折射出的是不同的价值观。 「好」架构,应当是对架构使用人「简单」并且「通用性强」,可以解决「很多」人的类似问题。 「好」架构,应当...

陶邦仁
2016/02/24
43
0
说说网站限时秒杀系统的架构设计

时值双十一在即,各大网站都在争相进行限时秒杀的促销活动。秒杀是一种常见的营销手段,它指的是把少量的商品(一般是一件)以极低的价格,在特定的时间点开始销售。这些商品一般在活动开始的...

deniro
2017/11/09
0
0
如何设计一个秒杀系统——秒杀系统架构设计都有哪些关键点

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_26545305/article/details/88386842 一、如何理解秒杀系统 秒杀系统其实主要解决两个问题,一个是并发读,...

LemmonTreelss
03/11
0
0
如何设计一个秒杀程序及避免超卖问题

很多的电商平台,在节假日如双十一,618等都会有商品描述的活动,今天和大家讨论一下,如何设计一个秒杀系统。 什么是秒杀 在一定的时间内几秒或者几分钟,对一定数量的库存进行出卖。 场景分...

时之令
2018/06/08
0
0
北京社区 | Apache RocketMQ 首届开发者训练营

时间:2019.06.29(周六) 18:00-21:00 地点:北京市海淀区中关村大街46号院 北京众海投资-东门(人民大学地铁站A2出口附近) 每位到场开发者都可获得极客时间99元课程卡 课程目的 掌握Rocke...

ApacheRocketMQ社区
06/22
20
0

没有更多内容

加载失败,请刷新页面

加载更多

Mybatis Plus删除

/** @author beth @data 2019-10-17 00:30 */ @RunWith(SpringRunner.class) @SpringBootTest public class DeleteTest { @Autowired private UserInfoMapper userInfoMapper; /** 根据id删除......

一个yuanbeth
今天
4
0
总结

一、设计模式 简单工厂:一个简单而且比较杂的工厂,可以创建任何对象给你 复杂工厂:先创建一种基础类型的工厂接口,然后各自集成实现这个接口,但是每个工厂都是这个基础类的扩展分类,spr...

BobwithB
今天
5
0
java内存模型

前言 Java作为一种面向对象的,跨平台语言,其对象、内存等一直是比较难的知识点。而且很多概念的名称看起来又那么相似,很多人会傻傻分不清楚。比如本文我们要讨论的JVM内存结构、Java内存模...

ls_cherish
今天
4
0
友元函数强制转换

友元函数强制转换 p522

天王盖地虎626
昨天
5
0
js中实现页面跳转(返回前一页、后一页)

本文转载于:专业的前端网站➸js中实现页面跳转(返回前一页、后一页) 一:JS 重载页面,本地刷新,返回上一页 复制代码代码如下: <a href="javascript:history.go(-1)">返回上一页</a> <a h...

前端老手
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部