1. 一趟火车其实只有2000张票,200w个人来买,最多2000个人下单成功,其他人都是查询库存,写比例只有0.1%,读比例占99.9%,非常适合使用缓存。
1.4 前端层设计1、需要解决的几个问题
1)第一个是秒杀页面的展示
1. 我们知道一个html页面还是比较大的,即使做了压缩,http头和内容的大小也可能高达数十K,加上其他的css, js,图片等资源
2. 如果同时有几千万人参与一个商品的抢购,一般机房带宽也就只有1G~10G,网络带宽就极有可能成为瓶颈
3. 所以这个页面上各类静态资源首先应分开存放,然后放到cdn节点上分散压力,由于CDN节点遍布全国各地,能缓冲掉绝大部分的压力
2)第二个是倒计时
1. 出于性能原因这个一般由js调用客户端本地时间,就有可能出现客户端时钟与服务器时钟不一致,另外服务器之间也是有可能出现时钟不一致。
2. 客户端与服务器时钟不一致可以采用客户端定时和服务器同步时间,这里考虑一下性能问题。
3. web服务器之间时间不同步可以采用统一时间服务器的方式,比如每隔1分钟所有参与秒杀活动的web服务器就与时间服务器做一次时间同步。
3)浏览器层请求拦截
1. 产品层面,用户点击“查询”或者“购票”后,按钮置灰,禁止用户重复提交请求;
2. JS层面,限制用户在x秒之内只能提交一次请求;
2、站点层设计
注:前端层的请求拦截,只能拦住小白用户,直接调用你后端的http请求,怎么整?
1. 同一个uid,限制访问频度,做页面缓存,x秒内到达站点层的请求,均返回同一页面
2. 同一个item的查询,例如手机车次,做页面缓存,x秒内到达站点层的请求,均返回同一页面
3. 如此限流,又有99%的流量会被拦截在站点层。
3、服务层设计
1)处理写请求
1. 服务层,清楚的知道小米只有1万部手机,我透10w个请求去数据库没有任何意义。
2. 可以做请求队列,每次只透过有限的写请求去数据层,如果均成功再放下一批,如果库存不够则队列里的写请求全部返回“已售完”;
2)对于读请求
1. cache来抗,不管是memcached还是redis,单机抗个每秒10w应该都是没什么问题的;
2. 用户请求分发模块:使用Nginx或Apache将用户的请求分发到不同的机器上。
3. 用户请求预处理模块:判断商品是不是还有剩余来决定是不是要处理该请求。
4. 用户请求处理模块:把通过预处理的请求封装成事务提交给数据库,并返回是否成功。
5. 数据库接口模块:该模块是数据库的唯一接口,负责与数据库交互,提供RPC接口供查询是否秒杀结束、剩余数量等信息。
1.5 数据库设计1、数据库设计要考虑的问题
1. 如何保证数据可用性;
2. 如何提高数据库读性能(大部分应用读多写少,读会先成为瓶颈);
3. 如何保证一致性;
4. 如何提高扩展性;
2、如何保证数据的可用性?(问题1)
1. 解决可用性问题的思路是=>冗余
2. 如何保证站点的可用性?复制站点,冗余站点
3. 如何保证服务的可用性?复制服务,冗余服务
4. 如何保证数据的可用性?复制数据,冗余数据
注:数据的冗余,会带来一个副作用=>引发一致性问题(先不说一致性问题,先说可用性)。
3、如何保证数据库“读”高可用?(问题2)
1. 实际的玩法:服务+数据库+缓存 的方式提供数据访问,用cache提高读性能。
2. 业务层不直接面向db和cache,服务层屏蔽了底层db、cache的复杂性。