构建SpringBoot,SpringCloud秒杀系统微服务项目

设计原因:

为什么要针对秒杀设计一个完善的方案?因为系统可能会因为1%的秒杀业务影响其余99%正常业务的运行,所以需要将秒杀系统独立出来。

待解决问题:

主要解决两个问题:并发读、并发写。

整体架构要求:

概括为:"稳、准、快",即对应"高可用、一致性、高性能",其介绍分别如下:

高可用:保证系统的高可用和正确性,设计PlanB进行兜底。

一致性:保证秒杀减库存中的数据一致性。

高性能:涉及大量并发读写,所以需要支持高并发,从动静分离、热点发现与隔离、请求削峰与分层过滤、服务端极致优化来介绍。

五个架构原则(4要1不要):

数据尽量少:包含请求和响应的数据,因为网络传输需要时间。可简化秒杀页面、减少数据库打交道。

请求数尽量少:浏览器渲染页面包含额外请求,比如以来了css、js、图片等定义为额外请求,这些请求尽可能少,若请求域名不一致,还涉及DNS解析,耗时更久,可采用合并方法如:http://xxx.com/tm/modes??module-preview/index.xtpl.js,module-jhs/index.xtpl.js ,这个在服务器依旧是单独存放,只是提供了一个组件解析这个url。比如以下是淘宝的一个静态资源链接:

路径尽量短:这里的路径表示节点。每个节点都会产生新的socket连接,一个节点的可用性是99.9%,经过五个节点后就是五次方为99.5%。方法可以是服务内部RPC调用变为jvm内部调用。

依赖尽量少:将服务分级,比如将支付服务作为0级,优惠券是1级,要避免0级系统被1级系统拖垮。

不要有单点:单点意味着没有备份。将服务无状态化,即避免服务与机器绑定。可设置配置中心映射。

注:数据、请求数、路径、依赖、单点。但是其实这些原则会产生冲突,如请求数量少中的合并请求会使单次请求的数据量变大,这与数据尽量少违背。所以需要我们做一个平衡。

秒杀系统的大体涉及结构:

1 页面彻底动静分离,使得用户秒杀时不需要刷新整个页面,降低刷新请求数。

2 服务器缓存秒杀商品,直接调用缓存层,无需穿透到数据库层找数据。

3 增加流量限流保护,防止最g坏情况。

如何动静分离:

把用户请求数据(如HTML)分为"动态数据"和"静态数据"。

动态数据与静态数据区别:确定输出的数据是否含访问者个性化数据如 个人信息、cookie等私密数据。

区别动静数据的作用:区分了动静数据,就可以将静态数据缓存,提高效率。

如何对静态数据做缓存:

1. 将静态数据放在离用户最近的地方,如CDN、用户浏览器、服务端的Cache。

2. 做静态化改造,直接缓存HTTP连接。Web服务器根据请求URL直接取出HTTP响应头、响应体直接返回。

3. 选择谁来缓存静态数据,如可在web服务器层做缓存,屏蔽java层的弱点,不在java层做缓存。

如何做动静分离改造:

1. URL唯一化。如每个商品链接为:http://item.xxx/xxxx?id=xxx 来作为缓存的key,用于缓存整个HTTP连接。

2. 分离请求,含用户信息相关、时间、地狱相关,这些都可以通过异步请求独立获取。

3. 服务器返回的信息可去掉cookie。如Vanish可用unset req.http.cookie去掉cookie。

动态内容处理方案:

ESI:web代理服务器做动态请求时,将动态内容插入静态页面,然后全部返回。

CSI:异步js请求,性能最佳,但是有一定时延,可能对用户体验不好。

动静分离的几种架构方案:

1. 实体机单机部署:将虚拟机运行的Java应用换成实体机

优点:无网络瓶颈、可使用大内存。

提升命中率,减少Gzip压缩。

减少cache失效压力,因为采用定时失效,如3分钟失效。

2 统一Cache层:即抽离cache出来作为一个独立的集群。可设置二级Cache,放置回原(原服务器)

3. 上CDN:可增加二级Cache防止回原(原服务器)。

二八原则(针对性处理热点数据):

为什么要针对性处理:热点数据会大量占用服务资源,0.1%业务会抢占系统90%以上的资源。

什么是热点:

热点分为热点操作和热点数据,其中热点操作是一种优化的方式,将会在秒杀的操作优化讲解。

热点数据分为动态、静态热点数据如下:

-静态热点数据即可提前预测数据如数据分析出哪种更热门、一个商品做活动等。

-动态热点数据不可预测,如抖音广告然后突然火了。

如何发现热点数据:

发现静态热点数据:强制让卖家通过报名方式提前把热点数据筛选出来缓存,但是增加了卖家的工作量,也不够实时。也可以根据每日访问数进行统计,然后缓存TOP N的商品。

发现动态热点数据:抽离出一个中间件用于收集搜索、商品详情、购物车等关键热点业务的点击数据,然后异步记录到日志,然后根据规则判断是否热点数据后缓存在队列中(因为热点数据一般是临时的,所以可采用LRU算法淘汰)。

流量削峰怎么做:

为什么要削峰:稳定服务端,节省资源,本质是延缓用户请求发出,减少和过滤无用请求(遵循请求书尽量少原则)。

削峰思路:排队、答题、分层过滤

排队:消息队列缓存大量并发,把原来的一步操作变成两步。虽然违背了增加访问路径原则,但是防止了系统崩溃。

答题:可防止爬虫等的自动抢购的脚本。延缓请求从之前的1s内延缓到2-10s,对事件进行了分片,减缓服务器压力,如微信的摇一摇、支付宝休一休。也可限制答题时间间隔。

分层过滤:分层为:CDN->前台读系统(商品详情系统)->后台写系统(交易系统)->DB

大部分数据和流量都在CDN获取,拦截了大部分读的数据。

经过第二层(前台读系统)尽量走Cache。

到第三层(后台写系统),做数据校验、限流,进一步减少数据量和请求。

最后在数据层完成强一致性校验。

分层过滤核心思想:各层过滤无效请求,所以必须对数据做分层校验,其校验原则如下:

将动态请求的读数据缓存在浏览器本地,过滤无效数据读。

对读数据不做强一致性校验,较少一致性校验带来的性能问题。

对写数据基于时间的合理分片,过滤过期失效请求。

对写数据做强一致性校验,只保留有效数据。

影响性能的因素及其可优化处:

影响服务端性能的因素:QPS、响应时间(RT)

计算公式:QPS = (1000ms / 响应时间) * 线程数量,真正影响性能的是CPU执行时间。

再来分析下线程数是否对QPS的影响:不是线程数越多,QPS越高,因为线程上下文切换有消耗。所以需要合理的设置线程数,一般的计算公式为:线程数 = [(线程等待时间 + 线程CPU时间) / 线程CPU时间] * CPU数量,当然最好的方式是性能测试来确认。

如何发现瓶颈:就缓存系统而言,制约的是内存。存储系统的瓶颈是I/O。

秒杀系统的大部分瓶颈在CPU(使用JProfiler、YourKit),但不一定是CPU,有可能是其他部分,比如QPS达到极限时,CPU使用率是否超过95%,如果不是则可能是锁限制或过多本地I/O等待发生。

如何优化系统:

减少编码:java编码速度慢,涉及字符串操作(输入输出操作、I/O操作)比较消耗CPU资源。原因是磁盘、网络IO都需要将字符串转为字节,这个转换必须查表编码。可通过(OutputStream()直接进行流输出),可提高30%.

减少序列化:序列化与编码同时发生,所以需要减少。尽量减少RPC,将关联性强的应用服务合并。

Java极致优化:对大流量Web系统做静态化改造;直接使用Servlet,绕过框架多余处理逻辑;直接输出流数据。

并发读优化:秒杀系统单机缓存。不要求读一致性,但是写数据的时候要求强一致性。

秒杀系统设计的核心逻辑:

秒杀系统最重要要求是 "不要超卖",关键在于减库存。

减库存方式(三种):

下单减库存:一定不会出现超卖情况,但是有些人下单完不付款会影响其他人。

付款减库款:付款减库存,可能会因为并发高导致付款时已经卖光,付不了款。

预扣库存:最常用,如下单后扣库存,保留十分钟,在十分钟内未付款就不保留。如果付款时发现库存不足则不允许付款。

减库存存在的问题:在下单减库存、预扣库存的情况下,有竞争对手恶意多账号下单导致库存降为0,那商品就无法正常卖。

解决办法:指定反作弊措施,如给经常下单不买的用户打标识、设置最大购买书、设置重复下单不付款操作数。

秒杀减库存极致优化:

秒杀商品减库存放缓存如redis。给热点商品提供独立的缓存层、DB层集群。使用排队如应用层排队、数据库层排队(阿里针对mysql的innodb做了补丁程序patch可对单行记录做并发排队)解决数据库并发锁问题。

设计Plan B兜底方案:

再牛逼的系统也会问题,比如超大流量导致宕机,出现最坏情况,所以需要设计Plan对应高可用性。

各阶段处理操作:

架构阶段:考虑拓展性和容错性,避免系统出现单点问题。

编码阶段:保证代码健壮性,合理设置超时退出机制,对于异常捕获后需要一个默认处理。

测试阶段:保证最坏情况下,也有相应处理流程。

发布阶段:需要有备份用于回滚。

运行阶段:系统监控和报警,如cat监控系统。

故障发生:及时止损,如下架标错价商品。

运行阶段详细处理:

降级:限制或关闭某些非核心功能,留给核心功能。如展示成功记录由30条变成5条。

限流:设置一个QPS阈值,达到则排队或丢弃。

拒绝:当连接数过大,cpu负载达到90%,就拒绝请求。

读自:许令波-《如何设计一个秒杀系统》

原文地址:https://www.cnblogs.com/java188/p/12123721.html

时间: 2024-11-14 12:40:00

构建SpringBoot,SpringCloud秒杀系统微服务项目的相关文章

JAVA架构师之SpringBoot,SpringCloud构建微服务项目架构

springcloud微服务项目架构搭建第一天(一).项目简介1.准备工作:idea创建springboot模板 2.后台应该涉及的技术(后期可能会有删改) Spring Framework 容器SpringMVC MVC框架Apache Shiro 安全框架Spring session 分布式Session管理MyBatis ORM框架MyBatis Generator 代码生成PageHelper MyBatis物理分页插件Druid 数据库连接池FluentValidator 校验框架Th

【SpringCloud】(1)---基于RestTemplate微服务项目案例

基于RestTemplate微服务项目 在写SpringCloud搭建微服务之前,我想先搭建一个不通过springcloud只通过SpringBoot和Mybatis进行模块之间额通讯.然后在此基础上再添加SpringCloud框架. 下面先对案例做个说明 该项目有一个maven父模块,其中里面有三个子模块:  serverspringcloud:整体父工程.    serverspringcloud-api:公共子模块,放公共实体对象.  serverspringcloud-provider-

.Net Core 商城微服务项目系列(一):使用IdentityServer4构建基础登录验证

这里第一次搭建,所以IdentityServer端比较简单,后期再进行完善. 1.新建API项目MI.Service.Identity,NuGet引用IdentityServer4,添加类InMemoryConfiguration用于配置api和客户端资源: public class InMemoryConfiguration { public static IConfiguration Configuration { get; set; } /// <summary> /// Define

使用http://start.spring.io/构建maven微服务项目的几个坑及eclipse构建spring boot微服务项目

一,使用http://start.spring.io/构建maven微服务项目 本来嘛,直接构建的项目导入时没有任何问题的导入就可以运行,可是最近构建好项目,然后导入,种种报错 1.导入之后POM报错 将parent版本更改下,将2.1.6改为2.0.1就可以消除错误 2.启动报错,直接退出 pom中导入此依赖,问题就解决了 <dependency> <groupId>org.springframework.boot</groupId> <artifactId&g

系统微服务架构

v\:* {behavior:url(#default#VML);} o\:* {behavior:url(#default#VML);} w\:* {behavior:url(#default#VML);} .shape {behavior:url(#default#VML);} table.MsoNormalTable {mso-style-name:普通表格; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-n

基于Kafka构建事件溯源模式的微服务

概要 本文中我们将讨论如何借助Kafka实现分布式消息管理,使用事件溯源(Event Sourcing)模式实现原子化数据处理,使用CQRS模式(Command-Query Responsibility Segregation )实现查询职责分离,使用消费者群组解决单点故障问题,理解分布式协调框架Zookeeper的运行机制.整个应用的代码实现使用Go语言描述. 第一部分 引子.环境准备.整体设计及实现第二部分 消息消费者及其集群化第三部分 测试驱动开发.Docker部署和持续集成第一部分 引子

微服务项目战略战术

微服务项目战略战术 数据模型服务化:数据模型主要指数据库设计,数据库的设计很大程度的决定了模块划分.让不同的表责任到服务,一张表不能有两个大服务来控制.这样,第一便于容量扩展,量上来了直接水平拆分.第二,数据便于量化,有明确的责任人.第三,便于应对变化,模型独立,变化影响范围可控. 也就是是金融的战略:去除依赖.弱化依赖.控制依赖. 每个服务拆分子模块:标准的模块分成:共同依赖模块.核心服务模块.后台接口模块.监控报警等定时任务模块.服务分等级,确保有侧重. 这里需要着重说明的是:服务分等级,S

.Net Core 商城微服务项目系列(四):ELK

毫无疑问,项目里日志是必不可少的,在众多日志框架里ELK可以说是最好的选择之一,对于微服务项目来说也是一样. 之前写过关于ELK搭建的文章,所以这篇也就不再介绍了,本篇将会使用NLog搭配ElasticSearch和Kibana构建日志框架,本来是有Logstash的,但是接入Logstash后日志总是发送不成功,所以本篇将暂时不使用Logstash,等后面找到具体什么问题后再进行修改,最终整体的日志架构会是NLog+ELK+Kafka. 运行ELK有两种方式,一种是分别单独运行ElasticS

大型电商微服务项目视频教程

大型电商微服务项目视频教程课程分享链接:https://pan.baidu.com/s/1Pl2kMqT6KCMvohaABE0m0w 提取码:9lkn 本课程将手把手带大家从无到有实现一个真实的大型电商微服务项目,该项目是基于真实的知名互联网企业项目讲解的 本课程将讲解如何从无到有搭建一个真实的大型电商微服务项目,涉及的内容较多,录制所需的时间也会比较久,因此整部课程下来售价也比较高,但考虑到课程中讲解的某阶段的知识点,有部分学员可能已经掌握了解,并不需要再次学习该部分内容,因此本套系列课程将