大型秒杀中如何减库存?JAVA 架构知识

目前来看,业务系统中最常见的就是预扣库存方案,像你在买机票、买电影票时,下单后一般都有个“有效付款时间”,超过这个时间订单自动释放,这都是典型的预扣库存方案。而具体到秒杀这个场景,应该采用哪种方案比较好呢?


由于参加秒杀的商品,一般都是“抢到就是赚到”,所以成功下单后却不付款的情况比较少,再加上
卖家对秒杀商品的库存有严格限制,所以秒杀商品采用“下单减库存”更加合理。另外,理论上由于
“下单减库存”比“预扣库存”以及涉及第三方支付的“付款减库存”在逻辑上更为简单,所以性能
上更占优势。


“下单减库存”在数据一致性上,主要就是保证大并发请求时库存数据不能为负数,也就是要保证数
据库中的库存字段值不能为负数,一般我们有多种解决方案:一种是在应用程序中通过事务来判断,即保证减后库存不能为负数,否则就回滚;另一种办法是直接设置数据库的字段数据为无符号整数,这样减后库存字段值小于零时会直接执行 SQL 语句来报错;再有一种就是使用 CASE WHEN 判断语句,例如这样的 SQL 语句:
 

UPDATE item SET inventory = CASE WHEN inventory >= xxx THEN inventory-xxx ELSE inventory
秒杀减库存的极致优化

在交易环节中,“库存”是个关键数据,也是个热点数据,因为交易的各个环节中都可能涉及对库存
的查询。但是,我在前面介绍分层过滤时提到过,秒杀中并不需要对库存有精确的一致性读,把库存数据放到缓存(Cache)中,可以大大提升读性能。


解决大并发读问题,可以采用 LocalCache(即在秒杀系统的单机上缓存商品相关的数据)和对数据进行分层过滤的方式,但是像减库存这种大并发写无论如何还是避免不了,这也是秒杀场景为心
的一个技术难题。

因此,这里我想专门来说一下秒杀场景下减库存的极致优化思路,包括如何在缓存中减库存以及如何在数据库中减库存。

秒杀商品和普通商品的减库存还是有些差异的,例如商品数量比较少,交易时间段也比较短,因此这里有一个大胆的假设,即能否把秒杀商品减库存直接放到缓存系统中实现,也就是直接在缓存中减库存或者在一个带有持久化功能的缓存系统(如 Redis)中完成呢?

如果你的秒杀商品的减库存逻辑非常单一,比如没有复杂的 SKU 库存和总库存这种联动关系的话,我觉得完全可以。但是如果有比较复杂的减库存逻辑,或者需要使用事务,你还是必须在数据库中完成减库存。

由于 MySQL 存储数据的特点,同一数据在数据库里肯定是一行存储(MySQL),因此会有大量线程来竞争 InnoDB 行锁,而并发度越高时等待线程会越多,TPS(Transaction Per Second,即每秒处理的消息数)会下降,响应时间(RT)会上升,数据库的吞吐量就会严重受影响。

这就可能引发一个问题,就是单个热点商品会影响整个数据库的性能, 导致 0.01% 的商品影响
99.99% 的商品的售卖,这是我们不愿意看到的情况。一个解决思路是遵循前面介绍的原则进行隔离,把热点商品放到单独的热点库中。但是这无疑会带来维护上的麻烦,比如要做热点数据的动态迁移以及单独的数据库等。

而分离热点商品到单独的数据库还是没有解决并发锁的问题,我们应该怎么办呢?要解决并发锁的问
题,有两种办法:
应用层做排队。按照商品维度设置队列顺序执行,这样能减少同一台机器对数据库同一行记录进行
操作的并发度,同时也能控制单个商品占用数据库连接的数量,防止热点商品占用太多的数据库连
接。

数据库层做排队。应用层只能做到单机的排队,但是应用机器数本身很多,这种排队方式控制并发
的能力仍然有限,所以如果能在数据库层做全局排队是最理想的。阿里的数据库团队开发了针对这种
MySQL 的 InnoDB 层上的补丁程序(patch),可以在数据库层上对单行记录做到并发排队。
你可能有疑问了,排队和锁竞争不都是要等待吗,有啥区别?

如果熟悉 MySQL 的话,你会知道 InnoDB 内部的死锁检测,以及 MySQL Server 和 InnoDB 的切换会比较消耗性能,淘宝的 MySQL 核心团队还做了很多其他方面的优化,如 COMMIT_ON_SUCCESS和 ROLLBACK_ON_FAIL 的补丁程序,配合在 SQL 里面加提示(hint),在事务里不需要等待应用层提交(COMMIT),而在数据执行完最后一条 SQL 后,直接根据 TARGET_AFFECT_ROW 的结果进行提交或回滚,可以减少网络等待时间(平均约 0.7ms)。据我所知,目前阿里 MySQL 团队已经将包含这些补丁程序的 MySQL 开源。

另外,数据更新问题除了前面介绍的热点隔离和排队处理之外,还有些场景(如对商品的
lastmodifytime 字段的)更新会非常频繁,在某些场景下这些多条 SQL 是可以合并的,一定时间内只要执行最后一条 SQL 就行了,以便减少对数据库的更新操作。

总结一下
今天,我围绕商品减库存的场景,介绍了减库存的三种实现方案,以及分别存在的问题和可能的缓解办法。最后,我又聚焦秒杀这个场景说了如何实现减库存,以及在这个场景下做到极致优化的一些思路。

当然减库存还有很多细节问题,例如预扣的库存超时后如何进行库存回补,再比如目前都是第三方支付,如何在付款时保证减库存和成功付款时的状态一致性,这些都是很大的挑战。

图  alisql 排队减库存示例。

UPDATE COMMIT_ON_SUCCESS ROLLBACK_ON_FAIL QUEUE_ON_PK 1 TARGET_AFFECT_ROW 1 traffic_0 SET day_limit=day_limit+1 WHERE id = 1507594451815100442

------------------------------------------------------------------------------------------------------------ 

还有很多就不一一介绍了。下面是整理的一些面试题大纲,需要的来领取。

------------------------------------------------------------------------------------------------- 

 链接:https://pan.baidu.com/s/1KmlUj81iMT3KbxBheSEYcA?pwd=pkju 
提取码:pkju 

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【GAMES101】Lecture 19 相机

目录 相机 视场 Field of View (FOV) 曝光(Exposure) 感光度(ISO) 光圈 快门 相机 成像可以通过我们之前学过的光栅化成像和光线追踪成像来渲染合成,也可以用相机拍摄成像 今天就来学习一下相机是如何成像的…

vue3+vite+ts 配置commit强制码提交规范配置 commitlint

配置 git 提交时的 commit 信息,统一提交 git 提交规范 安装命令: npm install -g commitizen npm i cz-customizable npm i commitlint/config-conventional commitlint/cli -D 文件配置 根路径创建文件 commitlint.config.js module.exports {// 继承的规…

亚马逊认证考试系列 - 知识点 - 安全组介绍

第一部分:AWS简介 Amazon Web Services(AWS)是全球领先的云计算服务提供商,为个人、企业和政府机构提供广泛的云服务解决方案。AWS的服务包括计算、存储、数据库、分析、机器学习、人工智能、物联网、安全和企业应用等领域。AW…

Go 中如何检查文件是否存在?可能产生竞态条件?

嗨,大家好!本文是系列文章 Go 技巧第十三篇,系列文章查看:Go 语言技巧。 Go 中如何检查文件是否存在呢? 如果你用的是 Python,可通过标准库中 os.path.exists 函数实现。遗憾的是,Go 标准库没有…

《Python 网络爬虫简易速速上手小册》第2章:网络爬虫准备工作(2024 最新版)

文章目录 2.1 选择合适的爬虫工具和库2.1.1 重点基础知识讲解2.1.2 重点案例:使用 Scrapy 抓取电商网站2.1.3 拓展案例 1:使用 Requests 和 BeautifulSoup 抓取博客文章2.1.4 拓展案例 2:使用 Selenium 抓取动态内容 2.2 设置开发环境2.2.1 重…

python+flask人口普查数据的应用研究及实现django

作为一款人口普查数据的应用研究及实现,面向的是大多数学者,软件的界面设计简洁清晰,用户可轻松掌握使用技巧。在调查之后,获得用户以下需求: (1)用户注册登录后,可进入系统解锁更多…

Backtrader 文档学习- Plotting

Backtrader 文档学习- Plotting 虽然回测是一个基于数学计算的自动化过程,还是希望实际通过可视化验证。无论是使用现有算法回测,还是观察数据驱动的指标(内置或自定义)。 凡事都要有人完成,绘制数据加载、指标、操作…

CISCRISC? CPU架构有哪些? x86 ARM?

编者按:鉴于笔者水平有限,文中难免有不当之处,还请各位读者海涵。 是为序 我猜,常年混迹CSDN的同学应该不会没听说过CPU吧? 但你真的了解CPU吗?那笔者问你CPU有哪些架构呢? 如果你对你的答案…

《游戏引擎架构》 -- 学习2

声明,定义,以及链接规范 翻译单元 声明与定义 链接规范 C/C 内存布局 可执行映像 程序堆栈 动态分配的堆 对象的内存布局 kilobyte 和 kibibyte 流水线缓存以及优化 未完待续。。。

基于区块链/Hyperledger Fabric的商品交易溯源系统搭建步骤

欢迎订阅:《Fabric项目学习笔记》专栏 最新更新:订阅《Fabric项目学习笔记》用户群内包含商品溯源代码讲解与前后端开发模式演示的视频教程。 原项目链接:https://github.com/togettoyou/fabric-realty 此项目链接:https://gitee…

电商小程序04实现登录逻辑

目录 1 创建自定义方法2 获取用户名和密码3 验证用户是否同意协议4 验证用户名和密码总结 上一篇我们实现了登录功能的前端界面,这一篇实现一下登录的具体逻辑。 1 创建自定义方法 一般如果页面点击按钮需要有事件响应的,我们用自定义方法来实现。打开我…

opencv中使用cuda加速图像处理

opencv大多数只使用到了cpu的版本,实际上对于复杂的图像处理过程用cuda(特别是高分辨率的图像)可能会有加速效果。是否需要使用cuda需要思考: 1、opencv的cuda库是否提供了想要的算子。在CUDA-accelerated Computer Vision你可以…

百面嵌入式专栏(面试题)C语言面试题22道

沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇我们将介绍C语言相关面试题 。 宏定义是在编译的哪个阶段被处理的?答案:宏定义是在编译预处理阶段被处理的。 解读:编译预处理:头文件包含、宏替换、条件编译、去除注释、添加行号。 写一个“标准”宏MIN,这个…

Hexo更换Matery主题

引言 在数字化时代,拥有一个个人博客已经成为许多人展示自己技能、分享知识和与世界互动的重要方式。而在众多博客平台中,Hexo因其简洁、高效和易于定制的特点而备受青睐。本文将详细介绍如何为你的Hexo博客更换主题,让你的个人博客在互联网…

华为 Huawei 交换机 黑洞MAC地址的作用和配置示例

黑洞mac作用:某交换机上配置某个PC的mac地址为黑洞mac,那么这台PC发出来的包都会被交换机丢弃,不会被转发到网络中。 组网需求: 如 图 2-13 所示,交换机 Switch 收到一个非法用户的访问,非法用户的 MAC 地址…

node网站 宝塔 面板配置 防止刷新404

1.问题 我现在配置了一个网站 后台项目 放到了宝塔上 将相应的域名和项目都配置好了 域名也可以访问 但是有的时候 出现了404 类似这种404 这个资源找不到 2.说明 其实这个问题的原因是nginx 的问题 反向代理的原因 3.解决 在这个配置文件中 有个配置文件 # 防止刷新404l…

从中序与后序遍历序列构造二叉树

给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。 示例 1: 输入:inorder [9,3,15,20,7], postorder [9,15,7,20,3] 输出:[3…

[Java][算法 双指针]Day 02---LeetCode 热题 100---04~07

LeetCode 热题 100---04~07 第一题:移动零 思路 找到每一个为0的元素 然后移到数组的最后 但是需要注意的是 要在给定的数组原地进行修改 并且其他非零元素的相对顺序不能改变 我们采用双指针法 定义两个指针i和j i和j一开始分别都在0索引位置 然后判断j所…

MATLAB环境下基于深层小波时间散射网络的ECG信号分类

2012年,法国工程学院院士Mallat教授深受深度学习结构框架思想的启发,提出了基于小波变换的小波时间散射网络,并以此构造了小波时间散射网络。 小波时间散射网络的结构类似于深度卷积神经网络,不同的是其滤波器是预先确定好的小波…

熔断机制解析:如何用Hystrix保障微服务的稳定性

微服务与系统的弹性设计 大家好,我是小黑,在讲Hystrix之前,咱们得先聊聊微服务架构。想象一下,你把一个大型应用拆成一堆小应用,每个都负责一部分功能,这就是微服务。这样做的好处是显而易见的,更新快,容错性强,每个服务可以独立部署,挺美的对吧?但是,问题也随之而…