秒杀系统难点往往是短时间内对数据进行读写,然后造成读写上的一些冲突,甚至锁非常严重.当然知道难点在哪里,我们自然就有办法解决,人类智慧无限,办法总比困难多. 简单说来也就两点,限流和提升关键点的性能.
(1)限流,将请求尽量拦截在系统上游,流量层层过滤,当请求到达稀缺资源比如数据库的时候,流量变小,数据库的压力已经可以忽略.传统秒杀系统之所以挂,请求都压倒了后端数据层,数据读写锁冲突严重,并发高响应慢,几乎所有请求都超时,流量虽大,下单成功的有效流量甚小。
(2)提升关键点的性能,充分利用缓存便是一个不错的提升性能的方式.因为数据库的性能提升往往比较困难,而人们换个思考问题的方式, 既然数据库性能提升不容易,那换一个性能高的数据存储的地方总可以,缓存便是这种思路下产生的,缓存数据存放在内存中,处理的速度远大于数据库,这样便换角度的提升了数据访问的性能
常见的站点架构基本是这样的,这个图主要展示为了能够架构秒杀系统所需要改变的点.
浏览器端,最上层,会执行到一些JS代码,这个地方往往进行第一次流量过滤,主要是过滤重复提交的数据
代理,再一次对流量进行过滤
网站,这一层会访问后端数据,拼html页面返回给浏览器,这里再次对流量进行过滤
服务层,向上游屏蔽底层数据细节,提供数据访问
数据层,最终的库存是存在这里的,缓存也是使用在这里,传统的是使用数据库
各层次优化细节
客户端怎么优化(浏览器层,APP层)
- 设计:用户点击一次提交以后不再允许能够提交,比如将按钮置灰.
- 技术:可以使用js限制用户点击,提交的次数,例如一分钟之内只能点击一次.
这样在最上层,通过设计与技术手段就能够阻拦80%以上的流量,虽然如何但剩余的流量依然很大.所以还需要继续阻击.
代理层面的请求拦截
这里我们为了分担后端服务器压力,往往使用反向代理服务器,例如nginx, 这个地方可以配置nginx限流措施,比如单位时间只能有5万的访问量,这个时候再一次的阻拦了一部分流量.
站点层面的请求拦截
在站点层面,对用户id(当然需要登录)进行请求计数和去重。一个用户id,单位时间内(比如5秒)只准透过1个请求,这样又能拦住一大部分的请求。只透过一个请求,其余的请求怎么办?缓存,页面缓存,同一个用户id,限制访问频度,做页面缓存,单位时间内到达站点层的请求,均返回同一页面。同一个item的查询。
服务层来拦截
对于写请求,做请求队列,每次只透有限的写请求去数据层
对于读请求,用缓存,不管是memcached还是redis,单机抗个每秒10w应该都是没什么问题的。如此限流,只有非常少的写请求,和非常少的读缓存mis的请求会透到数据层去,又有99.9%的请求被拦住了。
数据库层
当数据经过层层阻击到达数据层的时候,流量已经过滤掉了绝大部分,服务层又做了写请求队列与数据缓存,每次透到数据库层的请求都是可控的。db基本就没什么压力了,闲庭信步,单机也能扛得住.
总结
秒杀系统是对单个请求的无限放大,解决方式总结一句话,限流与增加性能.
http://blog.csdn.net/bemavery/article/details/77448589