本文已收录在Github仓库,其中包括计算机基础、Java基础、多线程、JVM、数据库、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分布式、微服务、设计模式、架构等核心知识点,欢迎star~Github地址:https://github.com/Tyson0314/...秒杀系统涉及的知识点高并发,缓存,锁机制基于Redis和Memcached的缓存架构。不在队列中。稍微大一点的尖峰肯定是分布式集群,并发来自多节点的JVM。同步JVM上的所有锁将不起作用。数据库压力峰值超卖。如何防止用户刷卡、黑名单?IP限制?使用memcached的原子操作来进行并发控制峰值。简单的设计方案。比如有10个需要秒杀的item,可以放在缓存中,读写的时候不要加锁。当并发量大的时候,闪杀成功的可能有25人,这样后面就可以直接抛出闪杀结束的静态页面了。进去的25个人,不可能有15个人拿到货。因此,按照入场顺序,只有前10人才能购买成功。接下来的15个人直接把货扔了,秒杀就结束了。例如,10件商品等待秒。假设有100台web服务器(假设web服务器为Nginx+Tomcat),n个应用服务器,n个数据库。第一步,如果Java层做过滤,可以做一个计数器AtomicInteger(每个web服务器的业务处理模块中10))=待等待商品总数,如果decreaseAndGet()>=0,继续做后续处理,如果<0则直接返回秒杀结束页面,这样第一步处理后只剩下100*10=1000个请求。第二步,将10放入memcached中,商品id作为key的值。每个web服务器收到每个请求后,向memcached服务器发起请求,使用memcached的decr(key,1)操作返回值>=0继续处理,其余返回秒杀失败页面,所以经过第二步处理后,只剩下100个请求中到达最快的10个。第三步,向App服务器发起下单操作事务。第四步,App服务器向商品所在数据库请求减库存操作(操作数据库时,可以“updatetablesetcount=count-1whereid=commodityidandcount>0;”)更新成功记录数为1,然后提交订单将订单记录添加到数据库后提交整个交易,否则会提示秒杀失败,用户进入支付流程,看淘宝的秒杀1、前端面临高并发抢购活动,前端常用的三个trick是【扩容】【静态改造】【限制】Expansion:加机器,这是最简单的抵御峰值的方式,通过增加前端池的整体负载能力静态化:将活动页面所有可以静态化的元素静态化,尽量减少动态元素。使用CDN抗峰限流:一般采用IP级限流,即就是,针对某个IP,限制单位时间内发起的请求数。或添加游戏或问题链接以消除事件入口处的峰值。服务丢失:不得已,当前端池水位接近上限时,随机拒绝部分请求,以保障活动的整体可用性。二、后端数据库在高并发和超载的情况下会遇到什么问题?首先,MySQL本身在高并发处理性能上会存在问题。一般来说,MySQL的处理性能会随着并发线程的增加而增加,但是在达到一定的并发度后,会有一个明显的拐点,然后一路下降,最终甚至会比单体的性能还差线。其次,超卖的根本原因是减库存操作是事务操作,需要先选择,再插入,最后更新-1。最后一个-1操作不能有负数,但是在有库存的情况下多个用户并发操作时,负数是不可避免的。最后,当库存减少和高并发一起来的时候,因为库存操作的数量是在同一行,所以会出现InnoDB竞争行锁的问题,导致互相等待甚至死锁,大大降低了处理性能MySQL,最终导致前端页面超时异常。如何解决以上问题?淘宝高达解决方案:一:关闭死锁检测,提高并发处理性能。II:修改源码,提到进入引擎层前的排队,降低引擎层的并发。三:分组提交,减少服务端与引擎的交互次数,降低IO消耗。方案一:保存库从MySQL前移到Redis,写操作全部放在内存中。由于Redis没有锁,不会互相等待,而且Redis的写性能和读性能都比MySQL高很多,这样就解决了问题。高并发下的性能问题。然后通过队列等异步方式,将变化的数据异步写入DB。优点:解决性能问题缺点:没有解决超卖问题。同时,由于写入DB是异步的,在某个时刻DB和Redis存在数据不一致的风险。方案二:引入一个队列,然后将所有的写DB操作排在一个队列中,完成串行处理。当达到库存阈值时,将不在消费队列中,购买功能将关闭。这解决了超卖问题。优点:解决超卖问题,性能略有提升。缺点:性能受限于队列处理器的处理性能和DB的写入性能中最短的一个。另外,同时抢购多个商品时,需要准备多个队列。方案三:将写操作前移到MC,同时利用MC的轻量级锁机制CAS实现减库存操作。优点:在内存中读写,运行性能快,引入轻量级锁后,可以保证同一时间只有一次写入成功,解决库存减少问题。缺点:没有实测。基于CAS的特性,不知道高并发下会不会出现大量更新失败?但是加锁之后,肯定会对并发性能产生影响。方案四:将提交操作改为两阶段流程,先申请再确认。然后利用Redis的原子自增操作,同时利用Redis的事务特性来发号,保证拿到号小于等于库存阈值的可以成功提交订单。然后数据异步更新到DB。优点:解决超卖问题,库存读写都在内存中,所以同时解决了性能问题。缺点:异步写入DB可能会导致数据不一致。另外,可能会出现少买的情况,即如果拿到号的人没有实际下单,库存可能会降为0,但下单数量还没有达到库存阈值。总结1.前端三轴[扩展][限流][静态]2.后端两条路[内存]+[排队]最后给大家分享一个Github仓库,里面有300多本经典书籍大斌整理的计算机书籍PDF,包括C语言、C++、Java、Python、前端、数据库、操作系统、计算机网络、数据结构与算法、机器学习、编程生活等,可以star一下,next找书的时候直接搜索就可以了,仓库持续更新~Github地址:https://github.com/Tyson0314/...
