设计一个抽奖系统抽奖系统需求概述如果设计一个抽奖系统,如何设计一个高并发的秒杀系统?这类项目在网上其实很多,但是实

这类项目在网上其实很多,但是实际的工作流到底是什么呢?难不成只有简单的数据库操作和逻辑判断吗?实际的工作流都有哪些呢?站在整体上来看都需要哪些呢?下面就以一个项目来讲解下都有什么?

其实可以看到,该部分其实是DDD结构中的一个单独的领域,主要是用来走抽奖逻辑。那么实际上仅仅对于抽奖这件事来说,其实就是抽奖策略的设计。通过策略包装里面的doDraw方法选择合适的策略进行抽奖。那么核心流就是策略都有哪些?

实际上关于这方面的策略主要有总体策略和单项策略。

单项策略就是说加入某个奖品抽完了,我们不需要重新计算概率,如果刚好抽到了没有的奖品,那么就相当于没抽到

而总体概率加入说没有商品了,需要重新计算现有商品的概率。

这一步算的上是,抽出奖品后以什么样的规则进行发放了。

lottery-domain└──src└──main└──java└──cn.itedus.lottery.domain.award├──model├──repository│├──impl││└──AwardRepository│└──IAwardRepository└──service├──factory│├──DistributionGoodsFactory.java│└──GoodsConfig.java└──goods├──impl│├──CouponGoods.java│├──DescGoods.java│├──PhysicalGoods.java│└──RedeemCodeGoods.java├──DistributionBase.java└──IDistributionGoodsc.java关于award发奖领域中主要的核心实现在于service中的两块功能逻辑实现,分别是:goods商品处理、factory工厂

goods:包装适配各类奖品的发放逻辑,虽然我们目前的抽奖系统仅是给用户返回一个中奖描述,但在实际的业务场景中,是真实的调用优惠券、兑换码、物流发货等操作,而这些内容经过封装后就可以在自己的商品类下实现了。

factory:工厂模式通过调用方提供发奖类型,返回对应的发奖服务。通过这样由具体的子类决定返回结果,并做相应的业务处理。从而不至于让领域层包装太多的频繁变化的业务属性,因为如果你的核心功能域是在做业务逻辑封装,就会就会变得非常庞大且混乱。

实际上活动的创建在实际的工作流中必须涉及到这些步骤,那么基于这些步骤就可以设计具体的代码结构

lottery-domain└──src└──main└──java└──cn.itedus.lottery.domain.activity├──model├──repository│└──IActivityRepository└──service├──deploy├──partake[待开发]└──stateflow├──event│├──ArraignmentState.java│├──CloseState.java│├──DoingState.java│├──EditingState.java│├──OpenState.java│├──PassState.java│└──RefuseState.java├──impl│└──StateHandlerImpl.java├──AbstractState.java├──IStateHandler.java└──StateConfig.javaID生成与分库分表关于ID的生成因为有三种不同ID用于在不同的场景下;

所以针对订单号的这种情况,需要考虑分库分表的实现思路

这个图其实就简单的将主题的思路都囊括出来了,当有了各种活动以后,需要对当前用户能否参与活动进行检验,如状态、日期、库存、参与次数等。然后进入抽奖部分,按照不同的策略进行抽奖,最终做到落库,在这里后续的设计打算使用MQ进行解耦分离。

应用层编排的设计的具体思路其实还是需要知道一开始的活动才行的,但是假如说活动有很多,怎么知道要参加什么活动呢?

所以需要一种规则引擎

通过这种规则引擎的方式来选取不同的活动,然后在执行后续的逻辑。

使用消息队列必须要考虑的是发送成功或者失败,以后重复消费的问题。

首先需要开启幂等。然后发送端如果发送失败的话,更新表,这个表中存储的是发送成功或者失败的状态。如果发送失败的话,将来需要使用定时任务进行回调,而图中下半部分的MQ是否消费成功,则是手动开启了消费确认。

按照定时任务扫描,如果成功了就发送MQ,没有成功的话,就继续等待下一次定时任务扫描即可。

即使是使用Redis分布式锁,我们也不希望把锁的颗粒度放的太粗,否则还是会出现活动有库存但不能秒杀,提示“活动过于火爆”。那么我们就需要按照活动编号把库存锁的颗粒度缩小,实际操作也并不复杂,只是把活动ID+库存扣减后的值一起作为分布式锁的Key,这样就缩小了锁的颗粒度。

其中有一个比较关键的就是扣减库存后,在各个以下的流程节点中,如果有流程失败则进行缓存库存的恢复操作。

1、阿里云服务器三台4c8G100mbps带宽

2、一台中间件机器

3、一台监控机器prometheus、influxdb、grafana

4、一台应用机器jdk、lottery、arthas、nedo_export

梯度压测(逐渐增加并发,观察系统的负载,找到系统的临界点)

总线程总数:275

总循环次数:40000次

总样本数:1,040,000

开始压测:MySQL直接报错

问题1:数据库连接异常

引入DBRouter待数据源配置的用master分支的代码(需要在dbrouter的master分支加一个druid依赖否则会报如下错误)

Causedby:java.lang.ClassNotFoundException:com.alibaba.druid.pool.DruidDataSourceatjava.net.URLClassLoader.findClass(URLClassLoader.java:387)~[na:1.8.0_371]atjava.lang.ClassLoader.loadClass(ClassLoader.java:418)~[na:1.8.0_371]atsun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:355)~[na:1.8.0_371]atjava.lang.ClassLoader.loadClass(ClassLoader.java:351)~[na:1.8.0_371]atjava.lang.Class.forName0(NativeMethod)~[na:1.8.0_371]atjava.lang.Class.forName(Class.java:264)~[na:1.8.0_371]atcn.bugstack.middleware.db.router.config.DataSourceAutoConfig.createDataSource(DataSourceAutoConfig.java:103)~[db-router-spring-boot-starter-1.0.2-SNAPSHOT.jar:1.0.2-SNAPSHOT]加入Druid依赖,用的是Master分支代码需要加一个Druid数据源否则启动

在Lottery的父依赖中排除指定依赖

压测2:修改Druid数据源后直接压测

系统负载:1分钟负载2.15分钟负载1.315分钟负载0.7;说明系统可以处理过来系统的负载和CPU的核数有关,对于4核CPU来说当负载大于4就需要介入查看。CPU使用和内存占用不高

每个样本的汇总报告:系统的TPS持续增加

TPS

活动线程数

(1)Jmeter测试计划

(2)样本和线程数

(3)聚合报告

prometheus监控,整个系统资源使用率不高,负载不高IO也不高

TPS:

CPU:利用率很低

压测三改进:

(2)由于操作数据库比较多查询较多,建立字段索引列,加快查询效率

创建联合索引,user_take_activity和user_take_activity_count添加联合索引,activity表可以给activity_id加一个单列索引(数据量较少,暂时看不出效果)

索引执行效果

样本:

RT:

总结:

监控doDrawProcess找到耗时的doPartake方法

监控doPartake方法

优化查询账单接口:将查库操作改为查Redis

修改后的代码:

压测后的结果:RT有所减少TPS有所增加

Arthas返回结果:查询账单接口减少50ms

增加线程数压测

样本数:

聚合报告:TPS平均在1500左右RT平均在472

prometheus监控显示系统1分钟负载已达到5.4说明系统中有大量的排队请求,系统已经请求不过来了,这个时候就需要优化了,因为已经达到系统的瓶颈了,带宽也达到最大值,说明带宽也影响了系统的处理能力,CPU和内存正常

磁盘IO使用率很高、网络带宽不足或延迟造成系统的负载很高但是CPU和内存正常

THE END
1.统计知识数据分析4大段位,你在哪一层?n 即使互联网公司,100人以内的公司也不会专门设置数据分析师,除非是专门做大数据的公司。那么数据需求一般有产品经理,运营人员,或开发人员兼着做数据相关工作。 >100人 100人以上的公司,随着数据需求增加,会专门设置数据部门。数据部门是一个支持部门,完成什https://mp.weixin.qq.com/s?__biz=Mzg4NTM2NTI5Ng==&mid=2247599656&idx=3&sn=655cd5814ab1e32cb68ba80be623ec27&chksm=ceb10e48a3592e1514a9d83f8ff122d7e045dbf6fcc151ebf08f78c508d9b923b45296ebd349&scene=27
2.如何分析各类时长数据?后侵入时间数据集怎么计算服务请求的响应时长 缺陷修复的时长 问题的解决时长 开发响应周期 流动时间 前置时间 故障间隔时间 服务恢复时间 部署时长 无论关注对象是谁,无论度量指标叫什么名字,它的本质就是就是时间的长短,在定义与分析时长的数据时有哪些注意事项呢?我简单归纳如下: 时长https://blog.csdn.net/dylanren/article/details/142988323
3.数据分析常见术语是衡量随机变量或一组数据时离散程度的度量。概率论中方差用来度量随机变量和其数学期望(即均值)之间的偏离程度。统计中的方差(样本方差)是每个样本值与全体样本值的平均数之差的平方值的平均数。在许多实际问题中,研究方差即偏离程度有着重要意义。方差是衡量源数据和期望值相差的度量值。 https://meta.ecnu.edu.cn/76/b3/c35753a423603/page.htm
4.万文长字带你搞懂JTAG的门门道道专业集成电路测试网在板级测试时,可以在模式选择的控制下,构成一条就集成电路边界绕行的移位寄存器链,对板内集成电路的所有引脚进行扫描,通过将测试数据串行输入到该寄存器链的方法,检查发现印刷电路板上的器件焊接故障和板内连接故障,极大地方便了系统电路的调试。IEEE114911标准的推广应用引起测试设备和测试系统的重大变革,边界扫描测试技http://www.ictest8.com/a/Principle/2023/08/JTAG.html
5.连江县教师进修学校附属幼儿园青塘湖分园2022增班教玩具设备及④供应商根据谈判小组的要求,在谈判过程中以纸质方式签署确认并提交的澄清或说明、解决方案、图纸图表以及最后报价等资料均为补充响应文件,谈判小组将此部分内容通过扫描或拍照或数据录入或附件上传等形式提交到电子平台系统,应保持两者内容一致,并作为补充电子响应文件进行评审。相关纸质响应文件应当存档保留,做为监督或核验http://zfcg.fuzhou.gov.cn/upload/document/20220527/10d18bad615b47489e1f887488d9b073.html
6.电脑硬件知识大全(实用)属于损耗品,跟个人喜好有关系,相对没有什么技术含量。 以上就是电脑硬件的组成部分,对于想学习电脑硬件的朋友,可以详细看看小编整理的电脑硬件知识。 电脑硬件知识大全2 主板就是个平台,把CPU,内存,显卡,硬盘,光驱通过数据线或者直接安装来组成一个工作整体。CPU相当于人的大脑,发出各种指令来协调各个部分的工作,内存https://www.oh100.com/peixun/yingjianweihu/478103.html
7.MySQL查询数据库响应时长详解作为一名测试工程师,在性能测试中,查询数据库的响应时长是一个重要指标。MySQL 提供了多种方法来监控和优化查询性能。本文将详细介绍如何使用 MySQL 的内置功能和工具来查询数据库响应时长,并分享一些性能优化的技巧。 启用查询日志 开启慢查询日志 慢查询日志用于记录执行时间超过指定阈值的 SQL 查询,默认情况下是关闭https://maimai.cn/article/detail?fid=1836927138&efid=7muk2UZMSVXehhdkgB8kcQ
8.CISSP:错题汇总D.当传输未正确加密时保密性违反可能发生javascript:void(null) 2:STRIDE通常用于评估针对应用程序或操作系统的威胁有关,下列哪一项不包括STRIDE元素? D A.欺骗 B.权限提升 C.否认 D.披露 解析:信息披露 不等于披露 3:下列哪一项是机密数据的最低军事数据分类 B https://www.jianshu.com/p/d216171e7d2e
9.最全的前端性能定位总结全栈前端精选长任务(Long Task) :当一个任务执行时间超过 50ms 时消耗到的任务 (50ms 阈值是从 RAIL 模型总结出来的结论,这个是 google 研究用户感知得出的结论,类似用户的感知/耐心的阈值,超过这个阈值的任务,用户会感知到页面的卡顿) TTI (Time To Internative) :从页面开始到它的主要子资源加载到能够快速地响应用户输入https://www.shangyexinzhi.com/article/4580576.html
10.抖店App上线客服数据透传快捷短语功能客服数据透传是飞鸽在【抖店App-接待】页展示了首次响应时长、平均响应时长、3分钟回复率(会话)、不满意率的实时数据,客服可以在抖店App上随时查看客服数据并且接收数据警示,帮助客服实时评估回复效率,快速响应买家进线! 根据《商家体验分规范》规定,飞鸽IM客服系统的近90天人工客服会话量中,每天8-23点,3分钟人工https://school.jinritemai.com/doudian/wap/article/aHWrB32aEzDM
11.DataWorks阿里云现在的api接口响应时长有标准规范吗?问答在阿里云 DataWorks 中,API 接口的响应时长是有标准规范的。一般来说,API 接口的响应时长应该在数百毫秒以内,具体时间取决于接口的复杂度、数据量大小、网络延迟等因素。在运行过程中,如果接口的响应时长超过了正常范围,可能会影响用户的使用体验和数据处理效率。为了确保 API 接口的响应时长符合标准规范,阿里云 Datahttps://developer.aliyun.com/ask/531136
12.抖音商家要如何解读客服分析看板数据?抖音的客服分析看板支持商家查看最新客服水平概况,筛选时间段查看近期趋势,具体指标包括:三分钟平均回复率、接起率、平均响应时长、平均等待时长等客服效率指标,用户咨询量、转人工接待量、人工已接待量等客服量指标,客服销售额及满意率等用户指标。商家可实时监控以上关键数据指标判断当前客服水平,及时监控指标变化趋势来https://www.shuaishou.com/school/infos55035.html
13.第2章运行时问题(SunManagementCenter4.0发行说明)当被监视代理的数量很多(比如说超过 100)且性能数据也很多时,生成最近七天数据的报告会花费很长时间。七天时限是指数据库中保存最小细节级别的历史数据的日期到当前日期的时间段。最小的细节级别是小时。所以,该报告需要数据库来检索最大量的数据。数据大小会随着所请求的数据属性数量的增多而增加。八天给数据库带来https://docs.oracle.com/cd/E19957-01/820-3709/6nf7n3qbc/index.html
14.Nginx缓存详解(二)之服务端缓存腾讯云开发者社区proxy cache属于服务端缓存,主要实现 nginx服务器对客户端数据请求的快速响应。nginx 服务器在接收到被代理服务器的响应数据之后,一方面将数据传递给客户端,另一方面根据proxy cache的配置将这些数据缓存到本地硬盘上。当客户端再次访问相同的数据时,nginx服务器直接从硬盘检索到相应的数据返回给用户,从而减少与被代理服务https://cloud.tencent.com/developer/article/1825465
15.架构必看:12306抢票亿级流量架构演进(图解+秒懂+史上最全)放票时 高并发的下单集中在一起,形成请求高峰(类似于秒杀),请求导致订单 / 电子客 票数据库负载过高,引起交易响应时间过长,造成 AS 以及 inetis 的交易线程池拥堵。 下单长时间不响应,同一次购买,用户会反复重试,从而加剧拥堵。 由于响应时间过程,用户进而反复重试,一次操作变成多次,操作此时倍数增长,进一步 造成https://blog.51cto.com/u_15127678/4565654