惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Tor Project blog
博客园 - 聂微东
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
IT之家
IT之家
I
InfoQ
The Cloudflare Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
人人都是产品经理
人人都是产品经理
美团技术团队
B
Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Last Week in AI
Last Week in AI
TaoSecurity Blog
TaoSecurity Blog
Hacker News: Ask HN
Hacker News: Ask HN
T
Threatpost
H
Heimdal Security Blog
爱范儿
爱范儿
博客园_首页
SecWiki News
SecWiki News
腾讯CDC
大猫的无限游戏
大猫的无限游戏
GbyAI
GbyAI
The Register - Security
The Register - Security
N
News | PayPal Newsroom
Recent Commits to openclaw:main
Recent Commits to openclaw:main
云风的 BLOG
云风的 BLOG
酷 壳 – CoolShell
酷 壳 – CoolShell
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Security Latest
Security Latest
A
Arctic Wolf
P
Privacy & Cybersecurity Law Blog
T
The Blog of Author Tim Ferriss
M
MIT News - Artificial intelligence
Microsoft Security Blog
Microsoft Security Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
量子位
Schneier on Security
Schneier on Security
Microsoft Azure Blog
Microsoft Azure Blog
Attack and Defense Labs
Attack and Defense Labs
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Webroot Blog
Webroot Blog
C
Check Point Blog
Y
Y Combinator Blog
T
The Exploit Database - CXSecurity.com
aimingoo的专栏
aimingoo的专栏
I
Intezer
博客园 - 叶小钗
Cisco Talos Blog
Cisco Talos Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
小众软件
小众软件

博客园 - 山峰旺旺

博文阅读密码验证 - 博客园 2019年春节第一天上班 FastDFS搭建文件系统(单机版) 博文阅读密码验证 - 博客园 CentOS7 下docker 部署 Asp.Net Core Linux (CentOS7.0)安装Asp.Net Core项目总结 Linux 下 安装 .Net Core(CentOS 7) Spring框架IOC容器和AOP解析(转) 文本相似度simhash算法 Intellij Idea 2017.3版本MAVEN项目打JAR包 java 敏感词过滤 (DFA算法)(转) intellij idea 修改背景保护色&&修改字体&&快捷键大全(转) 2018年目标和愿景 CDN原理(转,学习用) 面试理论整理 C#中的where泛型约束中的new()使用(转) C# unsafe(fixed) 介于 managed code & unmanaged code之间的特性(转) C#中重写(override)和覆盖(new)的区别 (备注:转,留自己用) 2015年总结
C#队列Queue实现一个简单的电商网站秒杀程序
山峰旺旺 · 2018-04-24 · via 博客园 - 山峰旺旺

转自:https://www.cnblogs.com/yinrq/p/8883476.html

电商的秒杀和抢购,对程序员来说,都不是一个陌生的东西。然而,从技术的角度来说,这对于Web系统是一个巨大的考验。当一个Web系统,在一秒钟内收到数以万计甚至更多请求时,系统的优化和稳定至关重要。

我们直接将请求放入队列Queue中的,采用FIFO(First Input First Output,先进先出),这样的话,我们就不会导致某些请求永远获取不到锁。这里有点强行将多线程变成单线程的感觉。

秒杀看似简单,但是可能会存在两个问题:高并发和超卖

高并发:比较火秒杀活动同时参与秒杀人数都是10w+的,如此之高的秒杀人数对于网站架构从前到后都是一种考验。

超卖:秒杀商品都会有固定的数量,如何避免成功下订单买到商品的人数不超过商品数量的上限,这是每个抢购活动都要面临的一大难题。

此代码简单说明问题,例如有10万个人秒杀10个商品,我们定义队列queueAll 存放并发的10万人,queueCur存放已经抢到的10个人

1

2

3

private static int cnt =10;

private static Queue<string> queueAll = new Queue<string>();

private static Queue<string> queueCur = new Queue<string>();

购买代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

public RetData Buy(string uid)

{

    queueAll.Enqueue(uid);

    if (queueAll.Count > cnt){

        return new RetData {Code = -1, Msg = "商品抢光了", Cnt = 0};

    }

    queueCur.Enqueue(uid);

    return new RetData { Code = 1, Msg = "恭喜已抢到", Cnt = cnt - queueAll.Count };

}

public class RetData

{

    public int Code { getset; }

    public string Msg { getset; }

    public int Cnt { getset; }

}

处理订单

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

public static void HandleQueue()

{

    Task.Factory.StartNew(() =>

    {

        while (trueif (queueCur.Count > 0) HandleOrder();

    });

}

public static void HandleOrder()

{

    while (queueCur.Count != 0)

    {

        Console.WriteLine("处理用户订单中:" + queueCur.Dequeue());

    }

}

Parallel模拟10万用户并发请求

1

2

3

4

5

6

7

8

9

10

11

12

13

var tt = new ThreadPar();

Parallel.For(0, 100000, (t, state) =>

{

    var uid = "用户" + t;

    var x = tt.Buy(uid);

    if (x.Code == -1)

    {

        Console.WriteLine(uid + ":" + x.Msg);

    }

    else

        Console.WriteLine(uid + ":" + x.Msg + "还剩下:" + x.Cnt + "件");

});

处理中,由于数据太多看不到谁抢到了商品,后面注释了抢不到的输出

用户0、1、75000、50000、50001、50002 、50003 、50004、25000、75001 这10位抢到了商品,其他人都没有抢到,

public class ThreadPar
{
private static int cnt =10;
private static Queue<string> queueAll = new Queue<string>();
private static Queue<string> queueCur = new Queue<string>();
//private static object ol = new object();

static ThreadPar()
{
HandleQueue();
}

public RetData Buy(string uid)
{
queueAll.Enqueue(uid);

if (queueAll.Count > cnt){
return new RetData {Code = -1, Msg = "商品抢光了", Cnt = 0};
}
queueCur.Enqueue(uid);
return new RetData { Code = 1, Msg = "恭喜已抢到", Cnt = cnt - queueAll.Count };
}
public class RetData
{
public int Code { get; set; }
public string Msg { get; set; }
public int Cnt { get; set; }
}
public static void HandleQueue()
{
Task.Factory.StartNew(() =>
{
while (true) if (queueCur.Count > 0) HandleOrder();
});
}

public static void HandleOrder()
{
while (queueCur.Count != 0)
{
Console.WriteLine("处理用户订单中:" + queueCur.Dequeue());
}
}

}

class Program
{
static void Main()
{
ThreadBuy();

Console.WriteLine("----------操作完成----------");
Console.ReadKey();
}

//秒杀
static void ThreadBuy()
{
System.Threading.Thread.Sleep(10000);
var tt = new ThreadPar();
Parallel.For(0, 1000000, (t, state) =>
{
var uid = "用户" + t;
var x = tt.Buy(uid);
if (x.Code == -1)
{
Console.WriteLine(uid + ":" + x.Msg);
//state.Break();
}
else
{
Console.WriteLine(uid + ":" + x.Msg + "还剩下:" + x.Cnt + "件");
}

});

}

}