• C#队列Queue实现一个简单的电商网站秒杀程序


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

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

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

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

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

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

            private static int cnt =10;
            private static Queue<string> queueAll = new Queue<string>();
            private static Queue<string> queueCur = new Queue<string>();
    

    购买代码

            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());
                }
            }
    

    Parallel模拟10万用户并发请求

                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);
                        //state.Break();
                    }
                    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());
                }
            }
    
        }
    View Code
        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 + "");
                    }
                        
                });
    
            }
    
        }
    控制台程序
  • 相关阅读:
    Tensorflow2(预课程)---2.1、多层感知器-层方式
    pandas.Series转numpy的n维数组
    numpy将多维数组降维成一维
    《仙路争锋》读书感悟---200910(为逆所以顺,为玩所以勤,为生所以死)
    legend3---解决bootstrap栅格系统自动图片高度不齐问题
    python机器学习库numpy---15、模拟e^x的麦克劳林展开式
    400G 光模块的价格
    HTML编辑器 实现ctrl+v粘贴图片并上传、word粘贴带图片
    网页编辑器 实现ctrl+v粘贴图片并上传、word粘贴带图片
    富文本编辑器 实现ctrl+v粘贴图片并上传、word粘贴带图片
  • 原文地址:https://www.cnblogs.com/yinrq/p/8883476.html
Copyright © 2020-2023  润新知