首页 > 编程 > .NET > 正文

asp.net通过消息队列处理高并发请求(以抢小米手机为例)

2024-07-10 12:49:44
字体:
来源:转载
供稿:网友

网站面对高并发的情况下,除了增加硬件, 优化程序提高以响应速度外,还可以通过并行改串行的思路来解决。这种思想常见的实践方式就是数据库锁和消息队列的方式。这种方式的缺点是需要排队,响应速度慢,优点是节省成本。

演示一下现象

创建一个在售产品表

CREATE TABLE [dbo].[product](  [id] [int] NOT NULL,--唯一主键  [name] [nvarchar](50) NULL,--产品名称  [status] [int] NULL ,--0未售出 1 售出 默认为0  [username] [nvarchar](50) NULL--下单用户 )

添加一条记录

insert into product(id,name,status,username) values(1,'小米手机',0,null)

创建一个抢票程序

public ContentResult PlaceOrder(string userName)    {      using (RuanMou2020Entities db = new RuanMou2020Entities())      {          var product = db.product.Where<product>(p => p.status== 0).FirstOrDefault();          if (product.status == 1)          {            return Content("失败,产品已经被卖光");          }          else          {            //模拟数据库慢造成并发问题            Thread.Sleep(5000);            product.status = 1;            product.username= userName;              db.SaveChanges();               return Content("成功购买");             }       }     }

如果我们在5秒内一次访问以下两个地址,那么返回的结果都是成功购买且数据表中的username是lisi。

/controller/PlaceOrder?username=zhangsan

/controller/PlaceOrder?username=lisi

这就是并发带来的问题。

第一阶段,利用线程锁简单粗暴

Web程序是多线程的,那我们把他在容易出现并发的地方加一把锁就可以了,如下图处理方式。

    private static object _lock = new object();    public ContentResult PlaceOrder(string userName)    {      using (RuanMou2020Entities db = new RuanMou2020Entities())      {        lock (_lock)        {          var product = db.product.Where<product>(p => p.status == 0).FirstOrDefault();          if (product.status == 1)          {            return Content("失败,产品已经被卖光");          }          else          {            //模拟数据库慢造成并发问题            Thread.Sleep(5000);            product.status = 1;            product.username = userName;            db.SaveChanges();            return Content("成功购买");          }        }      }    }

这样每一个请求都是依次执行,不会出现并发问题了。

优点:解决了并发的问题。

缺点:效率太慢,用户体验性太差,不适合大数据量场景。

第二阶段,拉消息队列,通过生产者,消费者的模式

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表