您现在的位置是:首页 > 文章详情

设计一个秒杀系统

日期:2018-11-04点击:408

设计一个秒杀系统

1 设计的架构原则

1.1 4要1不要

  1. 尽量减少请求数量

    js,css等额外请求要少 合并请求

  2. 尽量减少请求数据

  3. 尽量减少请求路径

    用户发出去请求到返回数据过程中,经过的中间节点数要少

  4. 请求依赖要尽量少

    秒杀系统中的商品信息和用户信息是关键信息,优惠券列表,成交列表弱依赖

  5. 不要有单点

    避免服务状态华

1.2 不同场景的架构

img_cf51e57db8f300530b7fe9a2fb874e46.png
秒杀系统架构1
商品购买增加定时上架 -- 秒杀开始,才能看到按钮 单独部署 不和其他业务冲突 热点数据放到缓存 增加秒杀答题,方式秒杀器抢单 
img_e1aa9bf360a7b69e105011f36c673edf.png
秒杀系统架构2
页面动静分离 在服务端对秒杀少商品进行缓存 增加系统限流保护 

2 动静分离的可选方案

2.1 为什么要考虑动静分离

提高了单次的请求效率

减少了没必要的请求

2.2 怎么区分动静数据

动静数据主要区别就是看页面中输出的数据是否和URL,浏览者,时间,地域相关,以及是否含有Cookie等私密数据。

静态数据不是磁盘上的HTML内容,而是数据中是否有个性化的数据。

2.3 怎么对静态数据缓存

  1. 把静态数据缓存到离用户最近的地方,例如 浏览器里,CDN,或者服务端的Cache。

  2. 静态化改造就是要直接缓存HTTP连接,WEB代理服务器根据请求URL,直接取出对应的HTTP响应头和响应体直接返回。

  3. 在系统那个部分做静态缓存?WEB服务器由于Java语言。

2.4 怎么进行动静分离

怎么分离动态内容:

  1. URL唯一话,每个商品的URL是独一无二的。

  2. 分离浏览者相关的因素,包括是否登录,以及登录身份,这些相关因素可以单独拆分出来,通过动态请求来获取。

  3. 分离时间因素,服务端输出的时间也应该通过动态请求获取。

  4. 异步化地域因素,请求页面上与地域相关的因素做异步式获取。

  5. 去掉Cookie。缓存的静态数据中不包含有Cookie.

动态内容处理通用的两种方案:

  1. ESI方案,在Web代理服务器上做动态内容请求,并将请求插入静态页面中,当用户拿到页面的时候已经是一个完整的页面。

  2. CSI方案,单独发起一个异步的JavaScript请求,以向服务端获取动态内容。

2.5 架构方案

2.5.1 实体机单机部署

采用一致性Hash分组的方式来提升命中率,这里将Cache分成若干组,是希望能达到命中率和访问率的平衡。

优点:

  1. 没有网络瓶颈,而且能使用大内存。
  2. 既能提升命中率,又能减少Gzip压缩。
  3. 减少Cache失效压力,因为采用定时失效方式。
    缺点:
    运维复杂度高
2.5.2 统一Cache层

将单机的Cache统一分离出来,形成一个单独的Cache集群。

优点:

  1. 可以减少多个应用接入Cache的成本,只需关注自己的Java系统就好。
  2. 易于维护。
  3. 共享内存,最大化利用内存。不同系统之间的内存可以动态切换。

缺点:

  1. Cache层内部交换网络成为瓶颈。
  2. 缓存服务器的网卡也会成为瓶颈。
  3. 机器少,风险比较大,挂掉一台会影响很大一部分缓存数据。
2.5.3 上CDN

3 二八原则:有针对的处理好系统的热点数据

3.1 热点?

热点请求会占用大量服务器资源。

热点操作:

热点数据:静态热点数据(提前预测的热点数据,大数据分析热点商品,历史成交记录,用户购物车)+动态热点数据()

3.2 发现热点数据

3.2.1 发现静态热点数据
  1. 卖家报名的方式,然后给卖家的商品打tag,数据进行预处理,然后缓存数据。
  2. 分析买家访问的商品等,然后统计出TOP N的商品。
3.2.2 发现动态热点数据

系统内部秒级自动发现热点商品

  1. 构建一个异步的系统,进行收集交易链路上各个环节中的中间件热点key。如:Nginx,缓存,RPC服务框架等。
  2. 上游系统把已经发现的热点透传给下游系统,提前做好保护。

3.3 如何处理热点数据

  1. 优化:缓存热点数据,用队列进行存储,采用LRU淘汰算法。
  2. 限制:作为一种保护机制,把热点请求限制在一个请求队列里面。防止热点数据占用太多资源。
  3. 隔离:热点数据隔离出来,不要让1%的请求影响到另外的99%。业务隔离+系统隔离+数据隔离。

4 流量削峰

秒杀这个场景来说,最终抢到商品的人数是固定的,所以100人和10000人发起请求的结果都是一样的,并发度越高,无效请求越多。

4.1 为什么削峰

服务器能处理的资源是恒定的,所以为了服务稳定,我们延缓用户请求的发出,以便减少和过滤掉一些无效的请求。

4.2 削峰的思路

  • 排队

把一步操作,变成二步操作,其中增加一步操作用来起到缓冲的作用。

  1. 利用消息队列,把请求缓冲起来,然后消费端异步处理请求。
  2. 利用线程池加锁等待。
  3. 先进先出内存排队算法的实现方式。
  4. 把请求序列化到文件中,然后顺序的读文件来恢复请求操作。
  • 答题

一方面防止买家使用秒杀器在参加秒杀的时候作弊。一方面延缓请求,起到流量削峰的作用。

img_223ada4eaa004af9edd083f489e3c884.png
image
  • 分层过滤
img_7cd375e3cf3cd185fbd5b40f312070ef.png
image
  1. 大部分数据和流量在用户浏览器或者CDN上获取,这一层拦截大部分数据的读取。
  2. 前台系统的数据,尽量得走cache,过滤一些无效请求。
  3. 后台系统,做数据的二次校验,对系统做好保护和限流。
  4. DB数据层,完成数据的强一致性校验。

基本原则

  1. 将动态请求的读数据缓存在Web端,过滤掉无效请求读。
  2. 对读数据不做强一致性校验,减少因为一致性校验产生瓶颈的问题。
  3. 对写数据进行基于时间的合理分片,过滤掉过期的失效请求。
  4. 对写请求做限流保护,将超出系统承载能力的请求过滤掉。
  5. 对写数据进行强一致性校验,只保留最后有效的数据。

5 提升系统性能

5.1 影响性能的因素

响应时间:

每秒请求数:(Query Per Second)

CPU的执行时间+线程数

线程数=2*cpu+1

线程数=[(线程等待时间+线程CPU时间)/线程CPU时间]*CPU数量

5.2 如何发现瓶颈

CPU诊断工具:Jprofiler+Yourkit工具+jstack定时地打印调用栈,

QPS达到极限时候,CPU的使用率是不是超过95%,如果没有超过,那么CPU还有提升的空间。

5.3 如何优化系统

  1. 减少编码:
  2. 减少序列化
  3. Java极致优化 直接使用Servlet处理请求,直接输出流数据。
  4. 并发读优化 不变的信息,缓存系统内存里面,变化的信息,采用失效时间,失效之后拉取最新数据。

6 秒杀系统 减库存设计

6.1 减库存的几种方式

  • 下单减库存:有些人下单之后不会付款。
  • 付款减库存:买家下单之后,不能发起付款。
  • 预扣库存:买家下单之后,库存为其保留一定时间,超过这个时间,库存自动释放。在买家付款之前,系统会校验该订单的库存是否保留,如果没有保留,则再次尝试预扣,如果预扣失败,则不允许继续付款。

6.2 数据库一致性

  • 应用程序中通过事物来判断,即保证减库存不能为负数,否则就回滚。
  • 数据库字段设置为无符号整数,小于0的时候SQL抛出异常。
原文链接:https://yq.aliyun.com/articles/669657
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章