秒杀系统架构优化思路

看了沈剑的这篇文章,写的很好,很有总结的必要。总的来说主要是通过分层缓存,限流,校验来优化秒杀架构

一、秒杀系统为什么难做

秒杀系统,库存只有一份,所有人会集中在一个时间去读写这些数据。比如12306抢票,票是有限的,库存只有一份,瞬时流量非常多,都读相同的库存。读写冲突,锁非常严重,这就是秒杀业务难的地方

二、优化方向

  • 将请求尽量拦截在上游(不要让锁冲突落到数据库上)
  • 充分利用缓存(买票系统等,都是读多写少的,可以好好利用缓存)

三、各层次优化

  • (1)浏览器端,最上层,会执行到一些JS代码
  • (2)站点层,这一层会访问后端数据,拼html页面返回给浏览器
  • (3)服务层,向上游屏蔽底层数据细节,提供数据访问
  • (4)数据层,最终的库存是存在这里的,mysql是一个典型(当然还有会缓存)

站点层通过RPC调用服务层,服务层是一个常驻内存的服务

3.1、业务层

分时分段售票。比如12306,不同的火车会在不同的时间段开放售票。将流量均摊

3.2、浏览器层

  • 产品层面:用户点击查询或者购票后,按钮置灰,禁止重复点击
  • js层面:限制用户在x秒内只能提交一次请求
    程序猿抓包写个for循环咋办?

3.3站点层

  • 对uid、IP进行计数和去重(一个uid,5s只能1个请求,这样能拦截大量请求)
  • 页面缓存,同一个uid,限制访问频度,做页面缓存,x秒内到达的请求,都返回同一个页面。既保证了用户的体验(没有404),又保证系统健壮性。
  • 如果请求量还是太大,直接把请求抛弃吧。抛弃50%,一定要保证系统的稳定性,不能让所有用户都失败。

3.4、服务层

  • 一列火车200张票,投1w个请求到db层是没有意义的,所以我们用请求队列
  • 对于写请求,都放入请求队列,比如200张票,我就只放200个下单请求到db,其他都返回无票了。
  • 对于读请求,做缓存呀,redis、memcached单机可以抗10w的qps的,本来上册已经拦截这么多,到这里使用缓存完全可以拦截呀。
  • 粒度优化,流量大的时候,只告诉用户有票还是无票,等正真票没了的时候,才去更新redis说无票了,不需要每次减一张票都去更新读的redis

四、数据库层

  • 这一层已经没有什么流量了,上面已经把99%的垃圾流量都拦截了。db已经没有压力了。
  • 如果秒杀都没有支付怎么办?在x分钟后重新回仓,通知用户在x分钟后可以继续抢购
文章目录
  1. 1. 一、秒杀系统为什么难做
  2. 2. 二、优化方向
  3. 3. 三、各层次优化
    1. 3.0.1. 3.1、业务层
    2. 3.0.2. 3.2、浏览器层
    3. 3.0.3. 3.3站点层
    4. 3.0.4. 3.4、服务层
  • 4. 四、数据库层
  • ,