我现在写的代码是这样的,麻烦大家帮忙看看,那些地方需要改的,唉唉,,,卡在这里很久了,一过不去 public ActionResult SecKill() { //双十一那天的秒杀活动, //早上11点钟的有611个名额,下午三点钟的有500个名额 int totalPlaces = 0;//名额 DateTime time11 = new DateTime(2015, 11, 11, 11, 0, 0); DateTime time15 = new DateTime(2015, 11, 11, 18, 0, 0); //根据时间获取队列的最大的容量 if(time11<DateTime.Now&&DateTime.Now<time15) { totalPlaces = 611; }else if(DateTime.Now>time15) { totalPlaces = 500; } SecKillQueue q = new SecKillQueue(totalPlaces);//创建队列 //入队 while (!q.IsFull()) { q.In(SessionContext.User.UserId); int count = totalPlaces - q.GetQueueLength(); return Json(new { leftCount=count });//返回剩下的名额 } //根据队列中保存的用户ID,异步往Consume表插入记录 Task.Run(() => InsertToConsume(q)); return Json(new { ret = 1, msg = "秒杀结束" }); } InsertToConsume(SecKillQueue q)方法: public static void InsertToConsume(SecKillQueue q) { //出列 while (!q.IsEmpty()) { int userId = (int)q.Out(); User user = UserServices.GetItemById(userId); //这里还要判断当前出列的用户是否已经参与参与过秒杀活动了, //如果有的话就忽略,并且还要把名额重新添加到队列 Consume consume = new Consume() { WorkShopID = user.IsWorkShop == 2 ? (int)user.WorkShopID : user.Id, SerialNumber = PromotionHelper.getOrderCode() + "-" + new Random().Next(100000, 999999), Amount = 110, ConsumeType = 1, //本金预存 PayStatus = 0 //未支付 }; ConsumeServices.Insert(consume); } }
public ActionResult SecKill() { //双十一那天的秒杀活动, //早上11点钟的有611个名额,下午三点钟的有500个名额 int totalPlaces = 0;//名额 DateTime time11 = new DateTime(2015, 11, 11, 11, 0, 0); DateTime time15 = new DateTime(2015, 11, 11, 18, 0, 0); //根据时间获取队列的最大的容量 if(time11<DateTime.Now&&DateTime.Now<time15) { totalPlaces = 611; }else if(DateTime.Now>time15) { totalPlaces = 500; } SecKillQueue q = new SecKillQueue(totalPlaces);//创建队列 //入队 while (!q.IsFull()) { q.In(SessionContext.User.UserId); int count = totalPlaces - q.GetQueueLength(); return Json(new { leftCount=count });//返回剩下的名额 } //根据队列中保存的用户ID,异步往Consume表插入记录 Task.Run(() => InsertToConsume(q)); return Json(new { ret = 1, msg = "秒杀结束" }); }
public static void InsertToConsume(SecKillQueue q) { //出列 while (!q.IsEmpty()) { int userId = (int)q.Out(); User user = UserServices.GetItemById(userId); //这里还要判断当前出列的用户是否已经参与参与过秒杀活动了, //如果有的话就忽略,并且还要把名额重新添加到队列 Consume consume = new Consume() { WorkShopID = user.IsWorkShop == 2 ? (int)user.WorkShopID : user.Id, SerialNumber = PromotionHelper.getOrderCode() + "-" + new Random().Next(100000, 999999), Amount = 110, ConsumeType = 1, //本金预存 PayStatus = 0 //未支付 }; ConsumeServices.Insert(consume); } }
你这么小负载量的东西,就是简单的注意一下“不要被数据库给绑死了”就行了。 数据库事务(特别是你将较费时的工作放到数据库事务中完成)是很费时的,而且它是完全牺牲并发性来保证瞬时一致性的。因此你应该做一个评估,看看你们的系统能不能保证一秒钟有1万个事务。如果不能(一般来说都不能),那么就很简单,在影响页面响应速度的操作中中去掉数据库就行了。 例如秒杀时,主要就是要判断一下当前剩余多少名额。那么这个数字,就不要放到数据库中,而是要放到内存中(考虑到asp.net 经常重启而丢弃内存数据,那么这个数据最好是放到 windows service 承载的服务中),并且对这个数字的修改是 lock 的。这样,就能并发几十万用户去查询这个数字。 而一旦用户界面查询完(并且 -1 修改)这个数字,产生了购物车记录,剩下的步骤,就可以异步去执行了,不需要在秒杀服务器、秒杀页面后台去执行,而是客户端重定向到购物车业务服务器、购物车业务页面去执行(此时秒杀商品的唯一的编号已经被放入购物车,而其它普通的选购页面是无法将秒杀商品放入购物车的)。 购物车本身是可以慢慢地执行的,甚至就算是服务器重启了,购物车中的商品也不会丢失。而且购物车操作不占用秒杀功能的资源(CPU、甚至带宽);秒杀则不需要考虑数据库,只要在一个服务器上支持很短的几分钟就行了。 因此秒杀,关键是不扯上数据库。然后就是要为秒杀商品建立与普通商品不同的编码系统(好在购物车上能够与普通商品区别开来)。
1) 对现有网站业务的冲击 因为秒杀活动只是网站营销的一个附加活动,这个活动具有时间短,并发访问量大的特点,如果和网站原有应用部署在一起,必然会对现有业务造成冲击,稍有不慎可能导致整个网站瘫痪。 2) 高并发情况以及数据库的负载 用户在秒杀开始前,通过不停的刷新浏览器页面以保证不会错过秒杀,这些请求如果按照一般的网站应用架构,访问应用服务器、连接数据库,会对应用服务器、数据库服务器造成极大的负载压力。 3) 突然增加的网络和服务器带宽 假设商品页面大小200K(主要是商品图片大小),那么需要的网络和服务器带宽是2G(200K×10,000),这些网络带宽是因为秒杀活动新增的,超过网站平时使用的带宽。 4) 直接下单 秒杀的游戏规则是到了秒杀时间才能开始对商品下单购买,在此时间点之前,只能浏览商品信息,不能下单。而下单页面也是一个普通的URL,如果得到这个URL,不用等到秒杀开始就可以下单了。 5) 防止机器秒杀 防止网上的一些“秒杀器” 针对上面的5个问题,对应的策略如下: 1) 秒杀系统独立部署 为了避免因为秒杀活动的高并发访问而拖垮整个网站,使整个网站不必面对蜂拥而来的用户访问,将秒杀系统独立部署,如果需要,还可以使用独立的域名,以和网站完全隔离,即使秒杀系统崩溃了,也不会对网站造成任何影响。 2) 秒杀商品页面静态化 秒杀商品页面重新设计,不使用网站原来的商品详情页面,页面内容静态化:商品描述,商品参数,成交记录,用户评价全部写入一个静态页面,用户请求不需要经过应用服务器的业务逻辑处理,也不需要访问数据库。所以秒杀商品服务不需要部署动态的Web服务器、数据库服务器。 3) 租借秒杀活动网络带宽 对于因为秒杀新增的网络带宽,必须和运营商重新购买或者租借。为了减轻网站服务器的压力,需要将秒杀商品页面缓存在CDN,同样需要和CDN服务商临时租借新增的出口带宽。 4) 动态生成随机下单页面URL 为了避免用户直接访问下单页面URL,需要将该URL动态化,即使秒杀系统的开发者也无法在秒杀开始前访问下单页面的URL。办法是在下单页面URL加入由服务器端生成的随机数作为参数,在秒杀开始的时候才能得到。 5) 防止“秒杀器”感觉很难, 因为似乎总是有办法可以跳过设置的“障碍”。真正做到防止,仅靠webserver怕是很难防范,一般的做法都是增加一些人为的“障碍”,比如: 注册时有一定的门槛,像皮皮书屋一样,通过输入程序执行结果作为验证 –à之前批量手工注册 参加秒杀的积分或者等级策略 -à 挂太阳,就如同你当你为了升级QQ等级的时候一直挂着QQ一样。 验证码,阻止自动化操作 -à 可以图像识别 ip阻止 –à 但是ip可以伪造,可以代理
不是该直接提示“本次活动已经结束,感谢您的参与”之类的话么?
引用 15 楼 lc_antt 的回复:你的用户秒杀资格判断是不是应该在用户点击的时候就判断,而不是用户已经秒杀到了,再在InsertToConsume()方法里面去判断用户点击的时候该怎么判断呢?
你的用户秒杀资格判断是不是应该在用户点击的时候就判断,而不是用户已经秒杀到了,再在InsertToConsume()方法里面去判断
62,073
社区成员
669,028
社区内容
加载中
.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。
希望和大家一起共同营造一个活跃、友好的社区氛围。
试试用AI创作助手写篇文章吧