写点什么

作业十

作者:Geek_f3e842
  • 2022 年 5 月 15 日
  • 本文字数:2267 字

    阅读完需:约 7 分钟

1. 背景概述

1.1 业务背景

设计 6.18 大促秒杀系统的设计,业务模式如下:

1. 挑选各大电商平台上畅销和好评的商品进行销售,每个品类不超过 20 个商品,目前做了 10 个品类;

2. 本次 6.18 秒杀选择了 1000 个充电宝,10 台 iPhone 12 作为秒杀商品;

3. 正常的日活大约 100 万用户;

4. 老板要求万无一失。

1.2 技术背景

1. 技术团队以 Java 为主,已经落地了微服务架构;

2. 主要渠道是自有的 App(包括 iOS 和 Android)和微信小程序,为了促进用户转化为 App 用户,只有下载 App 才能参加秒杀活动;

3. 目前只有单机房。

2. 业务场景分析

2.1 业务基本场景

1、下订单,用户购买商品,系统生成订单,这个场景并发比较大

2、扣库存,扣减库存,直到扣减为 0 后,不能再下单,这个场景并发比较大。

3、支付订单,用户成功下单后,支付订单,这个场景可以异步执行,并发要求没有下订单场景那么大。

登录、生成物流信息等场景可以在秒杀场景之外完成,这里不做过多描述。

2.2 业务特点

1、瞬时并发量大,秒杀时会有大量用户在同一时间进行抢购,瞬时并发访问量突增。

2、库存量少 ,秒杀活动商品库存量都很少,只有极少量用户能成功购买到商品。

3、业务简单,流程比较简单,业务场景比较少,一般都是下订单、扣库存、支付订单。

3. 架构设计

3.1 存储架构

3.1.1 存储性能估算

1、下订单

本次 6.18 秒杀选择了 1000 个充电宝,10 台 iPhone 12 作为秒杀商品,故订单数量最多 1010 条,考虑到一定的冗余为 2000 条。

以后扩展到 10 个品类,每个品类 20 个商品后,订单数量应该也在 10 万量级上下。

2、扣库存

库存记录的数量与商品的个数相关,本次为 2 条,以后扩展为 200 条左右。

3、支付订单

支付信息,与订单信息的数量相似,本次为 2000 条,以后扩展为 10 万量级上下。

3.1.2 存储架构设计

订单、库存、支付信息都是关系型数据,所以存储使用 MySQL 数据库。为了保障数据的高可用,采用一主两备的方式存储,共保存 3 份数据。

10 万订单数据、10 万支付信息、200 条库存信息保存在 MySQL 主库中。

秒杀活动主要为写入操作,不做读写分离。

3.2 计算架构

3.2.1 计算性能估算

1、下订单

正常的日活大约 100 万用户,假设秒杀的时候,参与用户为日活用户的 3 倍,为 300 万,这些用户提前 5 分钟查看秒杀商品,故商品查看的 QPS 为:300 万/(5*60)=1 万/s,考虑到系统要预留一定的性能空间,查看商品的 QPS 设计为 2 万/s 。

假设所有秒杀活动商品可以在 10 秒内售罄,那么生成订单的 TPS 为:10 万/10s=1 万/s,考虑到系统要预留一定的性能空间,生成订单的 TPS 设计为 2 万/s。

2、扣库存

生成订单的时候,同时要修改库存,故修改库存的 TPS 与生成订单相同,设计为 2 万/s。

3、支付订单

只有成功下单的用户才会支付,所以支付的性能要求低于生成订单,假设为生成订单的一半,故支付订单的 TPS 为 1 万/s。

3.2.2 计算架构设计--负载均衡

采用 LVS、Nginx、服务网关三层负载均衡设计。

支撑 TPS+QPS 约 7 万。

3.2.3 计算架构设计--缓存

采用三级缓存架构

1、APP 端设置 APP 缓存

2、Nginx 上设置 Web 缓存

3、使用分布式缓存实现商品、订单、库存数据的高速读取与写入。

如果用户量、并发量增长较快,可以考虑增加 CDN 缓存,将商品信息中的静态内容缓存在 CDN 中,以便进一步降低服务器压力。

3.3 服务拆分说明

拆分为 5 个服务:

1、秒杀服务

缓存预热,在秒杀开始前,将商品信息和数量加载到 Redis 集群中。

秒杀请求响应,处理 APP 发起的秒杀请求,检查 Redis 集群中该商品的排队数量是否超过商品的总数量,如果超过,则返回商品已抢完,否则将对应商品的请求写入 Redis 集群的排队信息中,并发送订单创建请求报文到消息中间件中。

2、订单服务

接收订单创建请求报文,创建订单,保存在数据库中,并异步调用库存服务,扣减库存。

3、库存服务

修改对应商品的库存数量。

4、支付请求接收服务

接收 APP 发起的支付请求,并将支付请求报文发送到消息中间件中。

5、支付服务

接收支付请求报文,执行扣款操作,并将支付信息保存在数据库中。

3.4 总体架构设计

1、采用三层负载均衡设计,见负载均衡设计说明。

2、Redis 采用集群部署,以便获得更高的写入和读取性能。

3、采用消息中间件降低流量峰值。

4、支付服务、订单服务和库存服务分别处理支付信息、订单信息和商品库存,存放在不同的数据库中。为进一步提高处理效率,支付信息和订单信息可采用分库分表设计。

3.5 其他架构设计

3.5.1 高可用架构设计

1、限流

1)请求端限流

限制请求次数,通过在 APP 嵌入业务逻辑,限制大部分用户流量,只准许少量用户流量进入后端服务器。

2)接入端限流

限制同一用户请求频率;随机抛弃无状态请求(抛弃浏览请求,响应下单请求)

3)微服务限流

使用写缓冲的方式,先将请求写入缓冲区,然后再进行处理。如果缓冲区慢,那么可以丢弃无法处理的请求。

2、排队

将生成订单、修改库存、支付等涉及数据库的请求放入消息队列,将同步请求,改为异步处理。

3、MySQL

MySQL 采用一主两备方式,主库与备库之间采用半同步复制,并部署 MHA 作为主备切换工具。当主库出现异常,可以自动从主库切换到备库。

4、Redis 集群

3 主 3 从,共 6 个节点。

3.5.2 可扩展架构设计

拆分为 5 个服务,每个服务都可以单独优化与演进。

4. 总结

1、将商品信息保存在 Redis 缓存中,通过 Redis 缓存中的排队数量判断商品是否还有库存,提高系统对客户端请求的响应能力。

2、通过消息中间件、排队等方式,将同步请求转换为异步处理,降低瞬间流量对服务端造成的冲击。

3、本设计主要为秒杀系统的重点环节设计,风险控制:放盗链、判断是否为真实用户、控制同一用户下单数量等功能,本次设计中未包含。

用户头像

Geek_f3e842

关注

还未添加个人签名 2021.01.23 加入

还未添加个人简介

评论

发布
暂无评论
作业十_架构实战营_Geek_f3e842_InfoQ写作社区