秒杀系统

Gitee地址:https://gitee.com/yuyuuyuy/micro-mall

文章目录

  • 秒杀系统
  • 前言
  • 一、秒杀系统问题分析及解决方案探讨
  • 二、效果展示
  • 三、代码实现
    • gateway网关
    • sentinel
      • 定义资源的方式
      • 定义控制策略
      • 定义异常处理策略
    • skywalking链路追踪
    • Reddssion分布式锁
    • RabbitMQ
    • Jmeter
  • 总结

前言

秒杀是电商项目中的常见场景,如XX手机12点限量半价抢购等。该场景在极短的时间内涌入大量的请求,来同时访问有限的服务资源,从而造成系统负载压力大,甚至导致系统服务瘫痪以及宕机的可能。本文会介绍秒杀系统中存在的痛点以及针对这些点的优化思路。使用到的技术有:redis,redisson,gateway,nacos,rabbitmq,sentinel,jmeter,skywalking


一、秒杀系统问题分析及解决方案探讨

1.短时间内高并发下,会产生商品超卖问题。比如A商品200个库存,同一时间3个用户对数据库发起请求,发现有200个库存,然后大家都对库存减1,为199,实际库存应该为200-3=197.解决这个问题的方案之一是给mysql加锁,但是给mysql加锁会产生锁竞争问题,一个线程只有等另一个线程执行完操作后才能访问数据库,从而导致用户等待时间延长,在高并发场景下该问题尤为严重。为解决该问题,提前将库存信息存入redis中,并加上redisson分布式锁,利用semaphore信号量来表示库存的数量。首先要让用户从redis中抢商品库存,只有抢到库存的用户才有资格下订单。还可以使用redis来保证接口幂等性,在redis中保存一个用户id和商品的映射,参与过秒杀的用户就不能再次秒杀。

2.此时系统负载压力依然很大。我们就要使用RabbitMQ来实现队列泄洪,确保数据库来的及处理消息。

3.通过网关gateway来拦截不必要的请求,并负载均衡路由到不同的服务器,分担每一个服务器的压力。

4.使用sentinel来进行限流,比如限流到8000qps。为保险起见,我们还要给系统加熔断处理,比如当消息队列的响应速度超过一定时间时,就直接熔断,给前端返回活动太火爆,请稍后再试,以免出现服务雪崩,造成严重后果。

5.每秒的流量依然巨大,为了确定限流熔断的参数设置,我们可以事先用jmeter进行压力测试,并通过skywalking链路追踪技术来分析性能瓶颈在哪里,然后做出进一步的优化。

流程图如下:

架构图如下:

二、效果展示

效果如下(示例):
可以看到,该秒杀系统可单机承受每秒5000次的请求,并且平均时延只有588ms
https://www.bilibili.com/video/BV1Q44y1G7Cz/

秒杀系统


三、代码实现

gateway网关

gateway基本上不用写什么代码,只用配置一下就能实现各种功能。
以下是使用gateway实现负载均衡的核心配置
其中id就是服务名称,uri: lb://order/表示使用负载均衡策略进行路由匹配, predicates:就是断言,满足这断言的就会路由到负载均很的地址

 routes:- id: orderuri: lb://order/predicates:- Path=/order/**

sentinel

sentinel可对服务进行限流和熔断,支持对多种粒度的控制。核心就是定义资源,和对该资源的控制策略。

定义资源的方式

1.抛出异常的方式定义资源

public static void main(String[] args) {initFlowRules();while (true) {Entry entry = null;try {entry = SphU.entry("HelloWorld");/*您的业务逻辑 - 开始*/System.out.println("hello world");/*您的业务逻辑 - 结束*/} catch (BlockException e1) {/*流控逻辑处理 - 开始*/System.out.println("block!");/*流控逻辑处理 - 结束*/} finally {if (entry != null) {entry.exit();}}}
}

这种定义资源的方式对代码侵入性高,但是控制粒度更细
2.使用注解的方式定义资源,Sentinel 支持通过 @SentinelResource 注解定义资源并配置 blockHandler 和 fallback 函数来进行限流之后的处理。

// 原本的业务方法.
@SentinelResource(blockHandler = "blockHandlerForGetUser")
public User getUserById(String id) {throw new RuntimeException("getUserById command failed");
}// blockHandler 函数,原方法调用被限流/降级/系统保护的时候调用
public User blockHandlerForGetUser(String id, BlockException ex) {return new User("admin");
}

对代码侵入性更低
3.sentinel控制台自动检测资源,对代码无侵入性

定义控制策略

1.使用sentinel控制台来定义控制规则,对代码无侵入性

2.使用代码来定义控制规则,本秒杀系统使用的熔断规则代码如下:

    //自定义熔断规则@PostConstructprivate static void initDegradeRules() {List<DegradeRule> rules = new ArrayList<>();DegradeRule rule = new DegradeRule();rule.setResource("createOrder");//设置熔断策略为慢调用比例模式rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);// 设置慢调用临界阈值,单位是ms,响应时间超过1s就视为慢调用rule.setCount(1000);//定义熔断时长5srule.setTimeWindow(5);//设置慢调用比例阈值rule.setSlowRatioThreshold(0.1);//熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断rule.setMinRequestAmount(5);//设置统计时长,1srule.setStatIntervalMs(1000);rules.add(rule);DegradeRuleManager.loadRules(rules);}

定义异常处理策略

比如限流以后直接返回给前端服务器限流,请稍后再试,参考代码如下:

@Component
public class SentinelBlockExceptionHandler implements BlockExceptionHandler {@Overridepublic void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {Map<String, Object> errors = new HashMap<>();if (e instanceof FlowException) {errors.put("code","403");errors.put("message", "服务限流");}errors.put("path", httpServletRequest.getRequestURI());httpServletResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);httpServletResponse.setCharacterEncoding("UTF-8");httpServletResponse.setHeader("Content-Type", MimeTypeUtils.APPLICATION_JSON_VALUE);new ObjectMapper().writeValue(httpServletResponse.getWriter(), errors);}
}

skywalking链路追踪

核心就是定义探针,开启服务器,以及配置信息存储在哪里
在idea中使用skywalking,只需要在启动参数中做如下配置即可:
1.配置skywalking-agent.jar的位置
-javaagent:D:\SkyWalking\skywalking-agent/skywalking-agent.jar
2.定义服务的名称,和数据的收集地址
-Dskywalking.agent.service_name=XXX -Dskywalking.collector.backend_service=127.0.0.1:11800
然后就可以在控制台中看到微服务链路追踪及各种每个环节的数据分析了。

Reddssion分布式锁

//使用redisson的Semaphore来实现抢商品功能RSemaphore storage = redissonClient.getSemaphore("storage");//使用非阻塞方式来抢redis中的semaphore信号量,每次抢1件商品boolean success = storage.tryAcquire(1, 100, TimeUnit.MILLISECONDS);if(success){//秒杀成功,进入下一个环节,创建订单}else{//秒杀失败,直接返回}

RabbitMQ

请参考我的其他文章

Jmeter

压力测试工具
自定义线程数,在多少秒内完成,持续多少秒
下图所示就是每秒5000QPS,持续3秒

可从聚合报告中看到平均的响应时间,吞吐量等数据,以便分析系统的性能

总结

以上就是秒杀系统的实现方案。要综合使用多种技术,包括网关来实现负载均衡,消息队列削峰泄洪,服务限流与熔断,分布式锁保证不出现超卖问题,压力测试工具整合链路追踪技术分析系统的性能瓶颈。要做好秒杀系统,其实还有很长的路要走,只有不断积累和精进各种技术,才能实现系统的高可用,高并发,高性能。

秒杀系统设计思路与实现相关推荐

  1. 秒杀系统设计思路与实战(含源码实现)

    一.限流与降级 客户端限流 按钮置灰 js控制每秒只能发送一个请求 站点层限流 1. Nginx限流 Nginx官方版本限制IP的连接和并发分别有两个模块: limit_req_zone: 用来限制单 ...

  2. 转载和积累系列 - 秒杀系统设计思路

    目录 前言 一:秒杀应该考虑哪些问题 1.1:超卖问题 1.2:高并发 1.3:接口防刷 1.4:秒杀url 1.5:数据库设计 1.6:大量请求问题 二:秒杀系统的设计和技术方案 2.1:秒杀系统数 ...

  3. 电商秒杀系统设计思路和实现方法

    1 秒杀业务分析 正常电子商务流程 (1)查询商品:(2)创建订单:(3)扣减库存:(4)更新订单:(5)付款:(6)卖家发货 秒杀业务的特性 (1)低廉价格:(2)大幅推广:(3)瞬时售空:(4)一 ...

  4. java信用分秒杀系统设计思路,秒杀系统设计思路

    秒杀特性: 1. 商品个数有限 2. 时间分布集中 3. 流量超级大 整体方案: 1. 产品策略 a. 分离核心流程与其他可以延后处理的流程 b. 针对异常情况进行文案引导 2. 技术策略 a. 客户 ...

  5. 淘宝秒杀系统设计的几个注意点

    转载自  淘宝秒杀系统设计的几个注意点 还记得2013年的小米秒杀吗?三款小米手机各11万台开卖,走的都是大秒系统,3分钟后成为双十一第一家也是最快破亿的旗舰店.经过日志统计,前端系统双11峰值有效请 ...

  6. 秒杀系统设计中的业务性思考

    秒杀不是一个新鲜事物,特别是过去几年电商和互金业务的蓬勃发展,各种电商节的兴起,促使秒杀已经变成了非常重要的业务功能.我这几年也没少和"秒杀"打交道,和团队共同经历了各种挣扎后,积 ...

  7. 架构师之路(18)讲解秒杀系统设计

    1 秒杀场景 秒杀场景 登陆12306进行火车票抢座 1599元购入飞天茅台 周董演唱会的门票 双十一秒杀活动 秒杀场景关注点 严格防止超卖:库存1000件卖了1020件,要杀个码农祭天了!防止超卖是 ...

  8. 你了解淘宝大秒杀系统设计详解吗?

    1. 一些数据 2. 热点隔离 3. 动静分离 4. 基于时间分片削峰 5. 数据分层校验 6. 实时热点发现 7. 关键技术优化点 7.1 Java处理大并发动态请求优化 7.2 同一商品大并发读问 ...

  9. 淘宝大秒杀系统设计详解

    摘要:最初的秒杀系统的原型是淘宝详情上的定时上架功能,由于有些卖家为了吸引眼球,把价格压得很低.但这给的详情系统带来了很大压力,为了将这种突发流量隔离,才设计了秒杀系统,文章主要介绍大秒系统以及这种典 ...

  10. Java程序员,你了解淘宝大秒杀系统设计详解吗?

    1. 一些数据 大家还记得2013年的小米秒杀吗?三款小米手机各11万台开卖,走的都是大秒系统,3分钟后成为双十一第一家也是最快破亿的旗舰店.经过日志统计,前端系统双11峰值有效请求约60w以上的QP ...

最新文章

  1. cin lt lt c语言,编写程序:从键盘输入n(0lt;nlt;100)个整数,计算并输出其中出现次数最多且数值最大的元...
  2. 大数据 机器学习 算法概论
  3. sql脚本对比工具_Java开发中用到的数据库迁移工具(flyway)
  4. springcloud注册中心eureka
  5. 面向小姐姐的编程——JAVA面向对象之封装(二)
  6. Java之消息摘要(MD5)
  7. Matlab 小波变换dwt和wavedec
  8. Javascript你必须要知道的面试题
  9. Java 经纬度计算两个点的之间的距离工具类
  10. scala中的match详解
  11. 原装安装版WIN10安装详细教程
  12. 计算机网络安全专家高薪,纽约理工大学温哥华校区NYIT计算机网硕士
  13. mysql varchar 单引号_char、varchar数据类型值在使用时可以要用单引号或双引号括起来。...
  14. Giscus,由 GitHub Discussions驱动的评论系统
  15. QK对中断的特殊处理
  16. 在android上启动分屏的方法
  17. 自制图标字体FontAwesome
  18. 活着就是为了改变世界,人工智能缓解气候异常的4种方式
  19. MTK 写入SN设置读不到SN问题
  20. Authing 获得 ISO/IEC 20000-1 服务管理体系和信息安全管理体系认证

热门文章

  1. Cholesky 分解,QR分解
  2. VS2013 community 官方版下载
  3. 张钹院士:迈向第三代人工智能 |论文学习总结
  4. 开源在线客服系统源码h5|thinkphp在线客服完整源码|网页在线客服源码
  5. 使用 Spring Data JPA 简化 JPA 开发
  6. 无线网检查服务器在那,无线网络服务器地址在哪里找
  7. 关于PScc2018,2019不能开启液化人脸识别的问题
  8. 2019数据安装勾选_建筑CAD首选软件~【T20 天正建筑 V5.0 安装教程】
  9. 冲突域和广播域的隔离与扩展
  10. Thinkphp仿众图网图片素材下载站源码+自适应手机端