极客时间-如何设计一个秒杀系统-笔记0到2章
极客时间-如何设计一个秒杀系统-笔记0到2章
0.开篇词-系统秒杀系统架构设计都有哪些关键点?
把整个系统进行动静分离改造。
秒杀主要解决两个问题,一个是并发读,一个是并发写。并发读的核心优化理念是尽量减少用户到服务端来“读”数据,或者让他们读更少的数据;并发写的处理原则也一样,它要求我们在数据库层面独立出来一个库,做特殊的处理。另外,我们还要针对秒杀系统做一些保护,针对饮料之外的情况设计兜底方案,以防止最坏的情况发生。
用户请求路径上从浏览器到服务端我们要遵循几个原则:保证用户请求的数据尽量少、请求数尽量少、路径尽量短、依赖尽量少、且不能有单点
秒杀的结构可以概括为"稳、准、快"
-
稳:高可用,系统稳定,秒杀的产品顺利的卖出。高可用
-
准:要求保证数据的一致性。一致性
-
快:系统性能要足够高,服务端和整个请求链路都要做性能优化。高性能
高性能 涉及大量并发读和并发写, 关键为支持高并发访问。
-
设计数据的动静分离防范
-
热点的发现与隔离
-
请求的消峰与隔离
-
服务端的极致优化
一致性 如何设计秒杀减库存方案。减库存分为拍下减库存,付款减库存以及预扣。
高可用 设计一个PlanB来兜底,用于最坏的情况
1.设计秒杀系统时应该注意的5个架构原则
秒杀-同一时刻有大量的请求争抢购买同一个商品并完成交易的过程,大量的并发读写。
秒杀系统-一个满足大并发,高性能和高可用的分布式系统。
架构原则:4要1不要
1.数据要尽量少
用户请求的数据能少就少,请求的数据包括上传给系统的数据和系统返回用户的数据(通常就是网页)。
原因:数据在网络上传输需要时间,其次不管是请求数据还是返回数据都需要服务器处理,而服务器在写网络的时候要经过压缩和字符编码,这些都非常消耗CPU,所以减少传输的数据量可以显著减少CPU的使用。
举例:简化秒杀页面的大小,去掉不必要的页面装修效果。
系统依赖的数据能少就少,包括系统完成某些业务逻辑需要读取和保存的数据,这些数据一般是和后天服务以及数据库打交道的。调用其他服务会设计数据的序列化和反序列化,对CPU而言会占用不少资源。同时,数据库本身也容易成为瓶颈,所以和数据库打交道越少越好,数据越简单越好,越小越好。
2.请求数要尽量少
用户请求的页面返回后,浏览器渲染这个页面还会包含其他的额外请求,比如这个页面以来的CSS/JS、图片以及Ajax,这些都被定义为额外请求。
原因:浏览器每发出一个请求多少都会有一点消耗,比如建连接要做三次握手,有时候有页面依赖或者连接数限制,一些请求还需要串行加载等等。另外,如果不同请求的域名不一样的话, 还涉及到DNS解析。
举例:合并CSS和JS文件,这样虽然在服务端仍然是单个文件各自存放,但是服务端会有一个组件解析这个url(按照逗号分离多个css和js文件),然后动态地把这些文件合并起来一起返回。
3.路径要尽量少
路径-用户发送请求到返回数据这个过程中,需求经过的中间的节点数。通常这些节点可以表示为一个系统或者一个socket连接,每经过一个节点,一般都会产生一个新的socket连接。然后,每增加一个新的连接都会带来不确定。
缩短请求路径还可以有效提升性能(减少中间节点可以减少数据的序列化与反序列化),减少延时时间(减少网络传输耗时)
举例:多个相互强依赖的应用合并部署到一起,吧远程调用过程RPC变成JVM内部之间的方法调用。
4.依赖要尽量少
依赖-完成依次用户请求必须以来的系统或者服务,这里指的是强依赖。
举例-展示秒杀页面,这个页面必须强依赖商品信息,用户信息,还有其他如优惠券,成交列表等这些对秒杀不是非要不可的信息,这些弱依赖在紧急情况下可以去除。
可以为系统进行分级,比如0级,1级。。。如果0级是最重要的系统,那么0级系统强依赖的系统也是最重要的。同时0级系统要尽量较少对1级系统的强依赖,防止重要的系统被不重要的系统拖垮。
5.不要有单点
单点-没有备份,风险不可控,重要原则-消除单点(单点故障就是一个设备/子系统出现故障后,整个系统宕机。)
如何避免:避免将服务的状态和及其绑定,即把服务无状态化,这样服务就可以在季启忠随意移动。
如何解耦:把和机器相关的配置动态化,这些参数可以通过配置中心进行动态推送,在服务启动时动态拉取下来,在配置中心里方便的改变映射关系。类似存储服务本身很难无状态华,因此数据要存储在硬盘上,本身要和及其绑定,这种场景一般通过冗余多个备份的方式来解决单点问题。
架构形式
-
把秒杀系统独立出来,进行针对性优化,例如独立的系统减少店铺装修的功能,减少了页面的复杂度。
-
在系统部署上独立做一个机器集群,秒杀的大流量就不会影响到正常商品购买集群的机器负载
-
将热点数据(库存数据)单独放到一个缓存系统中,以提高读数据
-
增加秒杀答题,防止有秒杀器抢单
-
对页面进行彻底的动静分离,使得用户秒杀时不需要刷新整个页面,只需要点击抢宝按键,借此把页面刷新的数据降到最少
-
在服务端对秒杀商品进行本地缓存,不需要再调用依赖系统的后台服务获取数据,甚至不需要去公共的缓存集群中查询数据,不仅可以减少系统调用,而且能够避免压垮公共缓存集群
-
增加系统限流保护,防止最坏情况发生
答疑:
- localcache一般使用内存实现,采用java集合类即可。
- 通过订阅的方式向本地cache中写数据。(不了解)
- 秒杀系统cache怎样及时刷新?一是定时更新取3秒,二是主动更新,当数据库数据发生变化后,主动通知redis进行更新。
- localcache中的数据为静态数据,不会更新,没有一致性问题。比如库存数量不放在localcache中,而是放在独立的缓存系统中,如redis。库存采用主动失效的方式来失效缓存。
- 时间如何同步?以服务端时间为准,依赖同步组件进行同步。
- CDN中的静态cache数据包括JS,CSS,图片及商品中的静态数据。
2.如何才能做好动静分离?有哪些方案可选?
怎样才能让系统快起来?1.提高单次请求效率。2.减少没必要的请求。
1.动静的概念
动静分离-把用户请求的数据(如HTML页面)划分为“动态数据”和“静态数据”。动态数据与静态数据的主要区别就是看页面中输出的数据是否和URL、浏览器、时间、地域相关,以及是否含有Cookie等私密数据。比如说:
1.媒体网站的新闻,无论是谁访问都是一样的,那就是典型的静态数据,但是是动态页面。
2.淘宝首页会根据访问者的特征推荐,就是动态数据。
所谓动态还是静态,并不是说数据本身是否动静,而是数据中是否含有和访问者相关的个性化数据。
2.如何对静态数据做缓存
1.将静态数据缓存到离用户最近的地方。可以缓存至用户浏览器,CDN或者服务端的cache中。
2.静态化改造就是要直接缓存HTTP连接。静态化改造是直接缓存HTTP链接,而不仅仅是数据。Web代理服务器根据url直接获取http响应头和响应提,然后直接返回。
3.为克服jaca系统本身的弱点,比如不擅长处理大量连接请求,每个链接消耗的内存较多,servlet容器解析http协议较慢,因此可以不再java层做缓存,而是直接在web服务器层上左。
3.如何做动静分离的改造
1.URL唯一华。商品详情系统天然的可以做到URL唯一化——用商品id作为缓存http连接的key。
2.分离浏览者相关的因素。包括是否已登录,以及登陆身份等,这些相关因素我们可以单独拆分出来,通过动态请求来获取。
3.分离时间因素。服务端输出的时间也通过动态请求获取。
4.异步化地域因素。详情页面上与地域因素相关的采用异步获取,也可以采用动态请求。
5.去掉cookie。用户端收到的页面仍然含有Cookie,但是缓存的静态数据中不含所有cookie。
静态数据通过cache,动态数据通过ESI(Edge Side Includes)/SSI,CSI(Client Side Includes)。
ESI:又叫SSI,web代理服务器做动态内容请求,并将请求插入到静态页面中,用户拿到页面时已经是一个完整页面,对服务端性能有影响,用户体验较好。
CSI:单独发起一个异步javascript,以向服务端获取动态内容。服务端性能更加,但用户端页面可能有延迟。
3.动静分离的架构方案(这一部分我看不懂)
1.实体机单机部署
将虚拟机改为实体机,以增大Cache的容量,并且采用一致性Hash分组的方式来提升命中率。