概述
稳,保证整个系统满足高可用
准,不能有超卖,也就是一致性
快,也就是高性能
总体来说就是高可用,一致性,高性能
高性能,涉及大量的并发读,并发写,方案包括东京分离,热点的发现与隔离,请求的削峰与分层过滤,服务端极致优化
一致性,有限的商品在同一时间N多请求访问,减库存包括-拍下减库存,付款减库存,预扣款等
高可用,还需要设计一个备用方案,确保在最坏的情况下系统仍然可用
架构原则
“4 要 1 不要”
1. 数据要尽量少
2. 请求数要尽量少
把多个 JavaScript 文件合并成一个文件,在 URL 中用逗号隔开(https://g.xxx.com/tm/xx-b/4.0.94/mods/??module-preview/index.xtpl.js,module-jhs/index.xtpl.js,module-focus/index.xtpl.js)。这种方式在服务端仍然是单个文件各自存放,只是服务端会有一个组件解析这个 URL,然后动态把这些文件合并起来一起返回。
3. 路径要尽量短
用户发出请求到返回数据这个过程中,需求经过的中间的节点数
要缩短访问路径有一种办法,就是多个相互强依赖的应用合并部署在一起,把远程过程调用(RPC)变成 JVM 内部之间的方法调用。
4. 依赖要尽量少
完成一次用户请求必须依赖的系统或者服务,这里的依赖指的是强依赖。
要减少依赖,比如 0 级系统、1 级系统、2 级系统、3 级系统,0 级系统如果是最重要的系统,那么 0 级系统强依赖的系统也同样是最重要的系统,
0 级系统要尽量减少对 1 级系统的强依赖,防止重要的系统被不重要的系统拖垮。例如支付系统是 0 级系统,而优惠券是 1 级系统的话,在极端情况下可以把优惠券给降级
5. 不要有单点
避免将服务的状态和机器绑定,即把服务无状态化,这样服务就可以在机器中随意移动。
把和机器相关的配置动态化,这些参数可以通过配置中心来动态推送,在服务启动时动态拉取下来,我们在这些配置中心设置一些规则来方便地改变这些映射关系。
储服务本身很难无状态化,一般要通过冗余多个备份的方式来解决单点问题
架构是一种平衡的艺术,而最好的架构一旦脱离了它所适应的场景,一切都将是空谈。
1W/s 架构的秒杀系统
- 只需要把你的商品购买页面增加一个“定时上架”功能,仅在秒杀开始时才让用户看到购买按钮,当商品的库存卖完了也就结束了
10W/s 架构的秒杀系统
- 把秒杀系统独立出来单独打造一个系统,这样可以有针对性地做优化,例如这个独立出来的系统就减少了店铺装修的功能,减少了页面的复杂度;
- 在系统部署上也独立做一个机器集群,这样秒杀的大流量就不会影响到正常的商品购买集群的机器负载;
- 将热点数据(如库存数据)单独放到一个缓存系统中,以提高“读性能”;
- 增加秒杀答题,防止有秒杀器抢单。
- 秒杀详情成为了一个独立的新系统,另外核心的一些数据放到了缓存中,其他的关联系统也都以独立集群的方式进行部署。
100W/s 架构的秒杀系统
- 对页面进行彻底的动静分离,使得用户秒杀时不需要刷新整个页面,而只需要点击抢宝按钮,借此把页面刷新的数据降到最少
- 在服务端对秒杀商品进行本地缓存,不需要再调用依赖系统的后台服务获取数据,甚至不需要去公共的缓存集群中查询数据,这样不仅可以减少系统调用,而且能够避免压垮公共缓存集群
- 增加系统限流保护,防止最坏情况发生
- 秒杀过程中不需要刷新整个页面,而只需要向服务端请求很少的动态数据
- 最关键的详情和交易系统都增加了本地缓存,来提前缓存秒杀商品的信息,热点数据库也做了独立部署
从前面的几次升级来看,其实越到后面需要定制的地方越多,也就是越“不通用”。
例如,把秒杀商品缓存在每台机器的内存中,这种方式显然不适合太多的商品同时进行秒杀的情况,因为单机的内存始终有限。所以要取得极致的性能,就要在其他地方(比如,通用性、易用性、成本等方面)有所牺牲。