秒杀系统设计的知识点

标签: 系统 设计 知识 | 发表时间:2015-04-23 04:51 | 作者:cfyme
出处:http://www.iteye.com

秒杀系统涉及到的知识点:

 

A, 高并发,cache,锁机制 

 

B, 基于缓存架构redis,Memcached的先进先出队列。

 

C, 稍微大一点的秒杀,肯定是分布式的集群的,并发来自于多个节点的JVM,synchronized所有在JVM上加锁是不行了

 

D, 数据库压力

 

E, 秒杀超卖问题

 

F, 如何防止用户来刷, 黑名单?IP限制?

 

G, 利用memcached的带原子性特性的操作做并发控制. 

 

 

秒杀简单设计方案如:

比如有10件商品要秒杀,可以放到缓存中,读写时不要加锁。 当并发量大的时候,可能有25个人秒杀成功,这样后面的就可以直接抛秒杀结束的静态页面。进去的25个人中有15个人是不可能获得商品的。所以可以根据进入的先后顺序只能前10个人购买成功。后面15个人就抛商品已秒杀完。

 

 

 

 

 

假设我们的秒杀场景:

       比如某商品10件物品待秒. 假设有100台web服务器(假设web服务器是Nginx + Tomcat),n台app服务器,n个数据库 

 

 1. 第一步 如果Java层做过滤, 可以在每台web服务器的业务处理模块里做个计数器AtomicInteger(10)=待秒商品总数, 

 decreaseAndGet()>=0的继续做后续处理, <0的直接返回秒杀结束页面. 

 这样经过第一步的处理只剩下100台*10个=1000个请求. 

 

 2. 第二步, memcached 里以商品id作为key的value放个10, 每个web服务器在接到每个请求的同时, 向memcached服务器发起请求, 利用memcached的decr(key,1)操作返回值>=0的继续处理, 其余的返回秒杀失败页面. 

 这样经过第二步的处理只剩下100台中最快速到达的10个请求.

 

 3. 第三步, 向App服务器发起下单操作事务. 

 

 4. 第四步, App服务器向商品所在的数据库请求减库存操作, 

 (操作数据库时可以 "update table set count=count-1 where id=商品id and count>0;" update 成功记录数为1, 再向订单数据库添加订单记录, 都成功后提交整个事务, 否则的话提示秒杀失败. 用户进入支付流程. 

 

 

 

 

在看看淘宝的秒杀:

1、前端

面对高并发的抢购活动,前端常用的三板斧是【扩容】【静态化】【限流】

  A:扩容

  加机器,这是最简单的方法,通过增加前端池的整体承载量来抗峰值。

  B:静态化

  将活动页面上的所有可以静态的元素全部静态化,并尽量减少动态元素。通过CDN来抗峰值。

  C:限流

  一般都会采用IP级别的限流,即针对某一个IP,限制单位时间内发起请求数量。

  或者活动入口的时候增加游戏或者问题环节进行消峰操作。

  D:有损服务

  最后一招,在接近前端池承载能力的水位上限的时候,随机拒绝部分请求来保护活动整体的可用性。

2、后端

 

那么后端的数据库在高并发和超卖下会遇到什么问题呢

  I: 首先MySQL自身对于高并发的处理性能就会出现问题,一般来说,MySQL的处理性能会随着并发thread上升而上升,但是到了一定的并发度之后会出现明显的拐点,之后一路下降,最终甚至会比单thread的性能还要差。

  II: 其次,超卖的根结在于减库存操作是一个事务操作,需要先select,然后insert,最后update -1。最后这个-1操作是不能出现负数的,但是当多用户在有库存的情况下并发操作,出现负数这是无法避免的。

  III:最后,当减库存和高并发碰到一起的时候,由于操作的库存数目在同一行,就会出现争抢InnoDB行锁的问题,导致出现互相等待甚至死锁,从而大大降低MySQL的处理性能,最终导致前端页面出现超时异常。

 

针对上述问题,如何解决呢? 淘宝的高大上解决方案:

  I:  关闭死锁检测,提高并发处理性能。

  II:修改源代码,将排队提到进入引擎层前,降低引擎层面的并发度。

  III:组提交,降低server和引擎的交互次数,降低IO消耗。

 

解决方案1:

将存库从MySQL前移到Redis中,所有的写操作放到内存中,由于Redis中不存在锁故不会出现互相等待,并且由于Redis的写性能和读性能都远高于MySQL,这就解决了高并发下的性能问题。然后通过队列等异步手段,将变化的数据异步写入到DB中。

优点:解决性能问题

缺点:没有解决超卖问题,同时由于异步写入DB,存在某一时刻DB和Redis中数据不一致的风险。

 

解决方案2:

引入队列,然后将所有写DB操作在单队列中排队,完全串行处理。当达到库存阀值的时候就不在消费队列,并关闭购买功能。这就解决了超卖问题。

优点:解决超卖问题,略微提升性能。

缺点:性能受限于队列处理机处理性能和DB的写入性能中最短的那个,另外多商品同时抢购的时候需要准备多条队列。

 

解决方案3:

将写操作前移到MC中,同时利用MC的轻量级的锁机制CAS来实现减库存操作。

优点:读写在内存中,操作性能快,引入轻量级锁之后可以保证同一时刻只有一个写入成功,解决减库存问题。

缺点:没有实测,基于CAS的特性不知道高并发下是否会出现大量更新失败?不过加锁之后肯定对并发性能会有影响。

 

解决方案4:

将提交操作变成两段式,先申请后确认。然后利用Redis的原子自增操作,同时利用Redis的事务特性来发号,保证拿到小于等于库存阀值的号的人都可以成功提交订单。然后数据异步更新到DB中。

优点:解决超卖问题,库存读写都在内存中,故同时解决性能问题。

缺点:由于异步写入DB,可能存在数据不一致。另可能存在少买,也就是如果拿到号的人不真正下订单,可能库存减为0,但是订单数并没有达到库存阀值。

 

三、总结

1、前端三板斧【扩容】【限流】【静态化】

2、后端两条路【内存】+【排队】

 

 以上所有资料均来自互联网

 



已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [系统 设计 知识] 推荐:

秒杀系统设计的知识点

- - 互联网 - ITeye博客
A, 高并发,cache,锁机制 . B, 基于缓存架构redis,Memcached的先进先出队列. C, 稍微大一点的秒杀,肯定是分布式的集群的,并发来自于多个节点的JVM,synchronized所有在JVM上加锁是不行了. F, 如何防止用户来刷, 黑名单. G, 利用memcached的带原子性特性的操作做并发控制. .

系统设计的典型分层和涉及的知识点

- - 四火的唠叨
作为系统设计学习的一部分,不久前在梳理面试中典型的系统设计问题,发现大部分都可谓有套路可寻. 我把思路梳理了一下,简单整理到下面这张图表里面:. 对于其中的内容,稍微补充几句:. 系统设计需要经验的积累,但也确确实实有章可循. 问的问题考察的类型很集中,比如同步、异步,消息push和pull,根据实际问题设计存储的数据结构,对于scalability、availability的认识等等.

设计师需要的知识体系

- - 博客 - 伯乐在线
产品设计师面对复杂、庞大的制造业系统以及多元化的市场,其知识体系要同时具备广度和深度. 设计是循序渐进、不断深入的过程,因此我们面对的是交错的学科体系,以及深入的技术探究. 当国内工业设计教育界还在热烈地争论设计是艺术还是技术时,不妨退一步思考,设计本身既融合又独立,既有依附性又具有本身不可替代的意义.

设计师的知识管理

- - 百度MUX
人们每谈到设计很自然的就会联想到创意、想法. 作为设计师,好像我们的大脑里就理所应当地充满了各种创意,然而这些创意是本来就存在于大脑里的吗. 有人说创意来自冥想,我不否认有些天赋超人的设计神人可以通过冥想产生内容,但是对于非神设计师来说,冥想只是一个将脑海中的旧有内容进行重新组合并且呈现出来的一个方法.

评价系统设计篇

- - 互联网 - ITeye博客
评论系统大家都见得非常多了,大到京东、淘宝、亚马逊,小到个人网站、博客都有评论系统,小型网站采用传统PHP+Mysql方式就能很快将系统搭建起来,同时采用单库单表方式就能轻松解决数据存储、数据查询等问题,但是对于上述中大型网站而言,已经远远不能支撑系统正常运行了. 接下来将从系统架构、数据存储、高性能服务等方面来揭示京东的评价系统在面对海量数据、海量请求的情况是如何处理的.

如何把学到的知识系统化?

- - 战隼的学习探索
总能在知乎上发现一些眼前一亮的回答, 俞海鸥 的答案不错,很真实的个人经验. 知乎地址: http://www.zhihu.com/question/20737761. 这个问题跟: 六个步骤把资料转换成知识 这里的答案类似,实际上不外乎:. 流程化、系统化,形成节奏感. 通过知识管理来完成以下几项:.

软件公司如何免费搭建知识管理系统

- - 研发管理 - ITeye博客
知识管理对于一个公司来说非常重要,目前市面上有很多用于知识管理的软件,但是费用都比较高. 而使用几个开源网站代码,就可以在公司搭建起有效的知识管理系统了. 以下以Mantis+Testlink+SVN+Dokuwiki+Twitter 为例,简单说明如何搭建公司级的知识管理系统. 百度经验:jingyan.baidu.com.

关于个人知识管理系统 2014-03-08

- - CSDN博客综合推荐文章
美国教育家布鲁纳曾说过:“获得的知识,如果没有完满的结构把它联系在一起,那是一种多半会被遗忘的知识.   个人通过工具(即软件)建立知识体系(是一个知识网络)并不断跟踪完善优化,进行知识的收集、消化吸收和创新的过程,并且随时据情况进行结构调整或内容更新,它还提供某种将散乱的信息片段转化为可以系统性应用的东西的(个人)战略,并以此扩展我们的个人知识.

思考系统API设计的问题

- edware_love - C++博客-首页原创精华区
最近正好在思考系统API设计中考量的一些问题,. 我现在的理解是这样的,假设有巨大的真实内存. windows首先将高2G的内存自己占了,用作各种内核对象. 这2G内存共享给每个进程,但进程不能直接访问,只能通过windows给定的函数访问. : 然后每个进程都给他2G内存,进程如果创建自己的对象就放到自己那2G内存里面,如果要建立内核对象就放到共享的那高2G里面去.

系统设计中的简单法则

- - 酷勤网-挖经验 [expanded by feedex.net]
最近,包云岗在自己的 博客中总结了系统设计中的基本法则——简单之美,列举了不少经典观点和案例. 他首先总结了麻省理工方法(MIT Approach)和新泽西方法(New Jersey Approach)的异同:. 简单性:两种方法都强调设计必须简单,这既是对实现的要求,也是对接口的要求. 但是,MIT方法认为接口的简单要比实现的简单更加重要,而NJ方法认为实现的简单要比接口的简单更加重要.