【高并发】- 生产级系统搭建 - 4

news2024/11/15 13:55:23

前言

    关于高并发系统中,当前比较热门的还是属于“秒杀”系统,前面章节在整理了“秒杀”系统的相关设计概念后,本章节,来讲解扣减库存相关的业务逻辑。

1 库存的那些事

    一般电商网站中,购买流程一般都是这样的:商品列表页看重某个商品,然后进入详情页浏览商品详细信息,有购买意向后,单击“支付”按钮(或者将商品加入购物车,从购物车进行结算),网站弹出支付方式让用户进行选择支付方式,并进行支付。

    对于这样的购买流程,用户在下单时,一般不需要关心库存的,只有没有库存了,用户才会感到没有库存了。但是在高并发场景中,这样的购买流程就会出现问题。例如,在“秒杀”活动中,用户会争抢库存,如果没有控制好,则会出现“超卖”的情况。会给公司造成损失。

(对于“秒杀”活动,一般公司是不允许商品“超卖”的,即【下单成功的数量】不能大于【商品库存数量】。一旦出现“超卖”,公司则会出现损失。如果被恶意流量利用,则损失可能是巨大的。)

1.1 扣减库存方式

    库存对于电商平台来说,是一个重要的业务指标,所以在技术上需要合理设计扣减库存,不能出现“超卖”的情况。

一般扣减库存常有以下3种方式:

  • 下单后扣减库存:用户在下单后就扣减库存,这种扣减方式最简单,也最好理解。但是问题是,可能有用户下单后不付款,特别是竞争对手利用“秒杀器”大量抢购商品,但是不支付。如果是这样,那商家就没有达到活动的真正目的,且真正想得到商品的用户也无法得到低价商品。

  • 支付后扣减库存:在用户付完款后再扣减库存,这样可以解决用户“下单但不支付”的情况。但是这种方式也有问题:会发生【超卖】情况。因为,在瞬时洪峰流量下,会有很多用户付款成功,但是只有一小部分用户能真正抢到商品,大部分用户在付完款后系统会报“已售罄”或“活动结束”等。

(对于“支付后扣减库存”这种方式,当出现库存不足时,有些商家是可以后续再补货的)

  • 预扣减库存:在用户下完订单后,系统会为其锁定库存一段时间,例如30分钟;在超过锁定时间后,会自动释放锁定的库存,让其他用户抢购。当用户付款时,系统会校验库存是否在锁定有效期内,如果在有效期内,则可以进行支付;如果锁定有效期已过,则重新锁定库存,若锁定失败则报“库存不足”的提醒。

(在用户下单后,有些平台会有一个支付时间的倒计时。例如12306网站,会有一个30分钟的有效支付时间,这种扣减库存方式相当于“预扣减库存”方式。)

1.2 在千万级流量的“秒杀”中,如何扣减库存?

    上面了解到,有三种扣减库存方式:下单后扣减库存、支付后扣减库存 以及 预扣减库存。对于“秒杀”业务,应当如何选择扣减库存的方式呢?

    由于在“秒杀”场景中,商品一般对用户具有很强的吸引力,所以,在这种场景中使用“下单后扣减库存”方式更为合适。

(在“秒杀”场景中,大部分用户抱着“抢到就是赚到”的想法,一般都会付款,但是如果真的有竞争对手恶意下单不付款,应该怎么办?前面在流量管控中已经说到,可以对请求日志进行实时分析,让风控系统选择出恶意用户,然后将其封停。)

    因此,对于“下单后扣减库存”这种方式,利用数据库的事物特性,可以保证订单和库存扣减数量的一致性。

    下面来分析该如何去做好“下单后扣减库存”,防止商品被“超卖”。

(1)将某个商品的库存数量查询出来:

select num from stock where prod_id = $prod_id

(2)更新库存。用【库存数量】减去【购买的商品数量】,然后将结果值更新到库存数据库中。例如,商品库存数量为10,之后用户购买了2件,则d得到的结果值是:10 - 2 = 8,只需要将 8 更新为最新的库存数量即可。

问题:为什么是更新“结果值”的操作,而不是直接更新“扣减”的操作呢?

回答:因为,“扣减”不是幂等的,如果接口设计的不够完善,没有考虑到幂等性,那么在由于网络原因或者其他原因重试后,会出现重复“扣减”,即会出现“超卖”,甚至库存为负值的情况。

    通过上面两步的处理,基本可以保证下单扣减库存的准确性,但是对于“秒杀”这样的高并发场景来说这样还是有风险的。例如,在大流量、高并发下,有两个用户同时抢购,都拿到了库存数量为10的商品,其中一个用户购买了5件商品,随后更新库存数量为:10 - 5 = 5 件;接着另外一个请求购买了3件商品,随后更新库存数量为:10 - 3 = 7件。

(在高并发场景中,有可能出现并发更新数据不一致的情况,对于上图的两次请求,正常来讲应该卖出8件商品,但是现在却卖出了3件商品,因为update set动作覆盖了之前的数据。)

    在更新库存数量时,需要将【当前库存数量】与【之前的库存数量】进行对比:

update stock set num = $new_num where prod_id = $prod_id and num = $old num

    有了这种对比,在并发更新时,用户A和用户B只有在更新提交前查询到的库存数量为10,才能成功更新库存数量。

但是,在这种并发场景中,如果没有进行对比,则会出现以下问题:

  • 开始库存数量为10,第一个用户更新库存数量是成功的。

  • 在第一个用户更新完库存数量后,库存数量变成了5,所以,这时另一个请求是不能扣减成功的,在代码中会提示更新失败或者提示用户扣减库存失败的提示。

1.3 在千万级流量的“秒杀”中,优化库存数量扣减方案

    在“秒杀”场景中,通过流量分层控制可以分层管控大量的“读”请求。但是,依然会有很大的流量进入真正的下单罗技。对于这么大的的流量,除了前面说的数据库个例外,还需要进一步优化库存数量,否则数据库读/写依然是系统的瓶颈。

(1)利用好缓存。

    在“秒杀”场景中,如果只是一个扣减库存数量这样简单的流程,则可以先将库存数量直接放在缓存中,然后利用分布式缓存(如Redis)去应对这种瞬时流量洪峰下的系统挑战。

ps:使用缓存是存在一定风险的,例如,缓存节点出现异常,那库存数量应该怎么计算?使用缓存不仅要考虑分布式缓存高可用,还要考虑各种限流容错机制,以确保分布式缓存对外提供服务。

(2)异步处理。

    如果是复杂的扣减库存(如涉及商品信息本身或者牵连其他系统),则建议使用数据库进行库存数量的扣减,可以使用异步的方式来应对这种高并发的库存数量更新。

  • 在用户下单时,不like生成订单,而是将所有订单依次放入队列。

  • 下单模块依据自身处理速度,从队列中依次获取订单进行“下单扣减库存”的操作。

  • 在订单生成成功后,用户即可进行支付操作了。

    这种方式是针对“秒杀”场景的,依据“先到先得”的原则来保证公平公正,所有用户都可以抢购,然后等待订单处理,最后生成订单(如果库存不足,则生成订单失败)。这样的逻辑,对于用户来说体验感不是很差。具体排队逻辑如图:

(对于用户来说,只需要在商品活动详情页中提交一次抢购请求,之后就是等待系统处理进度。当然,这个等待时间是要设计的,不要让用户等待太久的时间,不管成功或者失败。)

    上面介绍了千万级流量“秒杀”系统的基本架构、“秒杀”系统的设计原则、如何做动静分离方案和流量控制,以及扣减库存方案的内容。这些都是设计高并发“秒杀”系统必须要考虑的。

    “秒杀”系统的流程并不复杂,只是一个“下单扣减库存”的动作,但是由于其具有独特的业务特点,所以在进行系统设计时千万不能大意。对于瞬时流量洪峰的高并发“秒杀”系统,我们可以总结一下:

(1)数据的静态化技术,用来应对高并发读的请求。

  • 各层级缓存的处理(即多级缓存的技术)。

  • 分布式缓存技术。

(2)负载均衡反向代理技术。

  • LVS。

  • Nginx。

(3)异步处理技术。

  • 消息队列技术。

  • 排队系统技术。

(4)系统架构设计技术。

  • 系统模块化划分。

  • 微服务架构思想。

(5)系统监控技术。

  • 日志监控。

  • 服务监控。

    本章节主要讲解了库存扣减相关设计经验,在面对库存扣减这一业务,不能大意,需要认真进行系统设计、业务设计,选择合理的方案来解决库存扣减的场景。以及在最后进行了一个简单的前面章节的统一汇总,希望小伙伴们能够及时回顾前面章节内容。

    下一章节会针对系统交互过程中的服务通信设计进行讲解。希望大家能够分享公众号给身边的小伙伴,大家一起来学习

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/187528.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

多线程之Callable接口、ReentrantLock、信号量 Semaphore以及CountDownLatch

目录:一、Callable接口Callable的用法小结二、ReentrantLockReentrantLock 的用法ReentrantLock 和 synchronized 的区别?为什么有了 synchronized 还需要 juc(java.util.concurrent) 下的 lock?三、信号量 Semaphore如何理解信号量&#xff…

Python接口测试实战4(下) - 框架完善:用例基类,用例标签,重新运行上次失败用例

本节内容使用用例基类自定义TestSuitecollect-only的实现testlist的实现用例tags的实现rerun-fails的实现命令行参数的使用更简单的用例编写使用用例基类因为每条用例都需要从excel中读取数据,解析数据,发送请求,断言响应结果,我们…

阿里云ECS学习笔记1

ECS:弹性计算服务。CPU可以热插、内存可变大变小、硬盘可以增加~ 注册: 在企业中,应该以企业的身份进行注册,而不是以个人身份进行注册。 手机号:行政部门专门管理注册的账号资源的,而不使用个人或者老板…

【可解释性机器学习】解释基于XGBoost对泰坦尼克号数据集的预测过程和结果

解释基于XGBoost对泰坦尼克号数据集的预测过程和结果1. 训练数据2. 简单的 XGBoost 分类器3. 解释重量4. 解释预测5. 添加文本特性参考资料本文介绍如何分析XGBoost分类器的预测( eli5也支持 XGBoost和大多数 scikit-learn树集成的回归)。 我们将使用 Ti…

【数据结构】8.5 归并排序

文章目录相邻两个有序子序列的归并归并排序算法归并排序算法分析基本思想 将两个或两个以上的有序子序列归并为一个有序序列。在内部排序中,通常采用的是2-路归并排序。 即:将两个位置相邻的有序子序列 R[l…m] 和 R[m1…n] 归并为一个有序序列 R[l…n]…

1个寒假能学会多少网络安全技能?

现在可以看到很多标题都声称三个月内就可以转行网络安全领域,并且成为月入15K的网络工程师。那么,这个寒假的时间能学多少网络安全知识?是否能入门网络安全工程师呢? 答案是肯定的。 虽然网络完全知识是一门广泛的学科&#xff…

在线支付系列【9】微信支付之申请微信公众号

有道无术,术尚可求,有术无道,止于术。 文章目录前言申请微信公众号前言 由于微信支付的产品体系全部搭载于微信的社交体系之上,所以直连商户或服务商接入微信支付之前,都需要有一个微信社交载体,该载体对应…

天啦撸~ChatGPT通过国际软件测试工程师(ISTQB)认证了~

天啦撸!目前最火的AI应用ChatGPT通过ISTQB认证了~ 近期,国外的一位工程师,放出了他用ChatGPT通过认证的相关信息。 ChatGPT相信大家都知道是什么了,ISTQB相信很多测试小伙伴也不陌生,而且很多考证的小伙伴也对此梦寐以…

Linux之网络性能测试工具netperf实践

一、netperf简介 Netperf是一种网络性能的测量工具,主要针对基于TCP或UDP的传输。Netperf根据应用的不同,可以进行不同模式的网络性能测试,即批量数据传输(bulk data transfer)模式和请求/应答(request/rep…

公司通知要大裁员,hr太强势,和所有人吵起来,老板见势不妙,不得不答应大家要求,把HR一起裁掉了!...

在裁员中,hr一般都会代表老板的利益和员工对抗,但如果hr和员工闹翻了,老板会维护hr吗?一位网友说:一上班就收到消息要裁员,立马让报上名单面谈,锁电脑关权限。后面那些人面谈的时候吵起来了&…

OpenAI Chatgpt注册及使用教程

零、什么是chatgpt?​ 1、简介 ChatGPT(Chat Generative Pre-trained Transformer)是OpenAI于 2022 年 11 月推出的聊天机器人。它建立在 OpenAI 的GPT-3大型语言模型家族之上,并经过微调(一种迁移学习的方法)…

双点双向的ISIS与OSPF、OSPF与OSPF、ISIS与ISIS环境以路由策略解决(1tag、2tag、4tag介绍与配置)

3.1.1 双点双向的ISIS与OSPF、OSPF与OSPF、ISIS与ISIS环境以路由策略解决(1tag、2tag、4tag介绍与配置) OSPF与ISIS双点双向 次优的产生与解决: 由于OSPF引入外部路由之后其优先级为150,再由ASBR进行双向引入之后。 原先OSPF外部…

闲鱼自动化软件——筛选/发送系统 V20已经测试完毕

做程序,就是不断地改,不断地优化。当改动达到一定程序,已经和前面形成断代,程序的升级时刻便到了。V20做了哪些更改或优化。1。优化抓取:在抓取环境优化参数,使抓取更顺滑,抓取数据效果上更准确…

智能家居创意DIY-Homekit智能灯

一、什么是智能灯 传统的灯泡是通过手动打开和关闭开关来工作。有时,它们可以通过声控、触控、红外等方式进行控制,或者带有调光开关,让用户调暗或调亮灯光。 智能灯泡内置有芯片和通信模块,可与手机、家庭智能助手、或其他智能…

若依-excel预览功能实现

实现效果及源码 实现效果如下图所示: 实现思路: 1.动态表格:定义表头数组,表格遍历表头生成表格列 2.读取excel文件内容,封装表头,绑定表格数据 代码修改 首先参考若依官网,先实现excel导入功…

C++基础——C++ 字符串

C基础——C 字符串C 字符串C 风格字符串C 中的 String 类C 字符串 C 提供了以下两种类型的字符串表示形式: C 风格字符串C 引入的 string 类类型 C 风格字符串 C 风格的字符串起源于 C 语言,并在 C 中继续得到支持。字符串实际上是使用 null 字符 ‘…

126、【回溯算法】leetcode ——332. 重新安排行程:回溯算法(C++版本)

题目描述 原题链接:332. 重新安排行程 解题思路 本题要解决的问题: 需要构建起始与目的机场的映射关系;每次选择目的机场时,需要选择当前最小字母顺序的机场;从“JFK”之后依次飞往,并且可能会有多条路径…

58同城AI Lab在WeNet中开源Efficient Conformer模型

2022年8月,58同城TEG-AI Lab语音技术团队完成了WeNet端到端语音识别的大规模落地,替换了此前基于Kaldi的系统,并针对业务需求对识别效果和推理速度展开优化,取得了优异的效果,当前录音文件识别引擎处理语音时长达1000万…

非标设备ERP管理系统可以帮助企业解决哪些管理难题?

多品种、小批量、交货周期短、非标准化生产是大多数非标设备制造企业共同的特性,这就要求非标设备制造企业应具备足够的经营、技术、生产和管理力量,否则就会顾此失彼,产品质量难以得到保证。非标设备制造企业常见的管理难题(1&am…

DynaSLAM-2 DynaSLAM中Mask R-CNN部分源码解析(Ⅰ)

目录 1.Mask R-CNN源码地址 2.Mask R-CNN效果 3.项目配置 4.源码使用 1.Mask R-CNN源码地址 Mask R-CNN源码地址https://github.com/matterport/Mask_RCNN/releases 这里我们拿Mask R-CNN2.1版本进行讲解。 2.Mask R-CNN效果 最传统最核心的功能就是物体检测了…